From 1d70aa7c391f8487284d3330b7a27889b7d867c8 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Wed, 21 Jul 2021 21:55:26 -0700 Subject: [PATCH] Normative: move __proto__ out of annex b (#2125) Co-authored-by: Gus Caplan Co-authored-by: Jordan Harband Co-authored-by: Michael Dyck --- spec.html | 267 ++++++++++++++++++++++++------------------------------ 1 file changed, 120 insertions(+), 147 deletions(-) diff --git a/spec.html b/spec.html index 99ae19e4d9..223b839bb0 100644 --- a/spec.html +++ b/spec.html @@ -17744,7 +17744,7 @@

Syntax

In certain contexts, |ObjectLiteral| is used as a cover grammar for a more restricted secondary grammar. The |CoverInitializedName| production is necessary to fully cover these secondary grammars. However, use of this production results in an early Syntax Error in normal contexts where an actual |ObjectLiteral| is expected.

- +

Static Semantics: Early Errors

PropertyDefinition : MethodDefinition
    @@ -17765,6 +17765,19 @@

    Static Semantics: Early Errors

    This production exists so that |ObjectLiteral| can serve as a cover grammar for |ObjectAssignmentPattern|. It cannot occur in an actual object initializer.

    + + ObjectLiteral : `{` PropertyDefinitionList `}` + + ObjectLiteral : `{` PropertyDefinitionList `,` `}` + +
      +
    • + It is a Syntax Error if PropertyNameList of |PropertyDefinitionList| contains any duplicate entries for *"__proto__"* and at least two of those entries were obtained from productions of the form PropertyDefinition : PropertyName `:` AssignmentExpression. This rule is not applied if this |PropertyDefinition| is contained within a |Script| that is being parsed for JSON.parse (see step of JSON.parse). +
    • +
    + +

    The List returned by PropertyNameList does not include property names defined using a |ComputedPropertyName|.

    +
    @@ -17860,18 +17873,25 @@

    Runtime Semantics: PropertyDefinitionEvaluation

    1. Let _propKey_ be the result of evaluating |PropertyName|. 1. ReturnIfAbrupt(_propKey_). - 1. If IsAnonymousFunctionDefinition(|AssignmentExpression|) is *true*, then + 1. If this |PropertyDefinition| is contained within a |Script| that is being evaluated for JSON.parse (see step of JSON.parse), then + 1. Let _isProtoSetter_ be *false*. + 1. Else if _propKey_ is the String value *"__proto__"* and if IsComputedPropertyKey of |PropertyName| is *false*, then + 1. Let _isProtoSetter_ be *true*. + 1. Else, + 1. Let _isProtoSetter_ be *false*. + 1. If IsAnonymousFunctionDefinition(|AssignmentExpression|) is *true* and _isProtoSetter_ is *false*, then 1. Let _propValue_ be ? NamedEvaluation of |AssignmentExpression| with argument _propKey_. 1. Else, 1. Let _exprValueRef_ be the result of evaluating |AssignmentExpression|. 1. Let _propValue_ be ? GetValue(_exprValueRef_). + 1. If _isProtoSetter_ is *true*, then + 1. If Type(_propValue_) is either Object or Null, then + 1. Return ! _object_.[[SetPrototypeOf]](_propValue_). + 1. Return NormalCompletion(~empty~). 1. Assert: _enumerable_ is *true*. 1. Assert: _object_ is an ordinary, extensible object with no non-configurable properties. 1. Return ! CreateDataPropertyOrThrow(_object_, _propKey_, _propValue_). - -

    An alternative semantics for this production is given in .

    -
    MethodDefinition : ClassElementName `(` UniqueFormalParameters `)` `{` FunctionBody `}` @@ -28302,7 +28322,7 @@

    Object.values ( _O_ )

    - +

    Properties of the Object Prototype Object

    The Object prototype object:

      @@ -28414,6 +28434,95 @@

      Object.prototype.valueOf ( )

      1. Return ? ToObject(*this* value). + + +

      Object.prototype.__proto__

      +

      `Object.prototype.__proto__` is an accessor property with attributes { [[Enumerable]]: *false*, [[Configurable]]: *true* }. The [[Get]] and [[Set]] attributes are defined as follows:

      + + +

      get Object.prototype.__proto__

      +

      The value of the [[Get]] attribute is a built-in function that requires no arguments. It performs the following steps when called:

      + + 1. Let _O_ be ? ToObject(*this* value). + 1. Return ? _O_.[[GetPrototypeOf]](). + +
      + + +

      set Object.prototype.__proto__

      +

      The value of the [[Set]] attribute is a built-in function that takes an argument _proto_. It performs the following steps when called:

      + + 1. Let _O_ be ? RequireObjectCoercible(*this* value). + 1. If Type(_proto_) is neither Object nor Null, return *undefined*. + 1. If Type(_O_) is not Object, return *undefined*. + 1. Let _status_ be ? _O_.[[SetPrototypeOf]](_proto_). + 1. If _status_ is *false*, throw a *TypeError* exception. + 1. Return *undefined*. + +
      +
      + + +

      Legacy Object.prototype Accessor Methods

      + + +

      Object.prototype.__defineGetter__ ( _P_, _getter_ )

      +

      When the `__defineGetter__` method is called with arguments _P_ and _getter_, the following steps are taken:

      + + 1. Let _O_ be ? ToObject(*this* value). + 1. If IsCallable(_getter_) is *false*, throw a *TypeError* exception. + 1. Let _desc_ be PropertyDescriptor { [[Get]]: _getter_, [[Enumerable]]: *true*, [[Configurable]]: *true* }. + 1. Let _key_ be ? ToPropertyKey(_P_). + 1. Perform ? DefinePropertyOrThrow(_O_, _key_, _desc_). + 1. Return *undefined*. + +
      + + +

      Object.prototype.__defineSetter__ ( _P_, _setter_ )

      +

      When the `__defineSetter__` method is called with arguments _P_ and _setter_, the following steps are taken:

      + + 1. Let _O_ be ? ToObject(*this* value). + 1. If IsCallable(_setter_) is *false*, throw a *TypeError* exception. + 1. Let _desc_ be PropertyDescriptor { [[Set]]: _setter_, [[Enumerable]]: *true*, [[Configurable]]: *true* }. + 1. Let _key_ be ? ToPropertyKey(_P_). + 1. Perform ? DefinePropertyOrThrow(_O_, _key_, _desc_). + 1. Return *undefined*. + +
      + + +

      Object.prototype.__lookupGetter__ ( _P_ )

      +

      When the `__lookupGetter__` method is called with argument _P_, the following steps are taken:

      + + 1. Let _O_ be ? ToObject(*this* value). + 1. Let _key_ be ? ToPropertyKey(_P_). + 1. Repeat, + 1. Let _desc_ be ? _O_.[[GetOwnProperty]](_key_). + 1. If _desc_ is not *undefined*, then + 1. If IsAccessorDescriptor(_desc_) is *true*, return _desc_.[[Get]]. + 1. Return *undefined*. + 1. Set _O_ to ? _O_.[[GetPrototypeOf]](). + 1. If _O_ is *null*, return *undefined*. + +
      + + +

      Object.prototype.__lookupSetter__ ( _P_ )

      +

      When the `__lookupSetter__` method is called with argument _P_, the following steps are taken:

      + + 1. Let _O_ be ? ToObject(*this* value). + 1. Let _key_ be ? ToPropertyKey(_P_). + 1. Repeat, + 1. Let _desc_ be ? _O_.[[GetOwnProperty]](_key_). + 1. If _desc_ is not *undefined*, then + 1. If IsAccessorDescriptor(_desc_) is *true*, return _desc_.[[Set]]. + 1. Return *undefined*. + 1. Set _O_ to ? _O_.[[GetPrototypeOf]](). + 1. If _O_ is *null*, return *undefined*. + +
      +
      @@ -40567,9 +40676,11 @@

      JSON.parse ( _text_ [ , _reviver_ ] )

      1. Let _jsonString_ be ? ToString(_text_). 1. [id="step-json-parse-validate"] Parse ! StringToCodePoints(_jsonString_) as a JSON text as specified in ECMA-404. Throw a *SyntaxError* exception if it is not a valid JSON text as defined in that specification. 1. Let _scriptString_ be the string-concatenation of *"("*, _jsonString_, and *");"*. - 1. Let _script_ be ParseText(! StringToCodePoints(_scriptString_), |Script|). + 1. [id="step-json-parse-parse"] Let _script_ be ParseText(! StringToCodePoints(_scriptString_), |Script|). + 1. NOTE: The early error rules defined in have special handling for the above invocation of ParseText. 1. Assert: _script_ is a Parse Node. - 1. Let _completion_ be the result of evaluating _script_. The extended PropertyDefinitionEvaluation semantics defined in must not be used during the evaluation. + 1. [id="step-json-parse-eval"] Let _completion_ be the result of evaluating _script_. + 1. NOTE: The PropertyDefinitionEvaluation semantics defined in have special handling for the above evaluation. 1. Let _unfiltered_ be _completion_.[[Value]]. 1. [id="step-json-parse-assert-type"] Assert: _unfiltered_ is either a String, Number, Boolean, Null, or an Object that is defined by either an |ArrayLiteral| or an |ObjectLiteral|. 1. If IsCallable(_reviver_) is *true*, then @@ -40583,7 +40694,7 @@

      JSON.parse ( _text_ [ , _reviver_ ] )

      The *"length"* property of the `parse` function is *2*𝔽.

      Valid JSON text is a subset of the ECMAScript |PrimaryExpression| syntax. Step verifies that _jsonString_ conforms to that subset, and step asserts that that parsing and evaluation returns a value of an appropriate type.

      -

      However, because applies when evaluating ECMAScript source text and does not apply during `JSON.parse`, the same source text can produce different results when evaluated as a |PrimaryExpression| rather than as JSON. Furthermore, the Early Error for duplicate *"__proto__"* properties in object literals, which likewise does not apply during `JSON.parse`, means that not all texts accepted by `JSON.parse` are valid as a |PrimaryExpression|, despite matching the grammar.

      +

      However, because behaves differently during `JSON.parse`, the same source text can produce different results when evaluated as a |PrimaryExpression| rather than as JSON. Furthermore, the Early Error for duplicate *"__proto__"* properties in object literals, which likewise does not apply during `JSON.parse`, means that not all texts accepted by `JSON.parse` are valid as a |PrimaryExpression|, despite matching the grammar.

      @@ -45794,95 +45905,6 @@

      unescape ( _string_ )

      - -

      Additional Properties of the Object.prototype Object

      - - -

      Object.prototype.__proto__

      -

      `Object.prototype.__proto__` is an accessor property with attributes { [[Enumerable]]: *false*, [[Configurable]]: *true* }. The [[Get]] and [[Set]] attributes are defined as follows:

      - - -

      get Object.prototype.__proto__

      -

      The value of the [[Get]] attribute is a built-in function that requires no arguments. It performs the following steps when called:

      - - 1. Let _O_ be ? ToObject(*this* value). - 1. Return ? _O_.[[GetPrototypeOf]](). - -
      - - -

      set Object.prototype.__proto__

      -

      The value of the [[Set]] attribute is a built-in function that takes an argument _proto_. It performs the following steps when called:

      - - 1. Let _O_ be ? RequireObjectCoercible(*this* value). - 1. If Type(_proto_) is neither Object nor Null, return *undefined*. - 1. If Type(_O_) is not Object, return *undefined*. - 1. Let _status_ be ? _O_.[[SetPrototypeOf]](_proto_). - 1. If _status_ is *false*, throw a *TypeError* exception. - 1. Return *undefined*. - -
      -
      - - -

      Object.prototype.__defineGetter__ ( _P_, _getter_ )

      -

      When the `__defineGetter__` method is called with arguments _P_ and _getter_, the following steps are taken:

      - - 1. Let _O_ be ? ToObject(*this* value). - 1. If IsCallable(_getter_) is *false*, throw a *TypeError* exception. - 1. Let _desc_ be PropertyDescriptor { [[Get]]: _getter_, [[Enumerable]]: *true*, [[Configurable]]: *true* }. - 1. Let _key_ be ? ToPropertyKey(_P_). - 1. Perform ? DefinePropertyOrThrow(_O_, _key_, _desc_). - 1. Return *undefined*. - -
      - - -

      Object.prototype.__defineSetter__ ( _P_, _setter_ )

      -

      When the `__defineSetter__` method is called with arguments _P_ and _setter_, the following steps are taken:

      - - 1. Let _O_ be ? ToObject(*this* value). - 1. If IsCallable(_setter_) is *false*, throw a *TypeError* exception. - 1. Let _desc_ be PropertyDescriptor { [[Set]]: _setter_, [[Enumerable]]: *true*, [[Configurable]]: *true* }. - 1. Let _key_ be ? ToPropertyKey(_P_). - 1. Perform ? DefinePropertyOrThrow(_O_, _key_, _desc_). - 1. Return *undefined*. - -
      - - -

      Object.prototype.__lookupGetter__ ( _P_ )

      -

      When the `__lookupGetter__` method is called with argument _P_, the following steps are taken:

      - - 1. Let _O_ be ? ToObject(*this* value). - 1. Let _key_ be ? ToPropertyKey(_P_). - 1. Repeat, - 1. Let _desc_ be ? _O_.[[GetOwnProperty]](_key_). - 1. If _desc_ is not *undefined*, then - 1. If IsAccessorDescriptor(_desc_) is *true*, return _desc_.[[Get]]. - 1. Return *undefined*. - 1. Set _O_ to ? _O_.[[GetPrototypeOf]](). - 1. If _O_ is *null*, return *undefined*. - -
      - - -

      Object.prototype.__lookupSetter__ ( _P_ )

      -

      When the `__lookupSetter__` method is called with argument _P_, the following steps are taken:

      - - 1. Let _O_ be ? ToObject(*this* value). - 1. Let _key_ be ? ToPropertyKey(_P_). - 1. Repeat, - 1. Let _desc_ be ? _O_.[[GetOwnProperty]](_key_). - 1. If _desc_ is not *undefined*, then - 1. If IsAccessorDescriptor(_desc_) is *true*, return _desc_.[[Set]]. - 1. Return *undefined*. - 1. Set _O_ to ? _O_.[[GetPrototypeOf]](). - 1. If _O_ is *null*, return *undefined*. - -
      -
      -

      Additional Properties of the String.prototype Object

      @@ -46150,55 +46172,6 @@

      RegExp.prototype.compile ( _pattern_, _flags_ )

      Other Additional Features

      - -

      __proto__ Property Names in Object Initializers

      -

      The following Early Error rule is added to those in . This rule is not applied under any of the following circumstances:

      -
        -
      • when |ObjectLiteral| appears in a context where |ObjectAssignmentPattern| is required,
      • -
      • when initially parsing a |CoverParenthesizedExpressionAndArrowParameterList| or a |CoverCallExpressionAndAsyncArrowHead|, or
      • -
      • when parsing text for JSON.parse.
      • -
      - - ObjectLiteral : - `{` PropertyDefinitionList `}` - `{` PropertyDefinitionList `,` `}` - -
        -
      • - It is a Syntax Error if PropertyNameList of |PropertyDefinitionList| contains any duplicate entries for *"__proto__"* and at least two of those entries were obtained from productions of the form PropertyDefinition : PropertyName `:` AssignmentExpression. -
      • -
      - -

      The List returned by PropertyNameList does not include string literal property names defined as using a |ComputedPropertyName|.

      -
      -

      In the PropertyDefinitionEvaluation algorithm for the production -
      - PropertyDefinition : PropertyName `:` AssignmentExpression -
      - is replaced with the following definition:

      - PropertyDefinition : PropertyName `:` AssignmentExpression - - 1. Let _propKey_ be the result of evaluating |PropertyName|. - 1. ReturnIfAbrupt(_propKey_). - 1. If _propKey_ is the String value *"__proto__"* and if IsComputedPropertyKey(|PropertyName|) is *false*, then - 1. Let _isProtoSetter_ be *true*. - 1. Else, - 1. Let _isProtoSetter_ be *false*. - 1. If IsAnonymousFunctionDefinition(|AssignmentExpression|) is *true* and _isProtoSetter_ is *false*, then - 1. Let _propValue_ be ? NamedEvaluation of |AssignmentExpression| with argument _propKey_. - 1. Else, - 1. Let _exprValueRef_ be the result of evaluating |AssignmentExpression|. - 1. Let _propValue_ be ? GetValue(_exprValueRef_). - 1. If _isProtoSetter_ is *true*, then - 1. If Type(_propValue_) is either Object or Null, then - 1. Return _object_.[[SetPrototypeOf]](_propValue_). - 1. Return NormalCompletion(~empty~). - 1. Assert: _enumerable_ is *true*. - 1. Assert: _object_ is an ordinary, extensible object with no non-configurable properties. - 1. Return ! CreateDataPropertyOrThrow(_object_, _propKey_, _propValue_). - -
      -

      Labelled Function Declarations

      Prior to ECMAScript 2015, the specification of |LabelledStatement| did not allow for the association of a statement label with a |FunctionDeclaration|. However, a labelled |FunctionDeclaration| was an allowable extension for non-strict code and most browser-hosted ECMAScript implementations supported that extension. In ECMAScript 2015 and later, the grammar production for |LabelledStatement| permits use of |FunctionDeclaration| as a |LabelledItem| but includes an Early Error rule that produces a Syntax Error if that occurs. That rule is modified with the addition of the highlighted text: