Changeset 218861 in webkit
- Timestamp:
- Jun 27, 2017 8:05:47 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 25 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r218845 r218861 1 2017-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 1 18 2017-06-27 Saam Barati <sbarati@apple.com> 2 19 -
trunk/LayoutTests/ChangeLog
r218859 r218861 1 2017-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 1 11 2017-06-27 Yusuke Suzuki <utatane.tea@gmail.com> 2 12 -
trunk/LayoutTests/js/parser-syntax-check-expected.txt
r217200 r218861 1216 1216 PASS Invalid: "var [...y, ...z] = 20". Produced the following syntax error: "SyntaxError: Unexpected token ','. Expected a closing ']' following a rest element destructuring pattern." 1217 1217 PASS 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." 1218 PASS Valid: "var [...{...y}] = 20" with TypeError 1219 PASS Valid: "function f() { var [...{...y}] = 20 }" 1220 PASS Valid: "var {a, b, ...r} = {a: 1, b: 2, c: 3};" 1221 PASS Valid: "function f() { var {a, b, ...r} = {a: 1, b: 2, c: 3}; }" 1222 PASS 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." 1223 PASS 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." 1224 PASS 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." 1225 PASS 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." 1226 PASS 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." 1227 PASS 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." 1228 PASS Valid: "(({a, b, ...r}) => {})({a: 1, b: 2, c: 3, d: 4});" 1229 PASS Valid: "function f() { (({a, b, ...r}) => {})({a: 1, b: 2, c: 3, d: 4}); }" 1230 PASS Valid: "(function ({a, b, ...r}) {})({a: 1, b: 2, c: 3, d: 4});" 1231 PASS Valid: "function f() { (function ({a, b, ...r}) {})({a: 1, b: 2, c: 3, d: 4}); }" 1232 PASS Valid: "var a, b, c; ({a, b, ...r} = {a: 1, b: 2, c: 3, d: 4});" 1233 PASS Valid: "function f() { var a, b, c; ({a, b, ...r} = {a: 1, b: 2, c: 3, d: 4}); }" 1234 PASS Valid: "try { throw {a:2} } catch({...rest}) {}" 1235 PASS Valid: "function f() { try { throw {a:2} } catch({...rest}) {} }" 1236 PASS Invalid: "function * foo(o) { ({...{ x = yield }} = o); }". Produced the following syntax error: "SyntaxError: Unexpected token '='. Expected a ':' following the property name 'x'." 1237 PASS Invalid: "function f() { function * foo(o) { ({...{ x = yield }} = o); } }". Produced the following syntax error: "SyntaxError: Unexpected token '='. Expected a ':' following the property name 'x'." 1238 PASS 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." 1239 PASS 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." 1240 PASS 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." 1241 PASS 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." 1242 PASS 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." 1243 PASS 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." 1244 PASS Invalid: "({...new Object()} = {a: 1, b: 2});". Produced the following syntax error: "SyntaxError: Invalid destructuring assignment target." 1245 PASS Invalid: "function f() { ({...new Object()} = {a: 1, b: 2}); }". Produced the following syntax error: "SyntaxError: Invalid destructuring assignment target." 1246 PASS Invalid: "(function * (o) { ({ ...{ x: yield } } = o); })()". Produced the following syntax error: "SyntaxError: Invalid destructuring assignment target." 1247 PASS Invalid: "function f() { (function * (o) { ({ ...{ x: yield } } = o); })() }". Produced the following syntax error: "SyntaxError: Invalid destructuring assignment target." 1248 PASS Invalid: "(function () {'use strict'; ({...eval} = {}); })()". Produced the following syntax error: "SyntaxError: Cannot modify 'eval' in strict mode." 1249 PASS Invalid: "function f() { (function () {'use strict'; ({...eval} = {}); })() }". Produced the following syntax error: "SyntaxError: Cannot modify 'eval' in strict mode." 1250 PASS Invalid: "(function () {'use strict'; ({...arguments} = {}); })()". Produced the following syntax error: "SyntaxError: Cannot modify 'arguments' in strict mode." 1251 PASS Invalid: "function f() { (function () {'use strict'; ({...arguments} = {}); })() }". Produced the following syntax error: "SyntaxError: Cannot modify 'arguments' in strict mode." 1252 PASS Invalid: "async function foo () { let {...await} = {}; }". Produced the following syntax error: "SyntaxError: Cannot use 'await' as a lexical variable name in an async function." 1253 PASS 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." 1254 PASS 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." 1255 PASS 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." 1256 PASS 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." 1257 PASS 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." 1258 PASS 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." 1259 PASS 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." 1220 1260 Rest parameter 1221 1261 PASS Valid: "function foo(...a) { }" … … 1285 1325 PASS Valid: "let x = (a = 20, ...{b}) => { }" 1286 1326 PASS 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 '...'"1327 PASS Valid: "let x = (a = 20, ...{...b}) => { }" 1328 PASS Valid: "function f() { let x = (a = 20, ...{...b}) => { } }" 1289 1329 PASS Invalid: "let x = (a = 20, ...{124}) => { }". Produced the following syntax error: "SyntaxError: Unexpected token '...'" 1290 1330 PASS Invalid: "function f() { let x = (a = 20, ...{124}) => { } }". Produced the following syntax error: "SyntaxError: Unexpected token '...'" … … 1571 1611 PASS Invalid: "({ foo({a},...a){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters." 1572 1612 PASS 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."1613 PASS Invalid: "({ foo({...a},...a){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters." 1614 PASS Invalid: "function f() { ({ foo({...a},...a){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters." 1575 1615 PASS Invalid: "({ *foo({a},a){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters." 1576 1616 PASS Invalid: "function f() { ({ *foo({a},a){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters." … … 1581 1621 PASS Invalid: "({ *foo({a},...a){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters." 1582 1622 PASS 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."1623 PASS Invalid: "({ *foo({...a},...a){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters." 1624 PASS Invalid: "function f() { ({ *foo({...a},...a){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters." 1585 1625 PASS Invalid: "({ async foo({a},a){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters." 1586 1626 PASS Invalid: "function f() { ({ async foo({a},a){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters." … … 1591 1631 PASS Invalid: "({ async foo({a},...a){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters." 1592 1632 PASS 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."1633 PASS Invalid: "({ async foo({...a},...a){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters." 1634 PASS Invalid: "function f() { ({ async foo({...a},...a){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters." 1595 1635 PASS Valid: "({ foo(a, ...b){} });" 1596 1636 PASS Valid: "function f() { ({ foo(a, ...b){} }); }" 1597 1637 PASS Valid: "({ foo({a}, ...b){} });" 1598 1638 PASS 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."1639 PASS Valid: "({ foo({a, ...b}){} });" 1640 PASS Valid: "function f() { ({ foo({a, ...b}){} }); }" 1641 PASS Valid: "({ foo({b, ...a}, ...c){} });" 1642 PASS Valid: "function f() { ({ foo({b, ...a}, ...c){} }); }" 1603 1643 Weird things that used to crash. 1604 1644 PASS Invalid: "or ([[{break //(elseifo (a=0;a<2;a++)n= -
trunk/LayoutTests/js/script-tests/parser-syntax-check.js
r217200 r218861 716 716 valid("var {x: [y, {z: {z: [...z]}}]} = 20"); 717 717 invalid("var [...y, ...z] = 20"); 718 invalid("var [...{...y}] = 20"); 718 valid("var [...{...y}] = 20"); 719 valid("var {a, b, ...r} = {a: 1, b: 2, c: 3};"); 720 invalid("var {a, b, ...{d}} = {a: 1, b: 2, c: 3, d: 4};"); 721 invalid("var {a, b, ...{d = 15}} = {a: 1, b: 2, c: 3, d: 4};"); 722 invalid("var {a, b, ...{d = 15, ...r}} = {a: 1, b: 2, c: 3, d: 4};"); 723 valid("(({a, b, ...r}) => {})({a: 1, b: 2, c: 3, d: 4});"); 724 valid("(function ({a, b, ...r}) {})({a: 1, b: 2, c: 3, d: 4});"); 725 valid("var a, b, c; ({a, b, ...r} = {a: 1, b: 2, c: 3, d: 4});"); 726 valid("try { throw {a:2} } catch({...rest}) {}"); 727 invalid("function * foo(o) { ({...{ x = yield }} = o); }"); 728 invalid("var {...r = {a: 2}} = {a: 1, b: 2};"); 729 invalid("var {...r, b} = {a: 1, b: 2};"); 730 invalid("var {...r, ...e} = {a: 1, b: 2};"); 731 invalid("({...new Object()} = {a: 1, b: 2});"); 732 invalid("(function * (o) { ({ ...{ x: yield } } = o); })()"); 733 invalid("(function () {'use strict'; ({...eval} = {}); })()"); 734 invalid("(function () {'use strict'; ({...arguments} = {}); })()"); 735 invalid("async function foo () { let {...await} = {}; }"); 736 invalid("let {...let} = {a: 1, b: 2};"); 737 invalid("const {...let} = {a: 1, b: 2};"); 738 invalid("try { throw {a:2} } catch({...foo.a}) {}"); 719 739 720 740 debug("Rest parameter"); … … 752 772 valid("let x = (a = 20, ...[...[b = 40]]) => { }"); 753 773 valid("let x = (a = 20, ...{b}) => { }"); 754 invalid("let x = (a = 20, ...{...b}) => { }");774 valid("let x = (a = 20, ...{...b}) => { }"); 755 775 invalid("let x = (a = 20, ...{124}) => { }"); 756 776 … … 911 931 valid("({ foo(a, ...b){} });"); 912 932 valid("({ foo({a}, ...b){} });"); 913 invalid("({ foo({a, ...b}){} });");914 invalid("({ foo({b, ...a}, ...c){} });");933 valid("({ foo({a, ...b}){} });"); 934 valid("({ foo({b, ...a}, ...c){} });"); 915 935 916 936 debug("Weird things that used to crash."); -
trunk/Source/JavaScriptCore/ChangeLog
r218856 r218861 1 2017-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 1 67 2017-06-27 Yusuke Suzuki <utatane.tea@gmail.com> 2 68 -
trunk/Source/JavaScriptCore/builtins/BuiltinNames.h
r218790 r218861 36 36 JSC_COMMON_BYTECODE_INTRINSIC_FUNCTIONS_EACH_NAME(macro) \ 37 37 JSC_COMMON_BYTECODE_INTRINSIC_CONSTANTS_EACH_NAME(macro) \ 38 macro(add) \ 38 39 macro(arrayIteratorNextIndex) \ 39 40 macro(arrayIterationKind) \ … … 73 74 macro(Error) \ 74 75 macro(RangeError) \ 76 macro(Set) \ 75 77 macro(TypeError) \ 76 78 macro(typedArrayLength) \ -
trunk/Source/JavaScriptCore/builtins/GlobalOperations.js
r217530 r218861 80 80 @throwTypeError("|this|.constructor[Symbol.species] is not a constructor"); 81 81 } 82 83 @globalPrivate 84 function 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 58 58 macro(toString) \ 59 59 macro(newArrayWithSize) \ 60 macro(defineEnumerableWritableConfigurableDataProperty) \ 60 61 61 62 #define JSC_COMMON_BYTECODE_INTRINSIC_CONSTANTS_EACH_NAME(macro) \ -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r218412 r218861 59 59 #include "JSLexicalEnvironment.h" 60 60 #include "JSModuleEnvironment.h" 61 #include "JSSet.h" 62 #include "JSString.h" 61 63 #include "JSTemplateRegistryKey.h" 62 64 #include "LLIntData.h" … … 406 408 if (!setConstantRegisters(unlinkedCodeBlock->constantRegisters(), unlinkedCodeBlock->constantsSourceCodeRepresentation())) 407 409 return false; 410 411 if (!setConstantIdentifierSetRegisters(vm, unlinkedCodeBlock->constantIdentifierSets())) 412 return false; 413 408 414 if (unlinkedCodeBlock->usesGlobalObject()) 409 415 m_constantRegisters[unlinkedCodeBlock->globalObjectRegister().toConstantIndex()].set(*m_vm, this, m_globalObject.get()); … … 862 868 } 863 869 #endif // ENABLE(JIT) 870 } 871 872 bool 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; 864 895 } 865 896 -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.h
r218794 r218861 919 919 void updateAllPredictionsAndCountLiveness(unsigned& numberOfLiveNonArgumentValueProfiles, unsigned& numberOfSamplesInProfiles); 920 920 921 bool setConstantIdentifierSetRegisters(VM&, const Vector<ConstantIndentifierSetEntry>& constants); 922 921 923 bool setConstantRegisters(const Vector<WriteBarrier<Unknown>>& constants, const Vector<SourceCodeRepresentation>& constantsSourceCodeRepresentation); 922 924 -
trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h
r218794 r218861 38 38 #include "UnlinkedFunctionExecutable.h" 39 39 #include "VirtualRegister.h" 40 #include <algorithm> 40 41 #include <wtf/BitVector.h> 42 #include <wtf/HashSet.h> 41 43 #include <wtf/TriState.h> 42 44 #include <wtf/Vector.h> 45 #include <wtf/text/UniquedStringImpl.h> 43 46 44 47 namespace JSC { … … 62 65 typedef unsigned UnlinkedObjectAllocationProfile; 63 66 typedef unsigned UnlinkedLLIntCallLinkInfo; 67 using ConstantIndentifierSetEntry = std::pair<IdentifierSet, unsigned>; 64 68 65 69 struct UnlinkedStringJumpTable { … … 180 184 } 181 185 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 182 196 unsigned addConstant(JSValue v, SourceCodeRepresentation sourceCodeRepresentation = SourceCodeRepresentation::Other) 183 197 { … … 211 225 } 212 226 const Vector<WriteBarrier<Unknown>>& constantRegisters() { return m_constantRegisters; } 227 const Vector<ConstantIndentifierSetEntry>& constantIdentifierSets() { return m_constantIdentifierSets; } 213 228 const WriteBarrier<Unknown>& constantRegister(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex]; } 214 229 ALWAYS_INLINE bool isConstantRegisterIndex(int index) const { return index >= FirstConstantRegisterIndex; } … … 444 459 Vector<BitVector> m_bitVectors; 445 460 Vector<WriteBarrier<Unknown>> m_constantRegisters; 461 Vector<ConstantIndentifierSetEntry> m_constantIdentifierSets; 446 462 Vector<SourceCodeRepresentation> m_constantsSourceCodeRepresentation; 447 463 typedef Vector<WriteBarrier<UnlinkedFunctionExecutable>> FunctionExpressionVector; -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r218794 r218861 1620 1620 { 1621 1621 if (!m_emptyValueRegister) { 1622 int index = m_nextConstantOffset; 1623 m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset); 1624 ++m_nextConstantOffset; 1622 int index = addConstantIndex(); 1625 1623 m_codeBlock->addConstant(JSValue()); 1626 1624 m_emptyValueRegister = &m_constantPoolRegisters[index]; … … 1642 1640 JSValueMap::AddResult result = m_jsValueMap.add(valueMapKey, m_nextConstantOffset); 1643 1641 if (result.isNewEntry) { 1644 m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset); 1645 ++m_nextConstantOffset; 1642 addConstantIndex(); 1646 1643 m_codeBlock->addConstant(v, sourceCodeRepresentation); 1647 1644 } else … … 1654 1651 unsigned constantIndex = static_cast<unsigned>(type); 1655 1652 if (!m_linkTimeConstantRegisters[constantIndex]) { 1656 int index = m_nextConstantOffset; 1657 m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset); 1658 ++m_nextConstantOffset; 1653 int index = addConstantIndex(); 1659 1654 m_codeBlock->addConstant(type); 1660 1655 m_linkTimeConstantRegisters[constantIndex] = &m_constantPoolRegisters[index]; … … 1928 1923 } 1929 1924 1925 unsigned BytecodeGenerator::addConstantIndex() 1926 { 1927 unsigned index = m_nextConstantOffset; 1928 m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset); 1929 ++m_nextConstantOffset; 1930 return index; 1931 } 1932 1930 1933 RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, bool b) 1931 1934 { … … 1951 1954 } 1952 1955 1956 RegisterID* 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 1953 1975 RegisterID* BytecodeGenerator::emitLoadGlobalObject(RegisterID* dst) 1954 1976 { 1955 1977 if (!m_globalObjectRegister) { 1956 int index = m_nextConstantOffset; 1957 m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset); 1958 ++m_nextConstantOffset; 1978 int index = addConstantIndex(); 1959 1979 m_codeBlock->addConstant(JSValue()); 1960 1980 m_globalObjectRegister = &m_constantPoolRegisters[index]; … … 3104 3124 return m_templateRegistryKeyMap.ensure(templateRegistryKey.copyRef(), [&] { 3105 3125 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(); 3109 3127 m_codeBlock->addConstant(result); 3110 3128 return &m_constantPoolRegisters[index]; -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
r218794 r218861 623 623 RegisterID* emitLoadNewTargetFromArrowFunctionLexicalEnvironment(); 624 624 625 unsigned addConstantIndex(); 625 626 RegisterID* emitLoad(RegisterID* dst, bool); 626 627 RegisterID* emitLoad(RegisterID* dst, const Identifier&); 627 628 RegisterID* emitLoad(RegisterID* dst, JSValue, SourceCodeRepresentation = SourceCodeRepresentation::Other); 629 RegisterID* emitLoad(RegisterID* dst, IdentifierSet& excludedList); 628 630 RegisterID* emitLoadGlobalObject(RegisterID* dst); 629 631 -
trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
r218581 r218861 1095 1095 } 1096 1096 1097 RegisterID* 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 } 1097 1110 1098 1111 #define JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS(name) \ … … 4057 4070 { 4058 4071 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()); 4066 4141 else { 4067 RefPtr<RegisterID> index = generator.emitLoad(nullptr, jsNumber(optionalIndex.value()));4068 generator.emit GetByVal(temp.get(), rhs, index.get());4142 RefPtr<RegisterID> excludedSetReg = generator.emitLoad(generator.newTemporary(), excludedSet); 4143 generator.emitMove(args.argumentRegister(2), excludedSetReg.get()); 4069 4144 } 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 } 4078 4150 } 4079 4151 } -
trunk/Source/JavaScriptCore/parser/ASTBuilder.h
r216891 r218861 945 945 void appendObjectPatternEntry(ObjectPattern node, const JSTokenLocation& location, bool wasString, const Identifier& identifier, DestructuringPattern pattern, ExpressionNode* defaultValue) 946 946 { 947 node->appendEntry(location, identifier, wasString, pattern, defaultValue );947 node->appendEntry(location, identifier, wasString, pattern, defaultValue, ObjectPatternNode::BindingType::Element); 948 948 tryInferNameInPattern(pattern, defaultValue); 949 949 } 950 950 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); 954 954 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); 955 970 } 956 971 -
trunk/Source/JavaScriptCore/parser/Nodes.h
r218794 r218861 2134 2134 }; 2135 2135 2136 class ObjectPatternNode : public DestructuringPatternNode, public ParserArenaDeletable {2136 class ObjectPatternNode : public DestructuringPatternNode, public ThrowableExpressionData, public ParserArenaDeletable { 2137 2137 public: 2138 2138 using ParserArenaDeletable::operator new; 2139 2139 2140 2140 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) 2142 2146 { 2143 m_targetPatterns.append(Entry { identifier, nullptr, wasString, pattern, defaultValue });2147 m_targetPatterns.append(Entry{ identifier, nullptr, wasString, pattern, defaultValue, bindingType }); 2144 2148 } 2145 2149 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) 2147 2151 { 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; 2149 2163 } 2150 2164 … … 2159 2173 DestructuringPatternNode* pattern; 2160 2174 ExpressionNode* defaultValue; 2175 BindingType bindingType; 2161 2176 }; 2177 bool m_containsRestElement { false }; 2178 bool m_containsComputedProperty { false }; 2162 2179 Vector<Entry> m_targetPatterns; 2163 2180 }; -
trunk/Source/JavaScriptCore/parser/Parser.cpp
r218794 r218861 139 139 m_functionCache = vm->addSourceProviderCache(source.provider()); 140 140 m_expressionErrorClassifier = nullptr; 141 m_useObjectRestSpread = Options::useObjectRestSpread(); 141 142 142 143 ScopeRef scope = pushScope(); … … 918 919 919 920 template <typename LexerType> 921 template <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 941 template <typename LexerType> 920 942 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseAssignmentElement(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth) 921 943 { … … 963 985 964 986 template <typename LexerType> 987 template <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 1004 template <typename LexerType> 1005 template <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 1012 template <typename LexerType> 965 1013 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseDestructuringPattern(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth) 966 1014 { … … 1023 1071 *hasDestructuringPattern = true; 1024 1072 1073 bool restElementWasFound = false; 1074 1025 1075 do { 1026 1076 bool wasString = false; … … 1028 1078 if (match(CLOSEBRACE)) 1029 1079 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 } 1030 1093 1031 1094 const Identifier* propertyName = nullptr; … … 1093 1156 TreeExpression defaultValue = parseDefaultValueForDestructuringPattern(context); 1094 1157 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 { 1098 1162 ASSERT(propertyName); 1099 1163 context.appendObjectPatternEntry(objectPattern, location, wasString, *propertyName, innerPattern, defaultValue); … … 1103 1167 if (kind == DestructuringKind::DestructureToExpressions && !match(CLOSEBRACE)) 1104 1168 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"); 1106 1170 pattern = objectPattern; 1107 1171 break; … … 3806 3870 return context.createProperty(propertyName, node, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed), PropertyNode::Unknown, complete, SuperBinding::NotNeeded, isClassProperty); 3807 3871 } 3872 case DOTDOTDOT: { 3873 if (m_useObjectRestSpread) { 3874 classifyExpressionError(ErrorIndicatesPattern); 3875 return 0; 3876 } 3877 FALLTHROUGH; 3878 } 3808 3879 default: 3809 3880 failIfFalse(m_token.m_type & KeywordTokenFlag, "Expected a property name"); -
trunk/Source/JavaScriptCore/parser/Parser.h
r218794 r218861 1552 1552 template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern createBindingPattern(TreeBuilder&, DestructuringKind, ExportType, const Identifier&, JSToken, AssignmentContext, const Identifier** duplicateIdentifier); 1553 1553 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); 1554 1555 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); 1555 1557 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); 1556 1559 template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern parseDestructuringPattern(TreeBuilder&, DestructuringKind, ExportType, const Identifier** duplicateIdentifier = nullptr, bool* hasDestructuringPattern = nullptr, AssignmentContext = AssignmentContext::DeclarationStatement, int depth = 0); 1557 1560 template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern tryParseDestructuringPatternExpression(TreeBuilder&, AssignmentContext); … … 1784 1787 ParserState m_parserState; 1785 1788 1789 bool m_useObjectRestSpread; 1786 1790 bool m_hasStackOverflow; 1787 1791 String m_errorMessage; -
trunk/Source/JavaScriptCore/parser/SyntaxChecker.h
r216891 r218861 347 347 return ObjectDestructuring; 348 348 } 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) 353 362 { 354 363 } -
trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
r218836 r218861 291 291 Float64Array JSGlobalObject::m_typedArrayFloat64 DontEnum|ClassStructure 292 292 DataView JSGlobalObject::m_typedArrayDataView DontEnum|ClassStructure 293 Set JSGlobalObject::m_setStructure DontEnum|ClassStructure294 293 Date JSGlobalObject::m_dateStructure DontEnum|ClassStructure 295 294 Boolean JSGlobalObject::m_booleanObjectStructure DontEnum|ClassStructure … … 822 821 GlobalPropertyInfo(vm.propertyNames->builtinNames().InspectorInstrumentationPrivateName(), InspectorInstrumentationObject::create(vm, this, InspectorInstrumentationObject::createStructure(vm, this, m_objectPrototype.get())), DontEnum | DontDelete | ReadOnly), 823 822 GlobalPropertyInfo(vm.propertyNames->builtinNames().MapPrivateName(), mapConstructor, DontEnum | DontDelete | ReadOnly), 823 GlobalPropertyInfo(vm.propertyNames->builtinNames().SetPrivateName(), setConstructor, DontEnum | DontDelete | ReadOnly), 824 824 GlobalPropertyInfo(vm.propertyNames->builtinNames().thisTimeValuePrivateName(), privateFuncThisTimeValue, DontEnum | DontDelete | ReadOnly), 825 825 GlobalPropertyInfo(vm.propertyNames->builtinNames().thisNumberValuePrivateName(), privateFuncThisNumberValue, DontEnum | DontDelete | ReadOnly), -
trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h
r218836 r218861 630 630 Structure* generatorFunctionStructure() const { return m_generatorFunctionStructure.get(); } 631 631 Structure* asyncFunctionStructure() const { return m_asyncFunctionStructure.get(); } 632 Structure* setStructure() const { return m_setStructure.get(); }633 632 Structure* stringObjectStructure() const { return m_stringObjectStructure.get(); } 634 633 Structure* symbolObjectStructure() const { return m_symbolObjectStructure.get(); } -
trunk/Source/JavaScriptCore/runtime/Options.h
r218007 r218861 463 463 v(bool, useWebAssemblyFastTLS, true, Normal, "If true, we will try to use fast thread-local storage if available on the current platform.") \ 464 464 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.") 466 467 467 468 -
trunk/Source/JavaScriptCore/runtime/SetPrototype.cpp
r217192 r218861 68 68 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->deleteKeyword, setProtoFuncDelete, DontEnum, 1); 69 69 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); 70 72 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().entriesPublicName(), setProtoFuncEntries, DontEnum, 0); 71 73 -
trunk/Source/WTF/ChangeLog
r218816 r218861 1 2017-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 1 11 2017-06-26 Yusuke Suzuki <utatane.tea@gmail.com> 2 12 -
trunk/Source/WTF/wtf/HashSet.h
r216891 r218861 1 1 /* 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. 3 3 * 4 4 * This library is free software; you can redistribute it and/or … … 124 124 template<typename OtherCollection> 125 125 bool operator==(const OtherCollection&) const; 126 127 template<typename OtherCollection> 128 bool operator!=(const OtherCollection&) const; 126 129 127 130 private: … … 378 381 return true; 379 382 } 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 } 380 390 381 391 } // namespace WTF
Note: See TracChangeset
for help on using the changeset viewer.