Changeset 219443 in webkit
- Timestamp:
- Jul 13, 2017 12:11:45 AM (7 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r219433 r219443 1 2017-07-13 Caio Lima <ticaiolima@gmail.com> 2 3 [ESnext] Implement Object Spread 4 https://bugs.webkit.org/show_bug.cgi?id=167963 5 6 Reviewed by Saam Barati. 7 8 * stress/obj-rest-destructuring-order.js: Added. 9 (assert): 10 (o.get z): 11 (o.get a): 12 * stress/obj-spread-order.js: Added. 13 (assert): 14 (o.get z): 15 (o.get a): 16 * stress/object-spread.js: Added. 17 (let.assert): 18 (assert.sameValue): 19 (let.o.get a): 20 (let.obj.get c): 21 (cthulhu.get x): 22 (let.obj.set c): 23 (calls.o.get z): 24 (calls.o.get a): 25 (try.let.obj.get foo): 26 (get calls): 27 1 28 2017-07-12 Saam Barati <sbarati@apple.com> 2 29 -
trunk/LayoutTests/ChangeLog
r219426 r219443 1 2017-07-13 Caio Lima <ticaiolima@gmail.com> 2 3 [ESnext] Implement Object Spread 4 https://bugs.webkit.org/show_bug.cgi?id=167963 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-07-12 Nan Wang <n_wang@apple.com> 2 12 -
trunk/LayoutTests/js/parser-syntax-check-expected.txt
r218861 r219443 1234 1234 PASS Valid: "try { throw {a:2} } catch({...rest}) {}" 1235 1235 PASS Valid: "function f() { try { throw {a:2} } catch({...rest}) {} }" 1236 PASS Valid: "let c = {}; let o = {a: 1, b: 2, ...c};" 1237 PASS Valid: "function f() { let c = {}; let o = {a: 1, b: 2, ...c}; }" 1238 PASS Valid: "let o = {a: 1, b: 3, ...{}};" 1239 PASS Valid: "function f() { let o = {a: 1, b: 3, ...{}}; }" 1240 PASS Valid: "let o = {a: 1, b: 2, ...null, c: 3};" 1241 PASS Valid: "function f() { let o = {a: 1, b: 2, ...null, c: 3}; }" 1242 PASS Valid: "let o = {a: 1, b: 2, ...undefined, c: 3};" 1243 PASS Valid: "function f() { let o = {a: 1, b: 2, ...undefined, c: 3}; }" 1244 PASS Valid: "let o = {a: 1, b: 2, ...{...{}}, c: 3};" 1245 PASS Valid: "function f() { let o = {a: 1, b: 2, ...{...{}}, c: 3}; }" 1246 PASS Valid: "let c = {}; let o = {a: 1, b: 2, ...c, d: 3, ...c, e: 5};" 1247 PASS Valid: "function f() { let c = {}; let o = {a: 1, b: 2, ...c, d: 3, ...c, e: 5}; }" 1248 PASS Valid: "let o = {a: 1, b: 2, ...d = {e: 2}, c: 3};" 1249 PASS Valid: "function f() { let o = {a: 1, b: 2, ...d = {e: 2}, c: 3}; }" 1250 PASS Valid: "let p = true; let o = {a: 1, b: 2, ...d = p ? {e: 2} : {f: 4}, c: 3};" 1251 PASS Valid: "function f() { let p = true; let o = {a: 1, b: 2, ...d = p ? {e: 2} : {f: 4}, c: 3}; }" 1252 PASS Valid: "let o = {a: 1, b: 2, ...(a) => 3, c: 3};" 1253 PASS Valid: "function f() { let o = {a: 1, b: 2, ...(a) => 3, c: 3}; }" 1254 PASS Valid: "function * foo() { return {a: 1, b: 2, ...yield, c: 3}; }" 1255 PASS Valid: "function f() { function * foo() { return {a: 1, b: 2, ...yield, c: 3}; } }" 1236 1256 PASS Invalid: "function * foo(o) { ({...{ x = yield }} = o); }". Produced the following syntax error: "SyntaxError: Unexpected token '='. Expected a ':' following the property name 'x'." 1237 1257 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'." -
trunk/LayoutTests/js/script-tests/parser-syntax-check.js
r218861 r219443 725 725 valid("var a, b, c; ({a, b, ...r} = {a: 1, b: 2, c: 3, d: 4});"); 726 726 valid("try { throw {a:2} } catch({...rest}) {}"); 727 valid("let c = {}; let o = {a: 1, b: 2, ...c};"); 728 valid("let o = {a: 1, b: 3, ...{}};"); 729 valid("let o = {a: 1, b: 2, ...null, c: 3};"); 730 valid("let o = {a: 1, b: 2, ...undefined, c: 3};"); 731 valid("let o = {a: 1, b: 2, ...{...{}}, c: 3};"); 732 valid("let c = {}; let o = {a: 1, b: 2, ...c, d: 3, ...c, e: 5};"); 733 valid("let o = {a: 1, b: 2, ...d = {e: 2}, c: 3};"); 734 valid("let p = true; let o = {a: 1, b: 2, ...d = p ? {e: 2} : {f: 4}, c: 3};"); 735 valid("let o = {a: 1, b: 2, ...(a) => 3, c: 3};"); 736 valid("function * foo() { return {a: 1, b: 2, ...yield, c: 3}; }"); 727 737 invalid("function * foo(o) { ({...{ x = yield }} = o); }"); 728 738 invalid("var {...r = {a: 2}} = {a: 1, b: 2};"); -
trunk/Source/JavaScriptCore/ChangeLog
r219437 r219443 1 2017-07-13 Caio Lima <ticaiolima@gmail.com> 2 3 [ESnext] Implement Object Spread 4 https://bugs.webkit.org/show_bug.cgi?id=167963 5 6 Reviewed by Saam Barati. 7 8 This patch implements ECMA262 stage 3 Object Spread proposal [1]. 9 It's implemented using CopyDataPropertiesNoExclusions to copy 10 all enumerable keys from object being spreaded. The implementation of 11 CopyDataPropertiesNoExclusions follows the CopyDataProperties 12 implementation, however we don't receive excludedNames as parameter. 13 14 [1] - https://github.com/tc39/proposal-object-rest-spread 15 16 * builtins/GlobalOperations.js: 17 (globalPrivate.copyDataPropertiesNoExclusions): 18 * bytecompiler/BytecodeGenerator.cpp: 19 (JSC::BytecodeGenerator::emitLoad): 20 * bytecompiler/NodesCodegen.cpp: 21 (JSC::PropertyListNode::emitBytecode): 22 (JSC::ObjectSpreadExpressionNode::emitBytecode): 23 * parser/ASTBuilder.h: 24 (JSC::ASTBuilder::createObjectSpreadExpression): 25 (JSC::ASTBuilder::createProperty): 26 * parser/NodeConstructors.h: 27 (JSC::PropertyNode::PropertyNode): 28 (JSC::ObjectSpreadExpressionNode::ObjectSpreadExpressionNode): 29 * parser/Nodes.h: 30 (JSC::ObjectSpreadExpressionNode::expression): 31 * parser/Parser.cpp: 32 (JSC::Parser<LexerType>::parseProperty): 33 * parser/SyntaxChecker.h: 34 (JSC::SyntaxChecker::createObjectSpreadExpression): 35 (JSC::SyntaxChecker::createProperty): 36 1 37 2017-07-12 Mark Lam <mark.lam@apple.com> 2 38 -
trunk/Source/JavaScriptCore/builtins/GlobalOperations.js
r218861 r219443 1 1 /* 2 2 * Copyright (C) 2016 Yusuke Suzuki <utatane.tea@gmail.com>. 3 * Copyright (C) 2017 Caio Lima <ticaiolima@gmail.com>. 3 4 * 4 5 * Redistribution and use in source and binary forms, with or without … … 105 106 return target; 106 107 } 108 109 @globalPrivate 110 function copyDataPropertiesNoExclusions(target, source) 111 { 112 if (!@isObject(target)) 113 @throwTypeError("target needs to be an object"); 114 115 if (source == null) 116 return target; 117 118 let from = @Object(source); 119 let keys = @Reflect.@ownKeys(from); 120 let keysLength = keys.length; 121 for (let i = 0; i < keysLength; i++) { 122 let nextKey = keys[i]; 123 if (@propertyIsEnumerable(from, nextKey)) { 124 let propValue = from[nextKey]; 125 @defineEnumerableWritableConfigurableDataProperty(target, nextKey, propValue); 126 } 127 } 128 129 return target; 130 } -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r219209 r219443 1957 1957 RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, IdentifierSet& set) 1958 1958 { 1959 for ( ConstantIndentifierSetEntryentry : m_codeBlock->constantIdentifierSets()) {1959 for (const auto& entry : m_codeBlock->constantIdentifierSets()) { 1960 1960 if (entry.first != set) 1961 1961 continue; -
trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
r219209 r219443 501 501 if (p) { 502 502 // Build a list of getter/setter pairs to try to put them at the same time. If we encounter 503 // a computed property , just emit everything as that may override previous values.504 bool hasComputedProperty= false;503 // a computed property or a spread, just emit everything as that may override previous values. 504 bool canOverrideProperties = false; 505 505 506 506 typedef std::pair<PropertyNode*, PropertyNode*> GetterSetterPair; … … 511 511 for (PropertyListNode* q = p; q; q = q->m_next) { 512 512 PropertyNode* node = q->m_node; 513 if (node->m_type & PropertyNode::Computed ) {514 hasComputedProperty= true;513 if (node->m_type & PropertyNode::Computed || node->m_type & PropertyNode::Spread) { 514 canOverrideProperties = true; 515 515 break; 516 516 } 517 517 518 if (node->m_type & PropertyNode::Constant) 518 519 continue; … … 537 538 emitPutConstantProperty(generator, dst, *node); 538 539 continue; 540 } else if (node->m_type & PropertyNode::Spread) { 541 generator.emitNode(dst, node->m_assign); 542 continue; 539 543 } 540 544 … … 548 552 ASSERT(node->m_type & (PropertyNode::Getter | PropertyNode::Setter)); 549 553 550 // This is a get/set property which may be overridden by a computed property later.551 if ( hasComputedProperty) {554 // This is a get/set property which may be overridden by a computed property or spread later. 555 if (canOverrideProperties) { 552 556 // Computed accessors. 553 557 if (node->m_type & PropertyNode::Computed) { … … 4278 4282 } 4279 4283 4284 RegisterID* ObjectSpreadExpressionNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 4285 { 4286 RefPtr<RegisterID> src = generator.newTemporary(); 4287 generator.emitNode(src.get(), m_expression); 4288 4289 // load and call @copyDataPropertiesNoExclusions 4290 auto var = generator.variable(generator.propertyNames().builtinNames().copyDataPropertiesNoExclusionsPrivateName()); 4291 4292 RefPtr<RegisterID> scope = generator.newTemporary(); 4293 generator.moveToDestinationIfNeeded(scope.get(), generator.emitResolveScope(scope.get(), var)); 4294 RefPtr<RegisterID> copyDataProperties = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound); 4295 4296 CallArguments args(generator, nullptr, 2); 4297 generator.emitLoad(args.thisRegister(), jsUndefined()); 4298 generator.emitMove(args.argumentRegister(0), dst); 4299 generator.emitMove(args.argumentRegister(1), src.get()); 4300 4301 generator.emitCall(generator.newTemporary(), copyDataProperties.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd(), DebuggableCall::No); 4302 4303 return dst; 4304 } 4305 4280 4306 } // namespace JSC -
trunk/Source/JavaScriptCore/parser/ASTBuilder.h
r218861 r219443 276 276 } 277 277 278 ExpressionNode* createObjectSpreadExpression(const JSTokenLocation& location, ExpressionNode* expression, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end) 279 { 280 auto node = new (m_parserArena) ObjectSpreadExpressionNode(location, expression); 281 setExceptionLocation(node, start, divot, end); 282 return node; 283 } 284 278 285 TemplateStringNode* createTemplateString(const JSTokenLocation& location, const Identifier* cooked, const Identifier* raw) 279 286 { … … 495 502 } 496 503 return new (m_parserArena) PropertyNode(*propertyName, node, type, putType, superBinding, isClassProperty); 504 } 505 PropertyNode* createProperty(ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, bool, SuperBinding superBinding, bool isClassProperty) 506 { 507 return new (m_parserArena) PropertyNode(node, type, putType, superBinding, isClassProperty); 497 508 } 498 509 PropertyNode* createProperty(VM* vm, ParserArena& parserArena, double propertyName, ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, bool, SuperBinding superBinding, bool isClassProperty) -
trunk/Source/JavaScriptCore/parser/NodeConstructors.h
r218794 r219443 233 233 { 234 234 } 235 236 inline PropertyNode::PropertyNode(ExpressionNode* assign, Type type, PutType putType, SuperBinding superBinding, bool isClassProperty) 237 : m_name(nullptr) 238 , m_assign(assign) 239 , m_type(type) 240 , m_needsSuperBinding(superBinding == SuperBinding::Needed) 241 , m_putType(putType) 242 , m_isClassProperty(isClassProperty) 243 { 244 } 235 245 236 246 inline PropertyNode::PropertyNode(ExpressionNode* name, ExpressionNode* assign, Type type, PutType putType, SuperBinding superBinding, bool isClassProperty) 237 : m_name( 0)247 : m_name(nullptr) 238 248 , m_expression(name) 239 249 , m_assign(assign) … … 289 299 290 300 inline SpreadExpressionNode::SpreadExpressionNode(const JSTokenLocation& location, ExpressionNode* expression) 301 : ExpressionNode(location) 302 , m_expression(expression) 303 { 304 } 305 306 inline ObjectSpreadExpressionNode::ObjectSpreadExpressionNode(const JSTokenLocation& location, ExpressionNode* expression) 291 307 : ExpressionNode(location) 292 308 , m_expression(expression) -
trunk/Source/JavaScriptCore/parser/Nodes.h
r218957 r219443 646 646 class PropertyNode : public ParserArenaFreeable { 647 647 public: 648 enum Type { Constant = 1, Getter = 2, Setter = 4, Computed = 8, Shorthand = 16 };648 enum Type { Constant = 1, Getter = 2, Setter = 4, Computed = 8, Shorthand = 16, Spread = 32 }; 649 649 enum PutType { Unknown, KnownDirect }; 650 650 651 651 PropertyNode(const Identifier&, ExpressionNode*, Type, PutType, SuperBinding, bool isClassProperty); 652 PropertyNode(ExpressionNode*, Type, PutType, SuperBinding, bool isClassProperty); 652 653 PropertyNode(ExpressionNode* propertyName, ExpressionNode*, Type, PutType, SuperBinding, bool isClassProperty); 653 654 … … 665 666 ExpressionNode* m_expression; 666 667 ExpressionNode* m_assign; 667 unsigned m_type : 5;668 unsigned m_type : 6; 668 669 unsigned m_needsSuperBinding : 1; 669 670 unsigned m_putType : 1; … … 745 746 746 747 bool isSpreadExpression() const override { return true; } 748 ExpressionNode* m_expression; 749 }; 750 751 class ObjectSpreadExpressionNode : public ExpressionNode, public ThrowableExpressionData { 752 public: 753 ObjectSpreadExpressionNode(const JSTokenLocation&, ExpressionNode*); 754 755 ExpressionNode* expression() const { return m_expression; } 756 757 private: 758 RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; 759 747 760 ExpressionNode* m_expression; 748 761 }; -
trunk/Source/JavaScriptCore/parser/Parser.cpp
r218861 r219443 3872 3872 case DOTDOTDOT: { 3873 3873 if (m_useObjectRestSpread) { 3874 classifyExpressionError(ErrorIndicatesPattern); 3875 return 0; 3874 auto spreadLocation = m_token.m_location; 3875 auto start = m_token.m_startPosition; 3876 auto divot = m_token.m_endPosition; 3877 next(); 3878 TreeExpression elem = parseAssignmentExpressionOrPropagateErrorClass(context); 3879 failIfFalse(elem, "Cannot parse subject of a spread operation"); 3880 auto node = context.createObjectSpreadExpression(spreadLocation, elem, start, divot, m_lastTokenEndPosition); 3881 return context.createProperty(node, PropertyNode::Spread, PropertyNode::Unknown, complete, SuperBinding::NotNeeded, isClassProperty); 3876 3882 } 3877 3883 FALLTHROUGH; -
trunk/Source/JavaScriptCore/parser/SyntaxChecker.h
r218861 r219443 77 77 DeleteExpr, ArrayLiteralExpr, BindingDestructuring, RestParameter, 78 78 ArrayDestructuring, ObjectDestructuring, SourceElementsResult, 79 FunctionBodyResult, SpreadExpr, ArgumentsResult,79 FunctionBodyResult, SpreadExpr, ObjectSpreadExpr, ArgumentsResult, 80 80 PropertyListResult, ArgumentsListResult, ElementsListResult, 81 81 StatementResult, FormalParameterListResult, ClauseResult, … … 195 195 int createArguments(int) { return ArgumentsResult; } 196 196 ExpressionType createSpreadExpression(const JSTokenLocation&, ExpressionType, int, int, int) { return SpreadExpr; } 197 ExpressionType createObjectSpreadExpression(const JSTokenLocation&, ExpressionType, int, int, int) { return ObjectSpreadExpr; } 197 198 TemplateString createTemplateString(const JSTokenLocation&, const Identifier*, const Identifier*) { return TemplateStringResult; } 198 199 TemplateStringList createTemplateStringList(TemplateString) { return TemplateStringListResult; } … … 212 213 ASSERT(name); 213 214 return Property(name, type); 215 } 216 Property createProperty(int, PropertyNode::Type type, PropertyNode::PutType, bool, SuperBinding, bool) 217 { 218 return Property(type); 214 219 } 215 220 Property createProperty(VM* vm, ParserArena& parserArena, double name, int, PropertyNode::Type type, PropertyNode::PutType, bool complete, SuperBinding, bool)
Note: See TracChangeset
for help on using the changeset viewer.