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

Normative: Allow null or undefined in Reference Records #2267

Merged
merged 1 commit into from
Aug 15, 2021

Conversation

codehag
Copy link
Contributor

@codehag codehag commented Jan 5, 2021

Hi folks,

The goal of this pr is to address the concern brought up in #1224 -- which has become more pressing. With the introduction of private fields, implementations will again diverge on this point from the specification.

There were two suggested solutions to this, one was re-evaluation, which was rejected in past meetings. The other was reordering.

This pr allows null and undefined as values in Reference Records. This means that throwing is moved to ToObject in most cases.

We are not too sure about the super code though, and could use some extra eyes. See the past discussion here

@ljharb ljharb added needs consensus This needs committee consensus before it can be eligible to be merged. normative change Affects behavior required to correctly evaluate some ECMAScript source text web reality labels Jan 5, 2021
@jorendorff
Copy link
Contributor

I think this patch is the simplest way to implement "reordering".

Currently, the spec says null.y = f() should fail before calling f; it happens in the CheckObjectCoercible calls that the patch removes.

With the patch, the same check will effectively happen anyway, but later, in the ToObject calls that are made fallible (changing from ! to ?).

@caiolima
Copy link
Contributor

Just for the record, I left a comment about this PR on codehag#3.

@ljharb ljharb added has consensus This has committee consensus. and removed needs consensus This needs committee consensus before it can be eligible to be merged. labels Jan 25, 2021
@ljharb
Copy link
Member

ljharb commented Jan 25, 2021

Does this PR need any test262 tests?

@codehag
Copy link
Contributor Author

codehag commented Jan 25, 2021

Yes, it needs some adjustments. I think someone may have started it already, if not I will look into it (soon).

@ljharb ljharb added the needs test262 tests The proposal should specify how to test an implementation. Ideally via github.com/tc39/test262 label Jan 25, 2021
@jugglinmike
Copy link
Contributor

I'm writing some Test262 tests for this, and I wanted to confirm my interpretation.

I believe that with this patch applied, web reality will continue to diverge when it comes to the ToPropertyKey operation in the "MemberExpression [ Expression ]" production. That's not related to the Class Fields proposal, so it may be an intentional decision to limit scope. I'd like to verify since this is implied by the motivating bug report and since web reality is part of the goal.

function prop() {
  print('property name value');
  return { toString() { print('property name string'); } };
}
[][prop()] = print('value');

Today, the standard specifies the following sequence:

property name value
property name string
value

...but SpiderMonkey, V8, and JSC behave as follows:

property name value
value
property name string

With this patch applied, my reading is that the spec will continue to describe the same sequence it does today.

@bakkot
Copy link
Contributor

bakkot commented May 21, 2021

@jugglinmike That matches my interpretation. Specifically, this PR only relates to the point at which we check for null and undefined, not the order (and count) of property key coercion discussed in #467 (which will remain open after this PR).

@jugglinmike
Copy link
Contributor

Got it. Thanks for confirming, Kevin! (And oof about the differences in count.)

spec.html Outdated
@@ -14205,7 +14202,7 @@ <h1>Runtime Semantics: Evaluation</h1>
1. Return *true*.
1. If IsPropertyReference(_ref_) is *true*, then
1. If IsSuperReference(_ref_) is *true*, throw a *ReferenceError* exception.
1. [id="step-delete-operator-toobject"] Let _baseObj_ be ! ToObject(_ref_.[[Base]]).
1. [id="step-delete-operator-toobject"] Let _baseObj_ be ? ToObject(_ref_.[[Base]]).
Copy link
Contributor

@jugglinmike jugglinmike May 21, 2021

Choose a reason for hiding this comment

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

This appears to change an edge case related to the null and undefined check--one that may be unintentional.

class C {
  static m() {
    delete super.x;
  }
}
Object.setPrototypeOf(C, null);
C.m();

In the spec today, evaluating super.x will produce a TypeError due to its use of RequireObjectCoercible (that is, before the runtime semantics of the delete operator begin).

With this change applied, evaluation makes it to the delete operator, but the ReferenceError from the IsSuperReference check will be thrown before ToObject has a chance to throw a TypeError.

There's implementation divergence here, too. Today, V8 and JSC throw the ReferenceError while SpiderMonkey and Engine262 throw the TypeError.

If my reading is accurate and we want to preserve the currently-specified behavior, it may be as simple as swapping this step and the one immediately before it.

Copy link
Contributor

Choose a reason for hiding this comment

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

Pardon me: the method in the example code ought to be static. I'll update it accordingly.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for pointing this out.

Personally I think the behavior in this PR is reasonable: checking whether something is a super reference seems more "static" than checking that the resolved value is object-coercible, so it makes sense to do the super check first. (In fact, I think it would have been possible to forbid delete super.x at parse time; I'm not sure why we made it a runtime error instead.)

Given that, and since we got consensus on this PR as written, I'm going to go ahead with the current behavior. But I'll call it out at the next meeting to make sure everyone is aware, and give people a chance to raise an issue if they'd like it modified.

Copy link
Contributor

Choose a reason for hiding this comment

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

jugglinmike added a commit to bocoup/test262 that referenced this pull request May 21, 2021
These tests support the following normative change

Normative: Allow null or undefined in Reference Records
tc39/ecma262#2267
jugglinmike added a commit to bocoup/test262 that referenced this pull request May 21, 2021
These tests support the following normative change

"Normative: Allow null or undefined in Reference Records"
tc39/ecma262#2267

The tests concerning the `delete` operator increase coverage to verify
behavior which, though related, is not altered by the normative change.
These tests are intended to guard against regressions as engines
implement the new semantics.
jugglinmike added a commit to bocoup/test262 that referenced this pull request May 21, 2021
These tests support the following normative change

"Normative: Allow null or undefined in Reference Records"
tc39/ecma262#2267

The tests concerning the `delete` operator increase coverage to verify
behavior which, though related, is not altered by the normative change.
These tests are intended to guard against regressions as engines
implement the new semantics.
rwaldron pushed a commit to tc39/test262 that referenced this pull request Jun 24, 2021
These tests support the following normative change

"Normative: Allow null or undefined in Reference Records"
tc39/ecma262#2267

The tests concerning the `delete` operator increase coverage to verify
behavior which, though related, is not altered by the normative change.
These tests are intended to guard against regressions as engines
implement the new semantics.
@ljharb ljharb force-pushed the master branch 3 times, most recently from 3d0c24c to 7a79833 Compare June 29, 2021 02:21
@devsnek
Copy link
Member

devsnek commented Jul 18, 2021

This has tests now right?

@bakkot bakkot added has test262 tests and removed needs test262 tests The proposal should specify how to test an implementation. Ideally via github.com/tc39/test262 labels Jul 18, 2021
@bakkot
Copy link
Contributor

bakkot commented Jul 18, 2021

Indeed, looks like tests landed in tc39/test262#2993. I'll get this rebased and we can land it (pending another stamp, which I'll ping other editors for at the editor call).

@bakkot bakkot force-pushed the null-or-undefined-reference-records branch from 7f38832 to d4cfaf1 Compare July 18, 2021 20:09
@bakkot bakkot added the editor call to be discussed in the next editor call label Jul 18, 2021
spec.html Outdated
@@ -18452,9 +18451,8 @@ <h1>
</dl>
<emu-alg>
1. Assert: _identifierName_ is an |IdentifierName|.
1. Let _bv_ be ? RequireObjectCoercible(_baseValue_).
Copy link
Collaborator

Choose a reason for hiding this comment

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

By removing the call to RequireObjectCoercible, it appears that EvaluatePropertyAccessWithIdentifierKey can no longer return an abrupt completion, so invocations of it should be prefixed with ! rather than ?.

Copy link
Contributor

Choose a reason for hiding this comment

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

Nice catch, done.

jugglinmike added a commit to tc39/test262 that referenced this pull request Jul 19, 2021
The following proposed change modifies the semantics this test was
originally written to verify:

Normative: Allow null or undefined in Reference Records
tc39/ecma262#2267
rwaldron pushed a commit to tc39/test262 that referenced this pull request Jul 19, 2021
The following proposed change modifies the semantics this test was
originally written to verify:

Normative: Allow null or undefined in Reference Records
tc39/ecma262#2267
Copy link
Contributor

@syg syg left a comment

Choose a reason for hiding this comment

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

lgtm

@anba
Copy link
Contributor

anba commented Jul 22, 2021

Don't we also want to remove the RequireObjectCoercible calls before private references?

moz-v2v-gh pushed a commit to mozilla/gecko-dev that referenced this pull request Jul 23, 2021
jamienicol pushed a commit to jamienicol/gecko that referenced this pull request Jul 26, 2021
@codehag codehag force-pushed the null-or-undefined-reference-records branch from 24de565 to e01feba Compare August 10, 2021 10:24
@bakkot bakkot added ready to merge Editors believe this PR needs no further reviews, and is ready to land. and removed editor call to be discussed in the next editor call labels Aug 14, 2021
@ljharb ljharb force-pushed the null-or-undefined-reference-records branch from e01feba to d09532c Compare August 15, 2021 19:36
@ljharb ljharb merged commit d09532c into tc39:master Aug 15, 2021
mathiasbynens pushed a commit to mathiasbynens/ecma262 that referenced this pull request Oct 18, 2021
Lubrsi added a commit to Lubrsi/serenity that referenced this pull request Jul 5, 2023
This is part of an old normative change that happened soon after
Andreas made `super` closer to spec in 1270df2.
See tc39/ecma262#2267

This was introduced into bytecode by virtue of copy and paste :^)

Bytecode results:
Summary:
    Diff Tests:
        +2 ✅    -2 ❌
Lubrsi added a commit to Lubrsi/serenity that referenced this pull request Jul 5, 2023
This is part of an old normative change that happened soon after
Andreas made `super` closer to spec in 1270df2.
See tc39/ecma262#2267

This was introduced into bytecode by virtue of copy and paste :^)

Bytecode results:
Summary:
    Diff Tests:
        +2 ✅    -2 ❌
Lubrsi added a commit to Lubrsi/serenity that referenced this pull request Jul 5, 2023
This is part of an old normative change that happened soon after
Andreas made `super` closer to spec in 1270df2.
See tc39/ecma262#2267

This was introduced into bytecode by virtue of copy and paste :^)

Bytecode results:
Summary:
    Diff Tests:
        +2 ✅    -2 ❌
Lubrsi added a commit to Lubrsi/serenity that referenced this pull request Jul 5, 2023
This is part of an old normative change that happened soon after
Andreas made `super` closer to spec in 1270df2.
See tc39/ecma262#2267

This was introduced into bytecode by virtue of copy and paste :^)

Bytecode results:
Summary:
    Diff Tests:
        +2 ✅    -2 ❌
awesomekling pushed a commit to SerenityOS/serenity that referenced this pull request Jul 6, 2023
This is part of an old normative change that happened soon after
Andreas made `super` closer to spec in 1270df2.
See tc39/ecma262#2267

This was introduced into bytecode by virtue of copy and paste :^)

Bytecode results:
Summary:
    Diff Tests:
        +2 ✅    -2 ❌
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
has consensus This has committee consensus. has test262 tests normative change Affects behavior required to correctly evaluate some ECMAScript source text ready to merge Editors believe this PR needs no further reviews, and is ready to land. web reality
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

10 participants