Changeset 218861 in webkit


Ignore:
Timestamp:
Jun 27, 2017 8:05:47 PM (7 years ago)
Author:
Caio Lima
Message:

[ESnext] Implement Object Rest - Implementing Object Rest Destructuring
https://bugs.webkit.org/show_bug.cgi?id=167962

Reviewed by Saam Barati.

JSTests:

  • stress/object-rest-deconstruct.js: Added.

(let.assert):
(let.assertPropDescriptor):
(catch):
(get 3):
(foo):
(let.src.get y):
(let.src.set y):
(let.gen):

Source/JavaScriptCore:

Object Rest/Spread Destructing proposal is in stage 3[1] and this
Patch is a prototype implementation of it. A simple change over the
parser was necessary to support the new '...' token on Object Pattern
destruction rule. In the bytecode generator side, We changed the
bytecode generated on ObjectPatternNode::bindValue to store in an
set the identifiers of already destructured properties, following spec draft
section[2], and then pass it as excludedNames to CopyDataProperties.
The rest destructuring calls copyDataProperties to perform the
copy of rest properties in rhs.

We also implemented CopyDataProperties as private JS global operation
on builtins/GlobalOperations.js following it's specification on [3].
It is implemented using Set object to verify if a property is on
excludedNames to keep this algorithm with O(n + m) complexity, where n

number of source's own properties and m = excludedNames.length.

In this implementation we aren't using excludeList as constant if
destructuring pattern contains computed property, i.e. we can
just determine the key to be excluded at runtime. If we can define all
identifiers in the pattern in compile time, we then create a
constant JSSet. This approach gives a good performance improvement,
since we allocate the excludeSet just once, reducing GC pressure.

[1] - https://github.com/tc39/proposal-object-rest-spread
[2] - https://tc39.github.io/proposal-object-rest-spread/#Rest-RuntimeSemantics-PropertyDestructuringAssignmentEvaluation
[3] - https://tc39.github.io/proposal-object-rest-spread/#AbstractOperations-CopyDataProperties

  • builtins/BuiltinNames.h:
  • builtins/GlobalOperations.js:

(globalPrivate.copyDataProperties):

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::finishCreation):

  • bytecompiler/NodesCodegen.cpp:

(JSC::ObjectPatternNode::bindValue):

  • parser/ASTBuilder.h:

(JSC::ASTBuilder::appendObjectPatternEntry):
(JSC::ASTBuilder::appendObjectPatternRestEntry):
(JSC::ASTBuilder::setContainsObjectRestElement):

  • parser/Nodes.h:

(JSC::ObjectPatternNode::appendEntry):
(JSC::ObjectPatternNode::setContainsRestElement):

  • parser/Parser.cpp:

(JSC::Parser<LexerType>::parseDestructuringPattern):
(JSC::Parser<LexerType>::parseProperty):

  • parser/SyntaxChecker.h:

(JSC::SyntaxChecker::operatorStackPop):

  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::init):

  • runtime/JSGlobalObject.h:

(JSC::JSGlobalObject::asyncFunctionStructure):
(JSC::JSGlobalObject::setStructure): Deleted.

  • runtime/JSGlobalObjectFunctions.cpp:

(JSC::privateToObject):

  • runtime/JSGlobalObjectFunctions.h:
  • runtime/ObjectConstructor.cpp:

(JSC::ObjectConstructor::finishCreation):

  • runtime/SetPrototype.cpp:

(JSC::SetPrototype::finishCreation):

Source/WTF:

  • wtf/HashSet.h:

(WTF::=):

LayoutTests:

  • js/parser-syntax-check-expected.txt:
  • js/script-tests/parser-syntax-check.js:
