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

Relax [[DefineOwnProperty]] on module namespace exotic objects. #858

Merged
merged 1 commit into from
Jul 18, 2018

Conversation

GeorgNeis
Copy link
Contributor

[[DefineOwnProperty]] on module namespace exotic objects used to always
return false. With this change, it returns true if, intuitively,
applying the given property descriptor wouldn't change anything. This
is consistent with how [[DefineOwnProperty]] behaves for other kinds of
objects.

…ects.

[[DefineOwnProperty]] on module namespace exotic objects used to always
return false.  With this change, it returns true if, intuitively,
applying the given property descriptor wouldn't change anything.  This
is consistent with how [[DefineOwnProperty]] behaves for other kinds of
objects.

 - Special case for symbols.
 - Make OrdinaryDefineOwnProperty use IsExtensible.
@GeorgNeis
Copy link
Contributor Author

Affected test262 tests: language/module-code/namespace/internals/define-own-property

@GeorgNeis
Copy link
Contributor Author

Note: Since [[GetOwnProperty]] can throw (if the property has not yet been initialized), it matters in which step we call it. In my change it's the very first step, but it may also make sense to do it as late as possible.

spec.html Outdated
1. Let _current_ be ? _O_.[[GetOwnProperty]](_P_).
1. If _current_ is *undefined*, return *false*.
1. If IsAccessorDescriptor(_Desc_) is *true*, return *false*.
1. If _Desc_.[[Writable]] is present and has value *false*, return *false*.
Copy link
Member

Choose a reason for hiding this comment

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

Would this perhaps be cleaner (and independently useful) if there was an IsSameDescriptor abstract operation? It might also be helpful in cleaning up ValidateAndApplyPropertyDescriptor as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It wasn't clear to me how to simplify things but in the meantime I think I found a way to factor out the common logic (something like IsSameDescriptor doesn't cut it, I believe). Will update the PR soon.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I had started writing this down but then felt that it doesn't really help a lot.

Copy link
Member

Choose a reason for hiding this comment

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

¯\_(ツ)_/¯ up to you, but it feels like being able to have an algorithm step that's effectively "if descriptorA == descriptorB, then" would be valuable - even if it's only used in a few places.

@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 labels Mar 27, 2017
@littledan
Copy link
Member

This change seems reasonable to me.

@leobalter leobalter added the needs test262 tests The proposal should specify how to test an implementation. Ideally via github.com/tc39/test262 label May 25, 2017
@rwaldron rwaldron added has consensus This has committee consensus. and removed needs consensus This needs committee consensus before it can be eligible to be merged. labels May 25, 2017
@rwaldron
Copy link
Contributor

rwaldron commented Aug 4, 2017

@GeorgNeis this change has consensus, but is blocked on tests. Are you planning to make the relevant updates to language/module-code/namespace/internals/define-own-property.js?

@GeorgNeis
Copy link
Contributor Author

I can do that.

@rwaldron
Copy link
Contributor

rwaldron commented Aug 4, 2017

@GeorgNeis excellent!

GeorgNeis added a commit to GeorgNeis/test262 that referenced this pull request Aug 7, 2017
rwaldron pushed a commit to tc39/test262 that referenced this pull request Aug 7, 2017
@rwaldron rwaldron 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 Aug 7, 2017
spec.html Outdated
@@ -8274,7 +8274,14 @@
<h1>[[DefineOwnProperty]] ( _P_, _Desc_ )</h1>
<p>When the [[DefineOwnProperty]] internal method of a module namespace exotic object _O_ is called with property key _P_ and Property Descriptor _Desc_, the following steps are taken:</p>
<emu-alg>
1. Return *false*.
1. Let _current_ be ? _O_.[[GetOwnProperty]](_P_).
Copy link
Contributor

Choose a reason for hiding this comment

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

The first step needs to be If Type(P) is Symbol, return OrdinaryDefineOwnProperty(O, P, Desc)., because the symbol properties of module namespace objects have different property descriptor attributes compared to the export properties.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right, thanks.

Copy link
Contributor

Choose a reason for hiding this comment

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

Meh, I just noticed there is an issue when the current definition of OrdinaryDefineOwnProperty is directly called:
OrdinaryDefineOwnProperty(...) directly accesses the [[Extensible]] internal slot instead of calling [[IsExtensible]], and module namespace objects don't have an [[Extensible]] internal slot.

So we've got two choices:

  • Either change OrdinaryDefineOwnProperty(...) to call [[IsExtensible]] instead of directly accessing [[Extensible]].
  • Or add an [[Extensible]] internal slot to module namespace objects.

Copy link
Member

Choose a reason for hiding this comment

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

I thing the first alternative is better. Providing alternative essential internal method definitions was intended to be the manner to encode such values that apply to all instance of a specific kind of exotic object.

I dislike the direction the second alternative is going. The [[Extensible]] internal slot is one of the defining characteristics of an ordinary object. Namespace objects are about as unordinary as you can get. Adding slots simply to allow use of Ordinary* internal methods on such non-ordinary objects weakens the concept of an ordinary object within the spec.

In ES6, Module namespace objects originally did not have a [[Prototype]] slot for similar reasons. Instead, it had a [[GetPrototypeOf]] internal method that always returned null. For some reason, this has changed to eliminate eliminate the exotic [[GetPrototypeOf]] and add a [[Prototype]] slot that always "contains the value null". I suspect this was done for a similar reason to choice 2 above. That change should probably be reverted.

In both cases, these sounds like changes that were simply made to facilitate pseudo-code reuse, but I think such changes detract rather than add to the clarity of the spec. Internal slots are instance specific, stateful and generally mutable. Their presence should imply at the very least that the state may differ among different instances of that kind of exotic object. When a value is immutable and constant that is no need to have instance specific slot to hold the constant value. The better way is to provide exotic internal methods (such as [[isExtensible]] or [[GetPrototypeOf]]) that directly use the constant. Such internal methods are conceptually shared among of instance of the exotic object type.

@littledan
Copy link
Member

What more does this need to be able to merge into the spec?

@anba
Copy link
Contributor

anba commented Oct 31, 2017

What more does this need to be able to merge into the spec?

At least the issue noted in https://github.com/tc39/ecma262/pull/858/files/5de505fcb88ceb61ba3778c18edb0ce2cb3e55ee..0c201ef1b82bd744e10dd5c7c8341d2175442002#r136673470 still needs to be fixed.

@GeorgNeis
Copy link
Contributor Author

Sorry, I had missed that. Diff now includes the (tiny) generalization of OrdinaryDefineOwnProperty.

@anba
Copy link
Contributor

anba commented Jan 11, 2018

Anything still missing before this change can be applied?

FWIW Firefox implements the proposed semantics since Firefox 57 (https://bugzilla.mozilla.org/show_bug.cgi?id=1391773).

@littledan
Copy link
Member

Now that we have tests, consensus on spec text, and a shipping implementation, it seems like time to land this patch.

@ljharb ljharb requested review from bterlson and bmeck March 5, 2018 19:20
@bmeck
Copy link
Member

bmeck commented Mar 5, 2018

LGTM but might want to match existing spec wording : https://tc39.github.io/ecma262/#sec-integer-indexed-exotic-objects-defineownproperty-p-desc

@littledan
Copy link
Member

OK, is this change ready to merge now?

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
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants