Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add [Symbol.toStringTag] property to all interfaces #1699

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

jdufresne
Copy link

Fixes #1641

Copy link
Contributor

Thanks for the PR!

This section of the codebase is owned by @saschanaz - if they write a comment saying "LGTM" then it will be merged.

@jdufresne
Copy link
Author

I made an attempt but I'm hoping to receive a bit guidance and early feedback on the approach and how to proceed. Running tests results in errors that look like:

generated/dom.generated.d.ts(28925,18): error TS1169: A computed property name in an interface must refer to an expression whose type is a literal type or a 'unique symbol' type.
generated/dom.generated.d.ts(28925,19): error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the 'lib' compiler option to es2015 or later.

I'm not sure how to reconcile it.

Copy link
Contributor

@saschanaz saschanaz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are already going in the right direction! One problem is that, as the error message says, Symbols are ES2015+ while dom.generated.d.ts needs to be ES5-compatible as of now. We probably need another set of files e.g. *.stringtag.d.ts just like *.iterable.d.ts.

@jdufresne
Copy link
Author

@microsoft-github-policy-service agree

@jdufresne jdufresne marked this pull request as ready for review March 24, 2024 14:28
@jdufresne
Copy link
Author

Thanks for the feedback. I took your advice and tried to follow the existing iterable pattern.

Copy link
Contributor

@saschanaz saschanaz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally nice!

@@ -135,7 +135,7 @@ function isEventHandler(p: Browser.Property) {
export function emitWebIdl(
webidl: Browser.WebIdl,
global: string,
iterator: "" | "sync" | "async",
flavor: "" | "sync" | "async" | "toStringTag",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sync/async is now confusing in this case, maybe iterator/asyncIterator?


const interfaces = getElements(webidl.interfaces, "interface");
interfaces.sort(compareName).forEach((i) => {
if (!i.noInterfaceObject && !i.namespace && !i.extends && !i.implements) {
Copy link
Contributor

@saschanaz saschanaz Mar 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get i.extends as it'll be inherited from parent interface, but why other checks? BTW we do need to filter out i.legacyNamespace and emit it inside a namespace, see also:

collectLegacyNamespaceTypes(webidl).forEach(emitNamespace);

Copy link
Contributor

@saschanaz saschanaz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the long silence, this looks nice. cc @sandersn for further opinion from TS team as this introduces a new set of files.

readonly: true,
comment:
"The well-known symbol @@toStringTag.\n\n" +
"[MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toStringTag)",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is causing quite some size in the generated file, but I think the doc should be in the Symbol.toStringTag rather than in the function. IDEs probably won't be able to show the comment for functions named with symbols anyway.

So I think it's better to not have this comment.

@sandersn
Copy link
Member

I don't much like the implementation since it requires so many new files. Also, I don't understand how this is useful to anybody. It's not a property that you need to refer to directly, is it?

Following the links in the original bug and skimming through them, it seems like there's some complex assignability problems without this property. Would it be possible to fix those in a simpler way (or stop using this property entirely -- I don't think it's meant for instanceof checks in the first place).

@saschanaz I skimmed the webidl spec discussion but couldn't find a definitive place that says that these are part of the DOM. How important do you think it is for spec compliance to have them here?

@saschanaz
Copy link
Contributor

@saschanaz I skimmed the webidl spec discussion but couldn't find a definitive place that says that these are part of the DOM. How important do you think it is for spec compliance to have them here?

By DOM I guess you meant Web Platform? Anything in Web IDL spec is part of Web Platform in that case, otherwise it won't be there.

About the size, given that the new files are pretty much duplicated with same symbolic member definitions, perhaps there can be an empty interface WebIDLInterface {} that extends every interface definition in es5 lib and then es6 lib - well, dom.iterable.d.ts - can add a member on it`. Then we don't have to add new files.

@saschanaz
Copy link
Contributor

About how important, I think it's pretty much edge case to use this at all, so maybe not too much worth extra effort 🤔

const iterators = emitWebIdl(exposed, options.global[0], "sync");
const toStringTag = emitWebIdl(exposed, options.global[0], "toStringTag");
await fs.writeFile(
new URL(`${options.name}.tostringtag.d.ts`, options.outputFolder),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
new URL(`${options.name}.tostringtag.d.ts`, options.outputFolder),
new URL(`${options.name}.tostringtag.generated.d.ts`, options.outputFolder),

@jdufresne
Copy link
Author

Just a heads up. I'm not actively working on this at the moment. If someone would like to pick up the remaining work to take it over the finish line, that is welcome.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Symbol.toStringTag is missing on File, Blob and FormData
4 participants