Location:
trunk
Files:
1 added
25 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r218845 r218861  
     12017-06-27  Caio Lima  <ticaiolima@gmail.com>
     2
     3        [ESnext] Implement Object Rest - Implementing Object Rest Destructuring
     4        https://bugs.webkit.org/show_bug.cgi?id=167962
     5
     6        Reviewed by Saam Barati.
     7
     8        * stress/object-rest-deconstruct.js: Added.
     9        (let.assert):
     10        (let.assertPropDescriptor):
     11        (catch):
     12        (get 3):
     13        (foo):
     14        (let.src.get y):
     15        (let.src.set y):
     16        (let.gen):
     17
    1182017-06-27  Saam Barati  <sbarati@apple.com>
    219
  • trunk/LayoutTests/ChangeLog

    r218859 r218861  
     12017-06-27  Caio Lima  <ticaiolima@gmail.com>
     2
     3        [ESnext] Implement Object Rest - Implementing Object Rest Destructuring
     4        https://bugs.webkit.org/show_bug.cgi?id=167962
     5
     6        Reviewed by Saam Barati.
     7
     8        * js/parser-syntax-check-expected.txt:
     9        * js/script-tests/parser-syntax-check.js:
     10
    1112017-06-27  Yusuke Suzuki  <utatane.tea@gmail.com>
    212
  • trunk/LayoutTests/js/parser-syntax-check-expected.txt

    r217200 r218861  
    12161216PASS Invalid: "var [...y, ...z] = 20". Produced the following syntax error: "SyntaxError: Unexpected token ','. Expected a closing ']' following a rest element destructuring pattern."
    12171217PASS Invalid: "function f() { var [...y, ...z] = 20 }". Produced the following syntax error: "SyntaxError: Unexpected token ','. Expected a closing ']' following a rest element destructuring pattern."
    1218 PASS Invalid: "var [...{...y}] = 20". Produced the following syntax error: "SyntaxError: Unexpected token '...'. Expected a property name."
    1219 PASS Invalid: "function f() { var [...{...y}] = 20 }". Produced the following syntax error: "SyntaxError: Unexpected token '...'. Expected a property name."
     1218PASS Valid:   "var [...{...y}] = 20" with TypeError
     1219PASS Valid:   "function f() { var [...{...y}] = 20 }"
     1220PASS Valid:   "var {a, b, ...r} = {a: 1, b: 2, c: 3};"
     1221PASS Valid:   "function f() { var {a, b, ...r} = {a: 1, b: 2, c: 3}; }"
     1222PASS Invalid: "var {a, b, ...{d}} = {a: 1, b: 2, c: 3, d: 4};". Produced the following syntax error: "SyntaxError: Unexpected token '{'. Expected a binding element."
     1223PASS Invalid: "function f() { var {a, b, ...{d}} = {a: 1, b: 2, c: 3, d: 4}; }". Produced the following syntax error: "SyntaxError: Unexpected token '{'. Expected a binding element."
     1224PASS Invalid: "var {a, b, ...{d = 15}} = {a: 1, b: 2, c: 3, d: 4};". Produced the following syntax error: "SyntaxError: Unexpected token '{'. Expected a binding element."
     1225PASS Invalid: "function f() { var {a, b, ...{d = 15}} = {a: 1, b: 2, c: 3, d: 4}; }". Produced the following syntax error: "SyntaxError: Unexpected token '{'. Expected a binding element."
     1226PASS Invalid: "var {a, b, ...{d = 15, ...r}} = {a: 1, b: 2, c: 3, d: 4};". Produced the following syntax error: "SyntaxError: Unexpected token '{'. Expected a binding element."
     1227PASS Invalid: "function f() { var {a, b, ...{d = 15, ...r}} = {a: 1, b: 2, c: 3, d: 4}; }". Produced the following syntax error: "SyntaxError: Unexpected token '{'. Expected a binding element."
     1228PASS Valid:   "(({a, b, ...r}) => {})({a: 1, b: 2, c: 3, d: 4});"
     1229PASS Valid:   "function f() { (({a, b, ...r}) => {})({a: 1, b: 2, c: 3, d: 4}); }"
     1230PASS Valid:   "(function ({a, b, ...r}) {})({a: 1, b: 2, c: 3, d: 4});"
     1231PASS Valid:   "function f() { (function ({a, b, ...r}) {})({a: 1, b: 2, c: 3, d: 4}); }"
     1232PASS Valid:   "var a, b, c; ({a, b, ...r} = {a: 1, b: 2, c: 3, d: 4});"
     1233PASS Valid:   "function f() { var a, b, c; ({a, b, ...r} = {a: 1, b: 2, c: 3, d: 4}); }"
     1234PASS Valid:   "try { throw {a:2} } catch({...rest}) {}"
     1235PASS Valid:   "function f() { try { throw {a:2} } catch({...rest}) {} }"
     1236PASS Invalid: "function * foo(o) { ({...{ x = yield }} = o); }". Produced the following syntax error: "SyntaxError: Unexpected token '='. Expected a ':' following the property name 'x'."
     1237PASS Invalid: "function f() { function * foo(o) { ({...{ x = yield }} = o); } }". Produced the following syntax error: "SyntaxError: Unexpected token '='. Expected a ':' following the property name 'x'."
     1238PASS Invalid: "var {...r = {a: 2}} = {a: 1, b: 2};". Produced the following syntax error: "SyntaxError: Unexpected token '='. Expected a closing '}' following a rest element destructuring pattern."
     1239PASS Invalid: "function f() { var {...r = {a: 2}} = {a: 1, b: 2}; }". Produced the following syntax error: "SyntaxError: Unexpected token '='. Expected a closing '}' following a rest element destructuring pattern."
     1240PASS Invalid: "var {...r, b} = {a: 1, b: 2};". Produced the following syntax error: "SyntaxError: Unexpected token ','. Expected a closing '}' following a rest element destructuring pattern."
     1241PASS Invalid: "function f() { var {...r, b} = {a: 1, b: 2}; }". Produced the following syntax error: "SyntaxError: Unexpected token ','. Expected a closing '}' following a rest element destructuring pattern."
     1242PASS Invalid: "var {...r, ...e} = {a: 1, b: 2};". Produced the following syntax error: "SyntaxError: Unexpected token ','. Expected a closing '}' following a rest element destructuring pattern."
     1243PASS Invalid: "function f() { var {...r, ...e} = {a: 1, b: 2}; }". Produced the following syntax error: "SyntaxError: Unexpected token ','. Expected a closing '}' following a rest element destructuring pattern."
     1244PASS Invalid: "({...new Object()} = {a: 1, b: 2});". Produced the following syntax error: "SyntaxError: Invalid destructuring assignment target."
     1245PASS Invalid: "function f() { ({...new Object()} = {a: 1, b: 2}); }". Produced the following syntax error: "SyntaxError: Invalid destructuring assignment target."
     1246PASS Invalid: "(function * (o) { ({ ...{ x: yield } } = o); })()". Produced the following syntax error: "SyntaxError: Invalid destructuring assignment target."
     1247PASS Invalid: "function f() { (function * (o) { ({ ...{ x: yield } } = o); })() }". Produced the following syntax error: "SyntaxError: Invalid destructuring assignment target."
     1248PASS Invalid: "(function () {'use strict'; ({...eval} = {}); })()". Produced the following syntax error: "SyntaxError: Cannot modify 'eval' in strict mode."
     1249PASS Invalid: "function f() { (function () {'use strict'; ({...eval} = {}); })() }". Produced the following syntax error: "SyntaxError: Cannot modify 'eval' in strict mode."
     1250PASS Invalid: "(function () {'use strict'; ({...arguments} = {}); })()". Produced the following syntax error: "SyntaxError: Cannot modify 'arguments' in strict mode."
     1251PASS Invalid: "function f() { (function () {'use strict'; ({...arguments} = {}); })() }". Produced the following syntax error: "SyntaxError: Cannot modify 'arguments' in strict mode."
     1252PASS Invalid: "async function foo () { let {...await} = {}; }". Produced the following syntax error: "SyntaxError: Cannot use 'await' as a lexical variable name in an async function."
     1253PASS Invalid: "function f() { async function foo () { let {...await} = {}; } }". Produced the following syntax error: "SyntaxError: Cannot use 'await' as a lexical variable name in an async function."
     1254PASS Invalid: "let {...let} = {a: 1, b: 2};". Produced the following syntax error: "SyntaxError: Unexpected keyword 'let'. Cannot use 'let' as an identifier name for a LexicalDeclaration."
     1255PASS Invalid: "function f() { let {...let} = {a: 1, b: 2}; }". Produced the following syntax error: "SyntaxError: Unexpected keyword 'let'. Cannot use 'let' as an identifier name for a LexicalDeclaration."
     1256PASS Invalid: "const {...let} = {a: 1, b: 2};". Produced the following syntax error: "SyntaxError: Unexpected keyword 'let'. Cannot use 'let' as an identifier name for a LexicalDeclaration."
     1257PASS Invalid: "function f() { const {...let} = {a: 1, b: 2}; }". Produced the following syntax error: "SyntaxError: Unexpected keyword 'let'. Cannot use 'let' as an identifier name for a LexicalDeclaration."
     1258PASS Invalid: "try { throw {a:2} } catch({...foo.a}) {}". Produced the following syntax error: "SyntaxError: Unexpected token '.'. Expected a closing '}' following a rest element destructuring pattern."
     1259PASS Invalid: "function f() { try { throw {a:2} } catch({...foo.a}) {} }". Produced the following syntax error: "SyntaxError: Unexpected token '.'. Expected a closing '}' following a rest element destructuring pattern."
    12201260Rest parameter
    12211261PASS Valid:   "function foo(...a) { }"
     
    12851325PASS Valid:   "let x = (a = 20, ...{b}) => { }"
    12861326PASS Valid:   "function f() { let x = (a = 20, ...{b}) => { } }"
    1287 PASS Invalid: "let x = (a = 20, ...{...b}) => { }". Produced the following syntax error: "SyntaxError: Unexpected token '...'"
    1288 PASS Invalid: "function f() { let x = (a = 20, ...{...b}) => { } }". Produced the following syntax error: "SyntaxError: Unexpected token '...'"
     1327PASS Valid:   "let x = (a = 20, ...{...b}) => { }"
     1328PASS Valid:   "function f() { let x = (a = 20, ...{...b}) => { } }"
    12891329PASS Invalid: "let x = (a = 20, ...{124}) => { }". Produced the following syntax error: "SyntaxError: Unexpected token '...'"
    12901330PASS Invalid: "function f() { let x = (a = 20, ...{124}) => { } }". Produced the following syntax error: "SyntaxError: Unexpected token '...'"
     
    15711611PASS Invalid: "({ foo({a},...a){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
    15721612PASS Invalid: "function f() { ({ foo({a},...a){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
    1573 PASS Invalid: "({ foo({...a},...a){} });". Produced the following syntax error: "SyntaxError: Unexpected token '...'. Expected a property name."
    1574 PASS Invalid: "function f() { ({ foo({...a},...a){} }); }". Produced the following syntax error: "SyntaxError: Unexpected token '...'. Expected a property name."
     1613PASS Invalid: "({ foo({...a},...a){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
     1614PASS Invalid: "function f() { ({ foo({...a},...a){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
    15751615PASS Invalid: "({ *foo({a},a){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
    15761616PASS Invalid: "function f() { ({ *foo({a},a){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
     
    15811621PASS Invalid: "({ *foo({a},...a){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
    15821622PASS Invalid: "function f() { ({ *foo({a},...a){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
    1583 PASS Invalid: "({ *foo({...a},...a){} });". Produced the following syntax error: "SyntaxError: Unexpected token '...'. Expected a property name."
    1584 PASS Invalid: "function f() { ({ *foo({...a},...a){} }); }". Produced the following syntax error: "SyntaxError: Unexpected token '...'. Expected a property name."
     1623PASS Invalid: "({ *foo({...a},...a){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
     1624PASS Invalid: "function f() { ({ *foo({...a},...a){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
    15851625PASS Invalid: "({ async foo({a},a){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
    15861626PASS Invalid: "function f() { ({ async foo({a},a){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
     
    15911631PASS Invalid: "({ async foo({a},...a){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
    15921632PASS Invalid: "function f() { ({ async foo({a},...a){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
    1593 PASS Invalid: "({ async foo({...a},...a){} });". Produced the following syntax error: "SyntaxError: Unexpected token '...'. Expected a property name."
    1594 PASS Invalid: "function f() { ({ async foo({...a},...a){} }); }". Produced the following syntax error: "SyntaxError: Unexpected token '...'. Expected a property name."
     1633PASS Invalid: "({ async foo({...a},...a){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
     1634PASS Invalid: "function f() { ({ async foo({...a},...a){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
    15951635PASS Valid:   "({ foo(a, ...b){} });"
    15961636PASS Valid:   "function f() { ({ foo(a, ...b){} }); }"
    15971637PASS Valid:   "({ foo({a}, ...b){} });"
    15981638PASS Valid:   "function f() { ({ foo({a}, ...b){} }); }"
    1599 PASS Invalid: "({ foo({a, ...b}){} });". Produced the following syntax error: "SyntaxError: Unexpected token '...'. Expected a property name."
    1600 PASS Invalid: "function f() { ({ foo({a, ...b}){} }); }". Produced the following syntax error: "SyntaxError: Unexpected token '...'. Expected a property name."
    1601 PASS Invalid: "({ foo({b, ...a}, ...c){} });". Produced the following syntax error: "SyntaxError: Unexpected token '...'. Expected a property name."
    1602 PASS Invalid: "function f() { ({ foo({b, ...a}, ...c){} }); }". Produced the following syntax error: "SyntaxError: Unexpected token '...'. Expected a property name."
     1639PASS Valid:   "({ foo({a, ...b}){} });"
     1640PASS Valid:   "function f() { ({ foo({a, ...b}){} }); }"
     1641PASS Valid:   "({ foo({b, ...a}, ...c){} });"
     1642PASS Valid:   "function f() { ({ foo({b, ...a}, ...c){} }); }"
    16031643Weird things that used to crash.
    16041644PASS Invalid: "or ([[{break //(elseifo (a=0;a<2;a++)n=
  • trunk/LayoutTests/js/script-tests/parser-syntax-check.js

    r217200 r218861  
    716716valid("var {x: [y, {z: {z: [...z]}}]} = 20");
    717717invalid("var [...y, ...z] = 20");
    718 invalid("var [...{...y}] = 20");
     718valid("var [...{...y}] = 20");
     719valid("var {a, b, ...r} = {a: 1, b: 2, c: 3};");
     720invalid("var {a, b, ...{d}} = {a: 1, b: 2, c: 3, d: 4};");
     721invalid("var {a, b, ...{d = 15}} = {a: 1, b: 2, c: 3, d: 4};");
     722invalid("var {a, b, ...{d = 15, ...r}} = {a: 1, b: 2, c: 3, d: 4};");
     723valid("(({a, b, ...r}) => {})({a: 1, b: 2, c: 3, d: 4});");
     724valid("(function ({a, b, ...r}) {})({a: 1, b: 2, c: 3, d: 4});");
     725valid("var a, b, c; ({a, b, ...r} = {a: 1, b: 2, c: 3, d: 4});");
     726valid("try { throw {a:2} } catch({...rest}) {}");
     727invalid("function * foo(o) { ({...{ x = yield }} = o); }");
     728invalid("var {...r = {a: 2}} = {a: 1, b: 2};");
     729invalid("var {...r, b} = {a: 1, b: 2};");
     730invalid("var {...r, ...e} = {a: 1, b: 2};");
     731invalid("({...new Object()} = {a: 1, b: 2});");
     732invalid("(function * (o) { ({ ...{ x: yield } } = o); })()");
     733invalid("(function () {'use strict'; ({...eval} = {}); })()");
     734invalid("(function () {'use strict'; ({...arguments} = {}); })()");
     735invalid("async function foo () { let {...await} = {}; }");
     736invalid("let {...let} = {a: 1, b: 2};");
     737invalid("const {...let} = {a: 1, b: 2};");
     738invalid("try { throw {a:2} } catch({...foo.a}) {}");
    719739
    720740debug("Rest parameter");
     
    752772valid("let x = (a = 20, ...[...[b = 40]]) => { }");
    753773valid("let x = (a = 20, ...{b}) => { }");
    754 invalid("let x = (a = 20, ...{...b}) => { }");
     774valid("let x = (a = 20, ...{...b}) => { }");
    755775invalid("let x = (a = 20, ...{124}) => { }");
    756776
     
    911931valid("({ foo(a, ...b){} });");
    912932valid("({ foo({a}, ...b){} });");
    913 invalid("({ foo({a, ...b}){} });");
    914 invalid("({ foo({b, ...a}, ...c){} });");
     933valid("({ foo({a, ...b}){} });");
     934valid("({ foo({b, ...a}, ...c){} });");
    915935
    916936debug("Weird things that used to crash.");
  • trunk/Source/JavaScriptCore/ChangeLog

    r218856 r218861  
     12017-06-27  Caio Lima  <ticaiolima@gmail.com>
     2
     3        [ESnext] Implement Object Rest - Implementing Object Rest Destructuring
     4        https://bugs.webkit.org/show_bug.cgi?id=167962
     5
     6        Reviewed by Saam Barati.
     7
     8        Object Rest/Spread Destructing proposal is in stage 3[1] and this
     9        Patch is a prototype implementation of it. A simple change over the
     10        parser was necessary to support the new '...' token on Object Pattern
     11        destruction rule. In the bytecode generator side, We changed the
     12        bytecode generated on ObjectPatternNode::bindValue to store in an
     13        set the identifiers of already destructured properties, following spec draft
     14        section[2], and then pass it as excludedNames to CopyDataProperties.
     15        The rest destructuring calls copyDataProperties to perform the
     16        copy of rest properties in rhs.
     17
     18        We also implemented CopyDataProperties as private JS global operation
     19        on builtins/GlobalOperations.js following it's specification on [3].
     20        It is implemented using Set object to verify if a property is on
     21        excludedNames to keep this algorithm with O(n + m) complexity, where n
     22        = number of source's own properties and m = excludedNames.length.
     23
     24        In this implementation we aren't using excludeList as constant if
     25        destructuring pattern contains computed property, i.e. we can
     26        just determine the key to be excluded at runtime. If we can define all
     27        identifiers in the pattern in compile time, we then create a
     28        constant JSSet. This approach gives a good performance improvement,
     29        since we allocate the excludeSet just once, reducing GC pressure.
     30
     31        [1] - https://github.com/tc39/proposal-object-rest-spread
     32        [2] - https://tc39.github.io/proposal-object-rest-spread/#Rest-RuntimeSemantics-PropertyDestructuringAssignmentEvaluation
     33        [3] - https://tc39.github.io/proposal-object-rest-spread/#AbstractOperations-CopyDataProperties
     34
     35        * builtins/BuiltinNames.h:
     36        * builtins/GlobalOperations.js:
     37        (globalPrivate.copyDataProperties):
     38        * bytecode/CodeBlock.cpp:
     39        (JSC::CodeBlock::finishCreation):
     40        * bytecompiler/NodesCodegen.cpp:
     41        (JSC::ObjectPatternNode::bindValue):
     42        * parser/ASTBuilder.h:
     43        (JSC::ASTBuilder::appendObjectPatternEntry):
     44        (JSC::ASTBuilder::appendObjectPatternRestEntry):
     45        (JSC::ASTBuilder::setContainsObjectRestElement):
     46        * parser/Nodes.h:
     47        (JSC::ObjectPatternNode::appendEntry):
     48        (JSC::ObjectPatternNode::setContainsRestElement):
     49        * parser/Parser.cpp:
     50        (JSC::Parser<LexerType>::parseDestructuringPattern):
     51        (JSC::Parser<LexerType>::parseProperty):
     52        * parser/SyntaxChecker.h:
     53        (JSC::SyntaxChecker::operatorStackPop):
     54        * runtime/JSGlobalObject.cpp:
     55        (JSC::JSGlobalObject::init):
     56        * runtime/JSGlobalObject.h:
     57        (JSC::JSGlobalObject::asyncFunctionStructure):
     58        (JSC::JSGlobalObject::setStructure): Deleted.
     59        * runtime/JSGlobalObjectFunctions.cpp:
     60        (JSC::privateToObject):
     61        * runtime/JSGlobalObjectFunctions.h:
     62        * runtime/ObjectConstructor.cpp:
     63        (JSC::ObjectConstructor::finishCreation):
     64        * runtime/SetPrototype.cpp:
     65        (JSC::SetPrototype::finishCreation):
     66
    1672017-06-27  Yusuke Suzuki  <utatane.tea@gmail.com>
    268
  • trunk/Source/JavaScriptCore/builtins/BuiltinNames.h

    r218790 r218861  
    3636    JSC_COMMON_BYTECODE_INTRINSIC_FUNCTIONS_EACH_NAME(macro) \
    3737    JSC_COMMON_BYTECODE_INTRINSIC_CONSTANTS_EACH_NAME(macro) \
     38    macro(add) \
    3839    macro(arrayIteratorNextIndex) \
    3940    macro(arrayIterationKind) \
     
    7374    macro(Error) \
    7475    macro(RangeError) \
     76    macro(Set) \
    7577    macro(TypeError) \
    7678    macro(typedArrayLength) \
  • trunk/Source/JavaScriptCore/builtins/GlobalOperations.js

    r217530 r218861  
    8080    @throwTypeError("|this|.constructor[Symbol.species] is not a constructor");
    8181}
     82
     83@globalPrivate
     84function copyDataProperties(target, source, excludedSet)
     85{
     86    if (!@isObject(target))
     87        @throwTypeError("target needs to be an object");
     88
     89    if (source == null)
     90        return target;
     91
     92    let from = @Object(source);
     93    let keys = @Reflect.@ownKeys(from);
     94    let keysLength = keys.length;
     95    for (let i = 0; i < keysLength; i++) {
     96        let nextKey = keys[i];
     97        if (!excludedSet.@has(nextKey)) {
     98            if (@propertyIsEnumerable(from, nextKey)) {
     99                let propValue = from[nextKey];
     100                @defineEnumerableWritableConfigurableDataProperty(target, nextKey, propValue);
     101            }
     102        }
     103    }
     104
     105    return target;
     106}
  • trunk/Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h

    r215916 r218861  
    5858    macro(toString) \
    5959    macro(newArrayWithSize) \
     60    macro(defineEnumerableWritableConfigurableDataProperty) \
    6061
    6162#define JSC_COMMON_BYTECODE_INTRINSIC_CONSTANTS_EACH_NAME(macro) \
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r218412 r218861  
    5959#include "JSLexicalEnvironment.h"
    6060#include "JSModuleEnvironment.h"
     61#include "JSSet.h"
     62#include "JSString.h"
    6163#include "JSTemplateRegistryKey.h"
    6264#include "LLIntData.h"
     
    406408    if (!setConstantRegisters(unlinkedCodeBlock->constantRegisters(), unlinkedCodeBlock->constantsSourceCodeRepresentation()))
    407409        return false;
     410
     411    if (!setConstantIdentifierSetRegisters(vm, unlinkedCodeBlock->constantIdentifierSets()))
     412        return false;
     413
    408414    if (unlinkedCodeBlock->usesGlobalObject())
    409415        m_constantRegisters[unlinkedCodeBlock->globalObjectRegister().toConstantIndex()].set(*m_vm, this, m_globalObject.get());
     
    862868    }
    863869#endif // ENABLE(JIT)
     870}
     871
     872bool CodeBlock::setConstantIdentifierSetRegisters(VM& vm, const Vector<ConstantIndentifierSetEntry>& constants)
     873{
     874    auto scope = DECLARE_THROW_SCOPE(vm);
     875    JSGlobalObject* globalObject = m_globalObject.get();
     876    ExecState* exec = globalObject->globalExec();
     877
     878    for (const auto& entry : constants) {
     879        Structure* setStructure = globalObject->setStructure();
     880        RETURN_IF_EXCEPTION(scope, false);
     881        JSSet* jsSet = JSSet::create(exec, vm, setStructure);
     882        RETURN_IF_EXCEPTION(scope, false);
     883
     884        const IdentifierSet& set = entry.first;
     885        for (auto setEntry : set) {
     886            JSString* jsString = jsOwnedString(&vm, setEntry.get());
     887            jsSet->add(exec, jsString);
     888            RETURN_IF_EXCEPTION(scope, false);
     889        }
     890        m_constantRegisters[entry.second].set(vm, this, jsSet);
     891    }
     892   
     893    scope.release();
     894    return true;
    864895}
    865896
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.h

    r218794 r218861  
    919919    void updateAllPredictionsAndCountLiveness(unsigned& numberOfLiveNonArgumentValueProfiles, unsigned& numberOfSamplesInProfiles);
    920920
     921    bool setConstantIdentifierSetRegisters(VM&, const Vector<ConstantIndentifierSetEntry>& constants);
     922
    921923    bool setConstantRegisters(const Vector<WriteBarrier<Unknown>>& constants, const Vector<SourceCodeRepresentation>& constantsSourceCodeRepresentation);
    922924
  • trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h

    r218794 r218861  
    3838#include "UnlinkedFunctionExecutable.h"
    3939#include "VirtualRegister.h"
     40#include <algorithm>
    4041#include <wtf/BitVector.h>
     42#include <wtf/HashSet.h>
    4143#include <wtf/TriState.h>
    4244#include <wtf/Vector.h>
     45#include <wtf/text/UniquedStringImpl.h>
    4346
    4447namespace JSC {
     
    6265typedef unsigned UnlinkedObjectAllocationProfile;
    6366typedef unsigned UnlinkedLLIntCallLinkInfo;
     67using ConstantIndentifierSetEntry = std::pair<IdentifierSet, unsigned>;
    6468
    6569struct UnlinkedStringJumpTable {
     
    180184    }
    181185
     186    void addSetConstant(IdentifierSet& set)
     187    {
     188        VM& vm = *this->vm();
     189        auto locker = lockDuringMarking(vm.heap, *this);
     190        unsigned result = m_constantRegisters.size();
     191        m_constantRegisters.append(WriteBarrier<Unknown>());
     192        m_constantsSourceCodeRepresentation.append(SourceCodeRepresentation::Other);
     193        m_constantIdentifierSets.append(ConstantIndentifierSetEntry(set, result));
     194    }
     195
    182196    unsigned addConstant(JSValue v, SourceCodeRepresentation sourceCodeRepresentation = SourceCodeRepresentation::Other)
    183197    {
     
    211225    }
    212226    const Vector<WriteBarrier<Unknown>>& constantRegisters() { return m_constantRegisters; }
     227    const Vector<ConstantIndentifierSetEntry>& constantIdentifierSets() { return m_constantIdentifierSets; }
    213228    const WriteBarrier<Unknown>& constantRegister(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex]; }
    214229    ALWAYS_INLINE bool isConstantRegisterIndex(int index) const { return index >= FirstConstantRegisterIndex; }
     
    444459    Vector<BitVector> m_bitVectors;
    445460    Vector<WriteBarrier<Unknown>> m_constantRegisters;
     461    Vector<ConstantIndentifierSetEntry> m_constantIdentifierSets;
    446462    Vector<SourceCodeRepresentation> m_constantsSourceCodeRepresentation;
    447463    typedef Vector<WriteBarrier<UnlinkedFunctionExecutable>> FunctionExpressionVector;
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r218794 r218861  
    16201620{
    16211621    if (!m_emptyValueRegister) {
    1622         int index = m_nextConstantOffset;
    1623         m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
    1624         ++m_nextConstantOffset;
     1622        int index = addConstantIndex();
    16251623        m_codeBlock->addConstant(JSValue());
    16261624        m_emptyValueRegister = &m_constantPoolRegisters[index];
     
    16421640    JSValueMap::AddResult result = m_jsValueMap.add(valueMapKey, m_nextConstantOffset);
    16431641    if (result.isNewEntry) {
    1644         m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
    1645         ++m_nextConstantOffset;
     1642        addConstantIndex();
    16461643        m_codeBlock->addConstant(v, sourceCodeRepresentation);
    16471644    } else
     
    16541651    unsigned constantIndex = static_cast<unsigned>(type);
    16551652    if (!m_linkTimeConstantRegisters[constantIndex]) {
    1656         int index = m_nextConstantOffset;
    1657         m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
    1658         ++m_nextConstantOffset;
     1653        int index = addConstantIndex();
    16591654        m_codeBlock->addConstant(type);
    16601655        m_linkTimeConstantRegisters[constantIndex] = &m_constantPoolRegisters[index];
     
    19281923}
    19291924
     1925unsigned BytecodeGenerator::addConstantIndex()
     1926{
     1927    unsigned index = m_nextConstantOffset;
     1928    m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
     1929    ++m_nextConstantOffset;
     1930    return index;
     1931}
     1932
    19301933RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, bool b)
    19311934{
     
    19511954}
    19521955
     1956RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, IdentifierSet& set)
     1957{
     1958    for (ConstantIndentifierSetEntry entry : m_codeBlock->constantIdentifierSets()) {
     1959        if (entry.first != set)
     1960            continue;
     1961       
     1962        return &m_constantPoolRegisters[entry.second];
     1963    }
     1964   
     1965    unsigned index = addConstantIndex();
     1966    m_codeBlock->addSetConstant(set);
     1967    RegisterID* m_setRegister = &m_constantPoolRegisters[index];
     1968   
     1969    if (dst)
     1970        return emitMove(dst, m_setRegister);
     1971   
     1972    return m_setRegister;
     1973}
     1974
    19531975RegisterID* BytecodeGenerator::emitLoadGlobalObject(RegisterID* dst)
    19541976{
    19551977    if (!m_globalObjectRegister) {
    1956         int index = m_nextConstantOffset;
    1957         m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
    1958         ++m_nextConstantOffset;
     1978        int index = addConstantIndex();
    19591979        m_codeBlock->addConstant(JSValue());
    19601980        m_globalObjectRegister = &m_constantPoolRegisters[index];
     
    31043124    return m_templateRegistryKeyMap.ensure(templateRegistryKey.copyRef(), [&] {
    31053125        auto* result = JSTemplateRegistryKey::create(*vm(), WTFMove(templateRegistryKey));
    3106         unsigned index = m_nextConstantOffset;
    3107         m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
    3108         ++m_nextConstantOffset;
     3126        unsigned index = addConstantIndex();
    31093127        m_codeBlock->addConstant(result);
    31103128        return &m_constantPoolRegisters[index];
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r218794 r218861  
    623623        RegisterID* emitLoadNewTargetFromArrowFunctionLexicalEnvironment();
    624624
     625        unsigned addConstantIndex();
    625626        RegisterID* emitLoad(RegisterID* dst, bool);
    626627        RegisterID* emitLoad(RegisterID* dst, const Identifier&);
    627628        RegisterID* emitLoad(RegisterID* dst, JSValue, SourceCodeRepresentation = SourceCodeRepresentation::Other);
     629        RegisterID* emitLoad(RegisterID* dst, IdentifierSet& excludedList);
    628630        RegisterID* emitLoadGlobalObject(RegisterID* dst);
    629631
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r218581 r218861  
    10951095}
    10961096
     1097RegisterID* BytecodeIntrinsicNode::emit_intrinsic_defineEnumerableWritableConfigurableDataProperty(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
     1098{
     1099    ArgumentListNode* node = m_args->m_listNode;
     1100    RefPtr<RegisterID> newObj = generator.emitNode(node);
     1101    node = node->m_next;
     1102    RefPtr<RegisterID> propertyNameRegister = generator.emitNode(node);
     1103    node = node->m_next;
     1104    RefPtr<RegisterID> value = generator.emitNode(node);
     1105    ASSERT(!node->m_next);
     1106
     1107    generator.emitCallDefineProperty(newObj.get(), propertyNameRegister.get(), value.get(), nullptr, nullptr, BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable | BytecodeGenerator::PropertyEnumerable, m_position);
     1108    return dst;
     1109}
    10971110
    10981111#define JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS(name) \
     
    40574070{
    40584071    generator.emitRequireObjectCoercible(rhs, ASCIILiteral("Right side of assignment cannot be destructured"));
    4059     for (const auto& target : m_targetPatterns) {
    4060         RefPtr<RegisterID> temp = generator.newTemporary();
    4061         if (!target.propertyExpression) {
    4062             // Should not emit get_by_id for indexed ones.
    4063             std::optional<uint32_t> optionalIndex = parseIndex(target.propertyName);
    4064             if (!optionalIndex)
    4065                 generator.emitGetById(temp.get(), rhs, target.propertyName);
     4072
     4073    RefPtr<RegisterID> excludedList;
     4074    IdentifierSet excludedSet;
     4075    RefPtr<RegisterID> addMethod;
     4076    if (m_containsRestElement && m_containsComputedProperty) {
     4077        auto var = generator.variable(generator.propertyNames().builtinNames().SetPrivateName());
     4078
     4079        RefPtr<RegisterID> scope = generator.newTemporary();
     4080        generator.moveToDestinationIfNeeded(scope.get(), generator.emitResolveScope(scope.get(), var));
     4081        RefPtr<RegisterID> setConstructor = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
     4082
     4083        CallArguments args(generator, nullptr, 0);
     4084        excludedList = generator.emitConstruct(generator.newTemporary(), setConstructor.get(), setConstructor.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd());
     4085
     4086        addMethod = generator.emitGetById(generator.newTemporary(), excludedList.get(), generator.propertyNames().builtinNames().addPrivateName());
     4087    }
     4088
     4089    for (size_t i = 0; i < m_targetPatterns.size(); i++) {
     4090        const auto& target = m_targetPatterns[i];
     4091        if (target.bindingType == BindingType::Element) {
     4092            RefPtr<RegisterID> temp = generator.newTemporary();
     4093            RefPtr<RegisterID> propertyName;
     4094            if (!target.propertyExpression) {
     4095                std::optional<uint32_t> optionalIndex = parseIndex(target.propertyName);
     4096                if (!optionalIndex)
     4097                    generator.emitGetById(temp.get(), rhs, target.propertyName);
     4098                else {
     4099                    RefPtr<RegisterID> propertyIndex = generator.emitLoad(nullptr, jsNumber(optionalIndex.value()));
     4100                    generator.emitGetByVal(temp.get(), rhs, propertyIndex.get());
     4101                }
     4102            } else {
     4103                propertyName = generator.emitNodeForProperty(target.propertyExpression);
     4104                generator.emitGetByVal(temp.get(), rhs, propertyName.get());
     4105            }
     4106
     4107            if (m_containsRestElement) {
     4108                if (m_containsComputedProperty) {
     4109                    if (!target.propertyExpression)
     4110                        propertyName = generator.emitLoad(nullptr, target.propertyName);
     4111
     4112                    CallArguments args(generator, nullptr, 1);
     4113                    generator.emitMove(args.thisRegister(), excludedList.get());
     4114                    generator.emitMove(args.argumentRegister(0), propertyName.get());
     4115                    generator.emitCall(generator.newTemporary(), addMethod.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd(), DebuggableCall::No);
     4116                } else
     4117                    excludedSet.add(target.propertyName.impl());
     4118            }
     4119
     4120            if (target.defaultValue)
     4121                assignDefaultValueIfUndefined(generator, temp.get(), target.defaultValue);
     4122            target.pattern->bindValue(generator, temp.get());
     4123        } else {
     4124            ASSERT(target.bindingType == BindingType::RestElement);
     4125            ASSERT(i == m_targetPatterns.size() - 1);
     4126            RefPtr<RegisterID> newObject = generator.emitNewObject(generator.newTemporary());
     4127           
     4128            // load and call @copyDataProperties
     4129            auto var = generator.variable(generator.propertyNames().builtinNames().copyDataPropertiesPrivateName());
     4130           
     4131            RefPtr<RegisterID> scope = generator.newTemporary();
     4132            generator.moveToDestinationIfNeeded(scope.get(), generator.emitResolveScope(scope.get(), var));
     4133            RefPtr<RegisterID> copyDataProperties = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
     4134           
     4135            CallArguments args(generator, nullptr, 3);
     4136            generator.emitLoad(args.thisRegister(), jsUndefined());
     4137            generator.emitMove(args.argumentRegister(0), newObject.get());
     4138            generator.emitMove(args.argumentRegister(1), rhs);
     4139            if (m_containsComputedProperty)
     4140                generator.emitMove(args.argumentRegister(2), excludedList.get());
    40664141            else {
    4067                 RefPtr<RegisterID> index = generator.emitLoad(nullptr, jsNumber(optionalIndex.value()));
    4068                 generator.emitGetByVal(temp.get(), rhs, index.get());
     4142                RefPtr<RegisterID> excludedSetReg = generator.emitLoad(generator.newTemporary(), excludedSet);
     4143                generator.emitMove(args.argumentRegister(2), excludedSetReg.get());
    40694144            }
    4070         } else {
    4071             RefPtr<RegisterID> propertyName = generator.emitNodeForProperty(target.propertyExpression);
    4072             generator.emitGetByVal(temp.get(), rhs, propertyName.get());
    4073         }
    4074 
    4075         if (target.defaultValue)
    4076             assignDefaultValueIfUndefined(generator, temp.get(), target.defaultValue);
    4077         target.pattern->bindValue(generator, temp.get());
     4145
     4146            RefPtr<RegisterID> result = generator.newTemporary();
     4147            generator.emitCall(result.get(), copyDataProperties.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd(), DebuggableCall::No);
     4148            target.pattern->bindValue(generator, result.get());
     4149        }
    40784150    }
    40794151}
  • trunk/Source/JavaScriptCore/parser/ASTBuilder.h

    r216891 r218861  
    945945    void appendObjectPatternEntry(ObjectPattern node, const JSTokenLocation& location, bool wasString, const Identifier& identifier, DestructuringPattern pattern, ExpressionNode* defaultValue)
    946946    {
    947         node->appendEntry(location, identifier, wasString, pattern, defaultValue);
     947        node->appendEntry(location, identifier, wasString, pattern, defaultValue, ObjectPatternNode::BindingType::Element);
    948948        tryInferNameInPattern(pattern, defaultValue);
    949949    }
    950950
    951     void appendObjectPatternEntry(ObjectPattern node, const JSTokenLocation& location, ExpressionNode* propertyExpression, DestructuringPattern pattern, ExpressionNode* defaultValue)
    952     {
    953         node->appendEntry(location, propertyExpression, pattern, defaultValue);
     951    void appendObjectPatternEntry(VM& vm, ObjectPattern node, const JSTokenLocation& location, ExpressionNode* propertyExpression, DestructuringPattern pattern, ExpressionNode* defaultValue)
     952    {
     953        node->appendEntry(vm, location, propertyExpression, pattern, defaultValue, ObjectPatternNode::BindingType::Element);
    954954        tryInferNameInPattern(pattern, defaultValue);
     955    }
     956   
     957    void appendObjectPatternRestEntry(VM& vm, ObjectPattern node, const JSTokenLocation& location, DestructuringPattern pattern)
     958    {
     959        node->appendEntry(vm, location, nullptr, pattern, nullptr, ObjectPatternNode::BindingType::RestElement);
     960    }
     961
     962    void setContainsObjectRestElement(ObjectPattern node, bool containsRestElement)
     963    {
     964        node->setContainsRestElement(containsRestElement);
     965    }
     966   
     967    void setContainsComputedProperty(ObjectPattern node, bool containsComputedProperty)
     968    {
     969        node->setContainsComputedProperty(containsComputedProperty);
    955970    }
    956971
  • trunk/Source/JavaScriptCore/parser/Nodes.h

    r218794 r218861  
    21342134    };
    21352135   
    2136     class ObjectPatternNode : public DestructuringPatternNode, public ParserArenaDeletable {
     2136    class ObjectPatternNode : public DestructuringPatternNode, public ThrowableExpressionData, public ParserArenaDeletable {
    21372137    public:
    21382138        using ParserArenaDeletable::operator new;
    21392139       
    21402140        ObjectPatternNode();
    2141         void appendEntry(const JSTokenLocation&, const Identifier& identifier, bool wasString, DestructuringPatternNode* pattern, ExpressionNode* defaultValue)
     2141        enum class BindingType {
     2142            Element,
     2143            RestElement
     2144        };
     2145        void appendEntry(const JSTokenLocation&, const Identifier& identifier, bool wasString, DestructuringPatternNode* pattern, ExpressionNode* defaultValue, BindingType bindingType)
    21422146        {
    2143             m_targetPatterns.append(Entry { identifier, nullptr, wasString, pattern, defaultValue });
     2147            m_targetPatterns.append(Entry{ identifier, nullptr, wasString, pattern, defaultValue, bindingType }); 
    21442148        }
    21452149
    2146         void appendEntry(const JSTokenLocation&, ExpressionNode* propertyExpression, DestructuringPatternNode* pattern, ExpressionNode* defaultValue)
     2150        void appendEntry(VM& vm, const JSTokenLocation&, ExpressionNode* propertyExpression, DestructuringPatternNode* pattern, ExpressionNode* defaultValue, BindingType bindingType)
    21472151        {
    2148             m_targetPatterns.append(Entry { Identifier(), propertyExpression, false, pattern, defaultValue });
     2152            m_targetPatterns.append(Entry{ vm.propertyNames->nullIdentifier, propertyExpression, false, pattern, defaultValue, bindingType });
     2153        }
     2154       
     2155        void setContainsRestElement(bool containsRestElement)
     2156        {
     2157            m_containsRestElement = containsRestElement;
     2158        }
     2159       
     2160        void setContainsComputedProperty(bool containsComputedProperty)
     2161        {
     2162            m_containsComputedProperty = containsComputedProperty;
    21492163        }
    21502164
     
    21592173            DestructuringPatternNode* pattern;
    21602174            ExpressionNode* defaultValue;
     2175            BindingType bindingType;
    21612176        };
     2177        bool m_containsRestElement { false };
     2178        bool m_containsComputedProperty { false };
    21622179        Vector<Entry> m_targetPatterns;
    21632180    };
  • trunk/Source/JavaScriptCore/parser/Parser.cpp

    r218794 r218861  
    139139    m_functionCache = vm->addSourceProviderCache(source.provider());
    140140    m_expressionErrorClassifier = nullptr;
     141    m_useObjectRestSpread = Options::useObjectRestSpread();
    141142
    142143    ScopeRef scope = pushScope();
     
    918919
    919920template <typename LexerType>
     921template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseObjectRestAssignmentElement(TreeBuilder& context)
     922{
     923    JSTextPosition startPosition = tokenStartPosition();
     924    auto element = parseMemberExpression(context);
     925
     926    if (!element || !context.isAssignmentLocation(element)) {
     927        reclassifyExpressionError(ErrorIndicatesPattern, ErrorIndicatesNothing);
     928        semanticFail("Invalid destructuring assignment target");
     929    }
     930
     931    if (strictMode() && m_parserState.lastIdentifier && context.isResolve(element)) {
     932        bool isEvalOrArguments = m_vm->propertyNames->eval == *m_parserState.lastIdentifier || m_vm->propertyNames->arguments == *m_parserState.lastIdentifier;
     933        if (isEvalOrArguments && strictMode())
     934            reclassifyExpressionError(ErrorIndicatesPattern, ErrorIndicatesNothing);
     935        failIfTrueIfStrict(isEvalOrArguments, "Cannot modify '", m_parserState.lastIdentifier->impl(), "' in strict mode");
     936    }
     937
     938    return createAssignmentElement(context, element, startPosition, lastTokenEndPosition());
     939}
     940
     941template <typename LexerType>
    920942template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseAssignmentElement(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth)
    921943{
     
    963985
    964986template <typename LexerType>
     987template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseObjectRestElement(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, AssignmentContext bindingContext)
     988{
     989    ASSERT(kind != DestructuringKind::DestructureToExpressions);
     990    failIfStackOverflow();
     991    TreeDestructuringPattern pattern;
     992   
     993    if (!matchSpecIdentifier()) {
     994        semanticFailureDueToKeyword(destructuringKindToVariableKindName(kind));
     995        failWithMessage("Expected a binding element");
     996    }
     997    failIfTrue(match(LET) && (kind == DestructuringKind::DestructureToLet || kind == DestructuringKind::DestructureToConst), "Cannot use 'let' as an identifier name for a LexicalDeclaration");
     998    semanticFailIfTrue(isDisallowedIdentifierAwait(m_token), "Cannot use 'await' as a ", destructuringKindToVariableKindName(kind), " ", disallowedIdentifierAwaitReason());
     999    pattern = createBindingPattern(context, kind, exportType, *m_token.m_data.ident, m_token, bindingContext, duplicateIdentifier);
     1000    next();
     1001    return pattern;
     1002}
     1003
     1004template <typename LexerType>
     1005template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseObjectRestBindingOrAssignmentElement(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, AssignmentContext bindingContext)
     1006{
     1007    if (kind == DestructuringKind::DestructureToExpressions)
     1008        return parseObjectRestAssignmentElement(context);
     1009    return parseObjectRestElement(context, kind, exportType, duplicateIdentifier, bindingContext);
     1010}
     1011
     1012template <typename LexerType>
    9651013template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseDestructuringPattern(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth)
    9661014{
     
    10231071            *hasDestructuringPattern = true;
    10241072
     1073        bool restElementWasFound = false;
     1074
    10251075        do {
    10261076            bool wasString = false;
     
    10281078            if (match(CLOSEBRACE))
    10291079                break;
     1080
     1081            if (match(DOTDOTDOT) && m_useObjectRestSpread) {
     1082                JSTokenLocation location = m_token.m_location;
     1083                next();
     1084                auto innerPattern = parseObjectRestBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, bindingContext);
     1085                propagateError();
     1086                if (!innerPattern)
     1087                    return 0;
     1088                context.appendObjectPatternRestEntry(*m_vm, objectPattern, location, innerPattern);
     1089                restElementWasFound = true;
     1090                context.setContainsObjectRestElement(objectPattern, restElementWasFound);
     1091                break;
     1092            }
    10301093
    10311094            const Identifier* propertyName = nullptr;
     
    10931156            TreeExpression defaultValue = parseDefaultValueForDestructuringPattern(context);
    10941157            propagateError();
    1095             if (propertyExpression)
    1096                 context.appendObjectPatternEntry(objectPattern, location, propertyExpression, innerPattern, defaultValue);
    1097             else {
     1158            if (propertyExpression) {
     1159                context.appendObjectPatternEntry(*m_vm, objectPattern, location, propertyExpression, innerPattern, defaultValue);
     1160                context.setContainsComputedProperty(objectPattern, true);
     1161            } else {
    10981162                ASSERT(propertyName);
    10991163                context.appendObjectPatternEntry(objectPattern, location, wasString, *propertyName, innerPattern, defaultValue);
     
    11031167        if (kind == DestructuringKind::DestructureToExpressions && !match(CLOSEBRACE))
    11041168            return 0;
    1105         consumeOrFail(CLOSEBRACE, "Expected either a closing '}' or an ',' after a property destructuring pattern");
     1169        consumeOrFail(CLOSEBRACE, restElementWasFound ? "Expected a closing '}' following a rest element destructuring pattern" : "Expected either a closing '}' or an ',' after a property destructuring pattern");
    11061170        pattern = objectPattern;
    11071171        break;
     
    38063870        return context.createProperty(propertyName, node, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed), PropertyNode::Unknown, complete, SuperBinding::NotNeeded, isClassProperty);
    38073871    }
     3872    case DOTDOTDOT: {
     3873        if (m_useObjectRestSpread) {
     3874            classifyExpressionError(ErrorIndicatesPattern);
     3875            return 0;
     3876        }
     3877        FALLTHROUGH;
     3878    }
    38083879    default:
    38093880        failIfFalse(m_token.m_type & KeywordTokenFlag, "Expected a property name");
  • trunk/Source/JavaScriptCore/parser/Parser.h

    r218794 r218861  
    15521552    template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern createBindingPattern(TreeBuilder&, DestructuringKind, ExportType, const Identifier&, JSToken, AssignmentContext, const Identifier** duplicateIdentifier);
    15531553    template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern createAssignmentElement(TreeBuilder&, TreeExpression&, const JSTextPosition&, const JSTextPosition&);
     1554    template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern parseObjectRestBindingOrAssignmentElement(TreeBuilder& context, DestructuringKind, ExportType, const Identifier** duplicateIdentifier, AssignmentContext bindingContext);
    15541555    template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern parseBindingOrAssignmentElement(TreeBuilder& context, DestructuringKind, ExportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth);
     1556    template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern parseObjectRestAssignmentElement(TreeBuilder& context);
    15551557    template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern parseAssignmentElement(TreeBuilder& context, DestructuringKind, ExportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth);
     1558    template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern parseObjectRestElement(TreeBuilder&, DestructuringKind, ExportType, const Identifier** duplicateIdentifier = nullptr, AssignmentContext = AssignmentContext::DeclarationStatement);
    15561559    template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern parseDestructuringPattern(TreeBuilder&, DestructuringKind, ExportType, const Identifier** duplicateIdentifier = nullptr, bool* hasDestructuringPattern = nullptr, AssignmentContext = AssignmentContext::DeclarationStatement, int depth = 0);
    15571560    template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern tryParseDestructuringPatternExpression(TreeBuilder&, AssignmentContext);
     
    17841787    ParserState m_parserState;
    17851788   
     1789    bool m_useObjectRestSpread;
    17861790    bool m_hasStackOverflow;
    17871791    String m_errorMessage;
  • trunk/Source/JavaScriptCore/parser/SyntaxChecker.h

    r216891 r218861  
    347347        return ObjectDestructuring;
    348348    }
    349     void appendObjectPatternEntry(ArrayPattern, const JSTokenLocation&, bool, const Identifier&, DestructuringPattern, int)
    350     {
    351     }
    352     void appendObjectPatternEntry(ArrayPattern, const JSTokenLocation&, Expression, DestructuringPattern, Expression)
     349    void appendObjectPatternEntry(ObjectPattern, const JSTokenLocation&, bool, const Identifier&, DestructuringPattern, int)
     350    {
     351    }
     352    void appendObjectPatternEntry(VM&, ObjectPattern, const JSTokenLocation&, Expression, DestructuringPattern, Expression)
     353    {
     354    }
     355    void appendObjectPatternRestEntry(VM&, ObjectPattern, const JSTokenLocation&, DestructuringPattern)
     356    {
     357    }
     358    void setContainsObjectRestElement(ObjectPattern, bool)
     359    {
     360    }
     361    void setContainsComputedProperty(ObjectPattern, bool)
    353362    {
    354363    }
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp

    r218836 r218861  
    291291  Float64Array          JSGlobalObject::m_typedArrayFloat64          DontEnum|ClassStructure
    292292  DataView              JSGlobalObject::m_typedArrayDataView         DontEnum|ClassStructure
    293   Set                   JSGlobalObject::m_setStructure               DontEnum|ClassStructure
    294293  Date                  JSGlobalObject::m_dateStructure              DontEnum|ClassStructure
    295294  Boolean               JSGlobalObject::m_booleanObjectStructure     DontEnum|ClassStructure
     
    822821        GlobalPropertyInfo(vm.propertyNames->builtinNames().InspectorInstrumentationPrivateName(), InspectorInstrumentationObject::create(vm, this, InspectorInstrumentationObject::createStructure(vm, this, m_objectPrototype.get())), DontEnum | DontDelete | ReadOnly),
    823822        GlobalPropertyInfo(vm.propertyNames->builtinNames().MapPrivateName(), mapConstructor, DontEnum | DontDelete | ReadOnly),
     823        GlobalPropertyInfo(vm.propertyNames->builtinNames().SetPrivateName(), setConstructor, DontEnum | DontDelete | ReadOnly),
    824824        GlobalPropertyInfo(vm.propertyNames->builtinNames().thisTimeValuePrivateName(), privateFuncThisTimeValue, DontEnum | DontDelete | ReadOnly),
    825825        GlobalPropertyInfo(vm.propertyNames->builtinNames().thisNumberValuePrivateName(), privateFuncThisNumberValue, DontEnum | DontDelete | ReadOnly),
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h

    r218836 r218861  
    630630    Structure* generatorFunctionStructure() const { return m_generatorFunctionStructure.get(); }
    631631    Structure* asyncFunctionStructure() const { return m_asyncFunctionStructure.get(); }
    632     Structure* setStructure() const { return m_setStructure.get(); }
    633632    Structure* stringObjectStructure() const { return m_stringObjectStructure.get(); }
    634633    Structure* symbolObjectStructure() const { return m_symbolObjectStructure.get(); }
  • trunk/Source/JavaScriptCore/runtime/Options.h

    r218007 r218861  
    463463    v(bool, useWebAssemblyFastTLS, true, Normal, "If true, we will try to use fast thread-local storage if available on the current platform.") \
    464464    v(bool, useFastTLSForWasmContext, true, Normal, "If true (and fast TLS is enabled), we will store context in fast TLS. If false, we will pin it to a register.") \
    465     v(bool, useCallICsForWebAssemblyToJSCalls, true, Normal, "If true, we will use CallLinkInfo to inline cache Wasm to JS calls.")
     465    v(bool, useCallICsForWebAssemblyToJSCalls, true, Normal, "If true, we will use CallLinkInfo to inline cache Wasm to JS calls.") \
     466    v(bool, useObjectRestSpread, true, Normal, "If true, we will enable Object Rest/Spread feature.")
    466467
    467468
  • trunk/Source/JavaScriptCore/runtime/SetPrototype.cpp

    r217192 r218861  
    6868    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->deleteKeyword, setProtoFuncDelete, DontEnum, 1);
    6969    JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->has, setProtoFuncHas, DontEnum, 1, JSSetHasIntrinsic);
     70    JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().hasPrivateName(), setProtoFuncHas, DontEnum, 1, JSSetHasIntrinsic);
     71    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().addPrivateName(), setProtoFuncAdd, DontEnum, 1);
    7072    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().entriesPublicName(), setProtoFuncEntries, DontEnum, 0);
    7173
  • trunk/Source/WTF/ChangeLog

    r218816 r218861  
     12017-06-27  Caio Lima  <ticaiolima@gmail.com>
     2
     3        [ESnext] Implement Object Rest - Implementing Object Rest Destructuring
     4        https://bugs.webkit.org/show_bug.cgi?id=167962
     5
     6        Reviewed by Saam Barati.
     7
     8        * wtf/HashSet.h:
     9        (WTF::=):
     10
    1112017-06-26  Yusuke Suzuki  <utatane.tea@gmail.com>
    212
  • trunk/Source/WTF/wtf/HashSet.h

    r216891 r218861  
    11/*
    2  * Copyright (C) 2005, 2006, 2007, 2008, 2011, 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2005, 2006, 2007, 2008, 2011, 2013, 2017 Apple Inc. All rights reserved.
    33 *
    44 * This library is free software; you can redistribute it and/or
     
    124124        template<typename OtherCollection>
    125125        bool operator==(const OtherCollection&) const;
     126       
     127        template<typename OtherCollection>
     128        bool operator!=(const OtherCollection&) const;
    126129
    127130    private:
     
    378381        return true;
    379382    }
     383   
     384    template<typename T, typename U, typename V>
     385    template<typename OtherCollection>
     386    inline bool HashSet<T, U, V>::operator!=(const OtherCollection& otherCollection) const
     387    {
     388        return !(*this == otherCollection);
     389    }
    380390
    381391} // namespace WTF
Note: See TracChangeset for help on using the changeset viewer.