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

Fix mixins, stringifiers, and static attributes #68

Merged
merged 4 commits into from
Sep 12, 2017

Conversation

TimothyGu
Copy link
Member

@TimothyGu TimothyGu commented Sep 6, 2017

This requires a change in jsdom to move idlUtils.mixin to jsdom, as it will no longer be needed or included in webidl2js. I could keep it in webidl2js for the time being however, until the next major bump.

Note, this does not yet fix #55

Fixes #49.
Fixes #67.

Copy link
Member

@domenic domenic left a comment

Choose a reason for hiding this comment

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

Overall looks good; a few suggestions and nits.

What does "Refactor Overloads operation collection" accomplish? (E.g., what would happen with that test case before?)

@@ -185,7 +221,7 @@ class Interface {
definingInterface = member[1];
continue;
}
if (forbiddenMembers.has(member.name)) {
if (forbiddenMembers.has(member.name) || member.name && member.name[0] === "_") {
Copy link
Member

Choose a reason for hiding this comment

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

It's worth adding a check that our IDL parsing library properly strips the _s from source files before handing them to us. I.e., attribute boolean _foo should not trigger an error.

@@ -0,0 +1,6 @@
interface Static {
static attribute DOMString abc;
Copy link
Member

Choose a reason for hiding this comment

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

Nit: I find the alignment here distracting and would prefer no extra spacing.

@@ -355,6 +355,357 @@ const Impl = require(\\"../implementations/LegacyArrayClass.js\\");
"
`;

exports[`MixedIn.idl 1`] = `
Copy link
Member

Choose a reason for hiding this comment

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

I guess this doesn't directly test that mixing something in to multiple places doesn't reuse the same object... but it does indirectly, as it'd be hard to imagine code generation for the second class that duplicates it.

Copy link
Member

@Sebmaster Sebmaster left a comment

Choose a reason for hiding this comment

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

Generally: Do we really have to use this sentinel in the inherited member call? Can we just split this up into two "iterators"?

continue;
}
if (forbiddenMembers.has(member.name)) {
if (forbiddenMembers.has(member.name) || member.name && member.name[0] === "_") {
Copy link
Member

Choose a reason for hiding this comment

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

Parens this && to reduce (my) confusion about operator precedence.

}

// TODO: are these actually allowed by the spec?
if (!this.ctx.options.suppressErrors) {
Copy link
Member

Choose a reason for hiding this comment

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

Remove this conditional. suppressErrors should only be used for stuff we know doesn't work but we know is "safe" to ignore.

@TimothyGu
Copy link
Member Author

@domenic

Comments addressed.

What does "Refactor Overloads operation collection" accomplish?

It's pure refactoring so that it is closer to the spec's language. No new features added or bugs fixed.


@Sebmaster

Comments addressed.

Do we really have to use this sentinel in the inherited member call? Can we just split this up into two "iterators"?

No, and done.

Copy link
Member

@Sebmaster Sebmaster left a comment

Choose a reason for hiding this comment

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

Otherwise looks pretty good to me

if (!this[key].has(member.name)) {
this[key].set(member.name, new Operation(this.ctx, this, member));
} else {
this[key].get(member.name).idls.push(member);
Copy link
Member

Choose a reason for hiding this comment

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

Is the order of these guaranteed? We're sometimes accessing idls[0]. How do we know that that's the correct one? What's in the others?

Copy link
Member Author

@TimothyGu TimothyGu Sep 12, 2017

Choose a reason for hiding this comment

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

The order is not guaranteed. Here are the specific cases in which idls[0] is accessed:

  • utils.isOnInstance(this.idls[0], this.interface.idl)

    This checks for [Unforgeable] extended attribute on this.idls[0] and returns true if that is the case. The Web IDL forbids some overloads of an operation having that extended attribute and others of the same operation do not:

    If it does appear on an operation, then it must appear on all operations with the same identifier on that interface.

    We do not enforce this requirement at this moment, and a TODO is included: The check has been added.

    // TODO: check [Unforgeable] is applied uniformly.

    But assuming the input IDL is well-formed, checking the first overload only should suffice.

  • this.idls[0].name || this.name

    This is a somewhat hacky way of supporting named stringifiers. Basically in case of

    stringifier DOMString opName();
                DOMString opName(DOMString input);

    we create two Operations:

    1. one with op.name being "opName", but op.idls having both overloads, and
    2. the other's op.name property manually overridden with "toString", but op.idls[0] is still "opName", and op.idls.length is always 1.

    For the first case, since all overloads have the same name, choosing which one doesn't matter. For the second case, since there is always going to be one overload, the first and only one it is.

    OTOH, for a more basic case of

    stringifier;

    we know there is only always going to be one overload.

  • this.idls[0].stringifier

    See above. This can be true only if there is one item in this.idls.

    This doesn't look necessary any more. Removed.

I can add some comments and asserts in the code regarding the last two items if that makes it a bit clearer? Done.

Copy link
Member

Choose a reason for hiding this comment

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

I'm fine with a single comment explaining this here (or at the access points, whatever seems clearer).

@TimothyGu TimothyGu merged commit bf9954d into jsdom:master Sep 12, 2017
@TimothyGu TimothyGu deleted the mixin-stringifier branch September 12, 2017 01:30
@TimothyGu
Copy link
Member Author

Just a note when publishing a new version: this is a breaking change as it removes mixin() from the utils file.

@Zirro Zirro mentioned this pull request Sep 20, 2017
@domenic
Copy link
Member

domenic commented Sep 30, 2017

I've decided that this is not a breaking change because mixin() is undocumented. I think that is the right policy going forward. But, it ended up being done as part of v8.0.0 regardless, so we're safe even if some people don't agree.

In practice, what this means is that fixing #56 and #52 are IMO not breaking changes since they change undocumented APIs and don't change how you write an impl class.

On the other hand I counted #72 as breaking since it changes how you would write an impl class.

stevedorries pushed a commit to stevedorries/webidl2js that referenced this pull request Jan 27, 2020
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.

mixin does not properly mix in toString Don't export most things, for mixins Rework mixins
3 participants