Rolling out r214038 and r213697: Crashes when using computed properties with rest...
authormark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 16 May 2017 00:21:59 +0000 (00:21 +0000)
committermark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 16 May 2017 00:21:59 +0000 (00:21 +0000)
https://bugs.webkit.org/show_bug.cgi?id=172147

Rubber-stamped by Saam Barati.

JSTests:

* stress/object-rest-deconstruct.js: Removed.
* stress/object-spread.js: Removed.

Source/JavaScriptCore:

I rolled out every thing in those 2 patches except for the change to make
CodeBlock::finishCreation() return a bool plus its clients that depend on this.
I made this exception because r214931 relies on this change, and this part of
the change looks correct.

* builtins/BuiltinNames.h:
* builtins/GlobalOperations.js:
(globalPrivate.speciesConstructor):
(globalPrivate.copyDataProperties): Deleted.
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::finishCreation):
(JSC::CodeBlock::setConstantIdentifierSetRegisters): Deleted.
* bytecode/CodeBlock.h:
* bytecode/UnlinkedCodeBlock.h:
(JSC::UnlinkedCodeBlock::addBitVector):
(JSC::UnlinkedCodeBlock::constantRegisters):
(JSC::UnlinkedCodeBlock::addSetConstant): Deleted.
(JSC::UnlinkedCodeBlock::constantIdentifierSets): Deleted.
* bytecompiler/BytecodeGenerator.cpp:
* bytecompiler/BytecodeGenerator.h:
* bytecompiler/NodesCodegen.cpp:
(JSC::PropertyListNode::emitBytecode):
(JSC::ObjectPatternNode::bindValue):
(JSC::ObjectSpreadExpressionNode::emitBytecode): Deleted.
* parser/ASTBuilder.h:
(JSC::ASTBuilder::createProperty):
(JSC::ASTBuilder::appendObjectPatternEntry):
(JSC::ASTBuilder::createObjectSpreadExpression): Deleted.
(JSC::ASTBuilder::appendObjectPatternRestEntry): Deleted.
(JSC::ASTBuilder::setContainsObjectRestElement): Deleted.
* parser/NodeConstructors.h:
(JSC::PropertyNode::PropertyNode):
(JSC::SpreadExpressionNode::SpreadExpressionNode):
(JSC::ObjectSpreadExpressionNode::ObjectSpreadExpressionNode): Deleted.
* parser/Nodes.h:
(JSC::ObjectPatternNode::appendEntry):
(JSC::ObjectSpreadExpressionNode::expression): Deleted.
(JSC::ObjectPatternNode::setContainsRestElement): Deleted.
* parser/Parser.cpp:
(JSC::Parser<LexerType>::parseDestructuringPattern):
(JSC::Parser<LexerType>::parseProperty):
* parser/SyntaxChecker.h:
(JSC::SyntaxChecker::createSpreadExpression):
(JSC::SyntaxChecker::createProperty):
(JSC::SyntaxChecker::operatorStackPop):
(JSC::SyntaxChecker::createObjectSpreadExpression): Deleted.
* 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:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@216891 268f45cc-cd09-0410-ab3c-d52691b4dbfc

24 files changed:
JSTests/ChangeLog
JSTests/stress/object-rest-deconstruct.js [deleted file]
JSTests/stress/object-spread.js [deleted file]
LayoutTests/ChangeLog
LayoutTests/js/parser-syntax-check-expected.txt
LayoutTests/js/script-tests/parser-syntax-check.js
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/builtins/BuiltinNames.h
Source/JavaScriptCore/builtins/GlobalOperations.js
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Source/JavaScriptCore/bytecode/CodeBlock.h
Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
Source/JavaScriptCore/parser/ASTBuilder.h
Source/JavaScriptCore/parser/NodeConstructors.h
Source/JavaScriptCore/parser/Nodes.h
Source/JavaScriptCore/parser/Parser.cpp
Source/JavaScriptCore/parser/SyntaxChecker.h
Source/JavaScriptCore/runtime/ObjectConstructor.cpp
Source/JavaScriptCore/runtime/SetPrototype.cpp
Source/WTF/ChangeLog
Source/WTF/wtf/HashSet.h

index 53521e9..b269a56 100644 (file)
@@ -1,3 +1,13 @@
+2017-05-15  Mark Lam  <mark.lam@apple.com>
+
+        Rolling out r214038 and r213697: Crashes when using computed properties with rest destructuring and object spread.
+        https://bugs.webkit.org/show_bug.cgi?id=172147
+
+        Rubber-stamped by Saam Barati.
+
+        * stress/object-rest-deconstruct.js: Removed.
+        * stress/object-spread.js: Removed.
+
 2017-05-11  JF Bastien  <jfbastien@apple.com>
 
         WebAssembly: stop supporting 0xD
diff --git a/JSTests/stress/object-rest-deconstruct.js b/JSTests/stress/object-rest-deconstruct.js
deleted file mode 100644 (file)
index 3baf785..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-let assert = (e) => {
-    if (!e)
-        throw Error("Bad assertion!");
-}
-
-let assertPropDescriptor = (restObj, prop) => {
-    let desc = Object.getOwnPropertyDescriptor(restObj, prop);
-    assert(desc.enumerable);
-    assert(desc.writable);
-    assert(desc.configurable);
-}
-
-// Base Case
-(() => {
-    let obj = {x: 1, y: 2, a: 5, b: 3}
-
-    let {a, b, ...rest} = obj;
-
-    assert(a === 5);
-    assert(b === 3);
-
-    assert(rest.x === 1);
-    assert(rest.y === 2);
-
-    assertPropDescriptor(rest, 'x');
-    assertPropDescriptor(rest, 'y');
-})();
-
-// Empty Object
-(() => {
-    let obj = {}
-
-    let {a, b, ...rest} = obj;
-
-    assert(a === undefined);
-    assert(b === undefined);
-
-    assert(typeof rest === "object");
-})();
-
-// Number case
-(() => {
-    let obj = 3;
-
-    let {...rest} = obj;
-
-    assert(typeof rest === "object");
-})();
-
-// String case
-(() => {
-    let obj = "foo";
-
-    let {...rest} = obj;
-
-    assert(typeof rest === "object");
-})();
-
-// Symbol case
-(() => {
-    let obj = Symbol("foo");
-
-    let {...rest} = obj;
-
-    assert(typeof rest === "object");
-})();
-
-// null case
-(() => {
-    let obj = null;
-
-    try {
-        let {...rest} = obj;
-        assert(false);
-    } catch (e) {
-        assert(e.message == "Right side of assignment cannot be destructured");
-    }
-
-})();
-
-// undefined case
-(() => {
-    let obj = undefined;
-
-    try {
-        let {...rest} = obj;
-        assert(false);
-    } catch (e) {
-        assert(e.message == "Right side of assignment cannot be destructured");
-    }
-
-})();
-
-// getter case
-(() => {
-    let obj = {a: 3, b: 4};
-    Object.defineProperty(obj, "x", { get: () => 3, enumerable: true });
-
-    let {a, b, ...rest} = obj;
-
-    assert(a === 3);
-    assert(b === 4);
-
-    assert(rest.x === 3);
-    assertPropDescriptor(rest, 'x');
-})();
-
-// Skip non-enumerable case
-(() => {
-    let obj = {a: 3, b: 4};
-    Object.defineProperty(obj, "x", { value: 4, enumerable: false });
-
-    let {...rest} = obj;
-
-    assert(rest.a === 3);
-    assert(rest.b === 4);
-    assert(rest.x === undefined);
-})();
-
-// Don't copy descriptor case
-(() => {
-    let obj = {};
-    Object.defineProperty(obj, "a", { value: 3, configurable: false, enumerable: true });
-    Object.defineProperty(obj, "b", { value: 4, writable: false, enumerable: true });
-
-    let {...rest} = obj;
-
-    assert(rest.a === 3);
-    assert(rest.b === 4);
-
-    assertPropDescriptor(rest, 'a');
-    assertPropDescriptor(rest, 'b');
-})();
-
-// Nested base case
-(() => {
-    let obj = {a: 1, b: 2, c: 3, d: 4, e: 5};
-
-    let {a, b, ...{c, e}} = obj;
-
-    assert(a === 1);
-    assert(b === 2);
-    assert(c === 3);
-    assert(e === 5);
-})();
-
-// Nested rest case
-(() => {
-    let obj = {a: 1, b: 2, c: 3, d: 4, e: 5};
-
-    let {a, b, ...{c, ...rest}} = obj;
-
-    assert(a === 1);
-    assert(b === 2);
-    assert(c === 3);
-
-    assert(rest.d === 4);
-    assert(rest.e === 5);
-})();
-
-// Destructuring Only Own Properties
-(() => {
-    var o = Object.create({ x: 1, y: 2 });
-    o.z = 3;
-
-    var x, y, z;
-
-    // Destructuring assignment allows nested objects
-    ({ x, ...{y , z} } = o);
-
-    assert(x === 1);
-    assert(y === undefined);
-    assert(z === 3);
-})();
-
-// Destructuring function parameter
-
-(() => {
-
-    var o = { x: 1, y: 2, w: 3, z: 4 };
-    
-    function foo({ x, y, ...rest }) {
-        assert(x === 1);
-        assert(y === 2);
-        assert(rest.w === 3);
-        assert(rest.z === 4);
-    }
-    foo(o);
-})();
-
-// Destructuring arrow function parameter
-
-(() => {
-
-    var o = { x: 1, y: 2, w: 3, z: 4 };
-    
-    (({ x, y, ...rest }) => {
-        assert(x === 1);
-        assert(y === 2);
-        assert(rest.w === 3);
-        assert(rest.z === 4);
-    })(o);
-})();
-
-// Destructuring to a property
-(() => {
-
-    var o = { x: 1, y: 2};
-    
-    let settedValue;
-    let src = {};
-    ({...src.y} = o);
-    assert(src.y.x === 1);
-    assert(src.y.y === 2);
-})();
-
-// Destructuring with setter
-(() => {
-
-    var o = { x: 1, y: 2};
-    
-    let settedValue;
-    let src = {
-        get y() { throw Error("The property should not be accessed"); }, 
-        set y(v) {
-            settedValue = v;
-        }
-    }
-    src.y = undefined;
-    ({...src.y} = o);
-    assert(settedValue.x === 1);
-    assert(settedValue.y === 2);
-})();
-
-// Destructuring yield
-(() => {
-
-    var o = { x: 1, y: 2, w: 3, z: 4 };
-    
-    let gen = (function * (o) {
-        ({...{ x = yield }} = o);
-    })(o);
-    
-    assert(gen.next().value === undefined);
-})();
-
diff --git a/JSTests/stress/object-spread.js b/JSTests/stress/object-spread.js
deleted file mode 100644 (file)
index 42af0b9..0000000
+++ /dev/null
@@ -1,297 +0,0 @@
-let assert = (a) => {
-    if (!a)
-        throw new Error("Bad Assertion");
-}
-
-assert.sameValue = (a, b) =>  {
-    assert(a === b);
-}
-
-function validatePropertyDescriptor(o, p) {
-    let desc = Object.getOwnPropertyDescriptor(o, p);
-
-    assert(desc.enumerable);
-    assert(desc.configurable);
-    assert(desc.writable);
-}
-
-// Base cases
-
-(() => {
-    let obj = {a: 1, b: 2, ...{c: 3, d: 4}};
-
-    assert.sameValue(obj.a, 1);
-    assert(obj.b, 2);
-    assert(obj.c, 3);
-    assert(obj.d, 4);
-    validatePropertyDescriptor(obj, "c");
-    validatePropertyDescriptor(obj, "d");
-    assert(Object.keys(obj), 2);
-})();
-
-(() => {
-    let o = {c: 3, d: 4};
-    let obj = {a: 1, b: 2, ...o};
-
-    assert.sameValue(obj.a, 1);
-    assert.sameValue(obj.b, 2);
-    assert.sameValue(obj.c, 3);
-    assert.sameValue(obj.d, 4);
-    assert.sameValue(Object.keys(obj).length, 4);
-
-    validatePropertyDescriptor(obj, "a");
-    validatePropertyDescriptor(obj, "b");
-    validatePropertyDescriptor(obj, "c");
-    validatePropertyDescriptor(obj, "d");
-})();
-
-(() => {
-    let o = {a: 2, b: 3};
-    let o2 = {c: 4, d: 5};
-
-    let obj = {...o, ...o2};
-
-    assert.sameValue(obj.a, 2);
-    assert.sameValue(obj.b, 3);
-    assert.sameValue(obj.c, 4);
-    assert.sameValue(obj.d, 5);
-    assert.sameValue(Object.keys(obj).length, 4);
-})();
-
-// Empty case
-
-(() => {
-    let obj = {a: 1, b: 2, ...{}};
-
-    assert.sameValue(obj.a, 1);
-    assert.sameValue(obj.b, 2);
-    assert.sameValue(Object.keys(obj).length, 2);
-})();
-
-// Ignoring cases
-
-(() => {
-    let obj = {a: 1, ...null, b: 2, ...undefined, c: 3, ...{}, ...{...{}}, d: 4};
-
-    assert.sameValue(obj.a, 1);
-    assert.sameValue(obj.b, 2);
-    assert.sameValue(obj.c, 3);
-    assert.sameValue(obj.d, 4);
-
-    let keys = Object.keys(obj);
-    assert.sameValue(keys[0], "a");
-    assert.sameValue(keys[1], "b");
-    assert.sameValue(keys[2], "c");
-    assert.sameValue(keys[3], "d");
-})();
-
-// Null case
-
-(() => {
-    let obj = {a: 1, b: 2, ...null};
-
-    assert.sameValue(obj.a, 1);
-    assert.sameValue(obj.b, 2);
-    assert.sameValue(Object.keys(obj).length, 2);
-})();
-
-(() => {
-    let obj = {...null};
-
-    assert.sameValue(Object.keys(obj).length, 0);
-})();
-
-// Undefined case
-
-(() => {
-    let obj = {a: 1, b: 2, ...undefined};
-
-    assert.sameValue(obj.a, 1);
-    assert.sameValue(obj.b, 2);
-    assert.sameValue(Object.keys(obj).length, 2);
-})();
-
-(() => {
-    let obj = {...undefined};
-
-    assert.sameValue(Object.keys(obj).length, 0);
-})();
-
-// Getter case
-
-(() => {
-    let o = {
-        get a() {
-            return 42;
-        }
-    };
-
-    let obj = {...o, c: 4, d: 5};
-
-    assert.sameValue(Object.getOwnPropertyDescriptor(obj, "a").value, 42);
-    assert.sameValue(obj.c, 4);
-    assert.sameValue(obj.d, 5);
-    assert.sameValue(Object.keys(obj).length, 3);
-
-    validatePropertyDescriptor(obj, "a");
-})();
-
-(() => {
-    let o = {a: 2, b: 3}
-    let executedGetter = false;
-
-    let obj = {...o, get c() { executedGetter = true; }};
-
-    assert.sameValue(obj.a, 2);
-    assert.sameValue(obj.b, 3);
-    assert.sameValue(executedGetter, false)
-    assert.sameValue(Object.keys(obj).length, 3);
-})();
-
-(() => {
-    let getterCallCount = 0;
-    let o = {
-        get a() {
-            return ++getterCallCount;
-        }
-    };
-
-    let obj = {...o, c: 4, d: 5, a: 42, ...o};
-
-    assert.sameValue(obj.a, 2);
-    assert.sameValue(obj.c, 4);
-    assert.sameValue(obj.d, 5);
-    assert.sameValue(Object.keys(obj).length, 3);
-})();
-
-// Manipulate Object case
-
-(() => {
-    var o = { a: 0, b: 1 };
-    var cthulhu = { get x() {
-      delete o.a;
-      o.b = 42;
-      o.c = "ni";
-    }};
-
-    let obj = {...cthulhu, ...o};
-
-    assert.sameValue(obj.hasOwnProperty("a"), false);
-    assert.sameValue(obj.b, 42);
-    assert.sameValue(obj.c, "ni");
-    assert(obj.hasOwnProperty("x"));
-    assert.sameValue(Object.keys(obj).length, 3);
-})();
-
-// Override
-
-(() => {
-    let o = {a: 2, b: 3};
-
-    let obj = {a: 1, b: 7, ...o};
-
-    assert.sameValue(obj.a, 2);
-    assert.sameValue(obj.b, 3);
-    assert.sameValue(Object.keys(obj).length, 2);
-    assert.sameValue(o.a, 2);
-    assert.sameValue(o.b, 3);
-})();
-
-(() => {
-    let o = {a: 2, b: 3, c: 4, e: undefined, f: null, g: false};
-
-    let obj = {...o, a: 1, b: 7, d: 5, h: -0, i: Symbol("foo"), j: o};
-
-    assert.sameValue(obj.a, 1);
-    assert.sameValue(obj.b, 7);
-    assert.sameValue(obj.c, 4);
-    assert.sameValue(obj.d, 5);
-    assert(obj.hasOwnProperty("e"));
-    assert.sameValue(obj.f, null);
-    assert.sameValue(obj.g, false);
-    assert.sameValue(obj.h, -0);
-    assert.sameValue(obj.i.toString(), "Symbol(foo)");
-    assert(Object.is(obj.j, o));
-    assert.sameValue(Object.keys(obj).length, 10);
-})();
-
-// Override Immutable
-
-(() => {
-    let o = {b: 2};
-    Object.defineProperty(o, "a", {value: 1, enumerable: true, writable: false, configurable: true});
-
-    let obj = {...o, a: 3};
-
-    assert.sameValue(obj.a, 3)
-    assert.sameValue(obj.b, 2);
-    validatePropertyDescriptor(obj, "a");
-    validatePropertyDescriptor(obj, "b");
-})();
-
-// Setter
-
-(() => {
-    let executedSetter = false;
-
-    let obj = {set c(v) { executedSetter = true; }, ...{c: 1}};
-
-    assert.sameValue(obj.c, 1);
-    assert.sameValue(executedSetter, false);
-    assert.sameValue(Object.keys(obj).length, 1);
-})();
-
-// Skip non-enumerble
-
-(() => {
-    let o = {};
-    Object.defineProperty(o, "b", {value: 3, enumerable: false});
-
-    let obj = {...o};
-
-    assert.sameValue(obj.hasOwnProperty("b"), false)
-    assert.sameValue(Object.keys(obj).length, 0);
-})();
-
-// Spread order
-
-(() => {
-    var calls = []
-    var o = { get z() { calls.push('z') }, get a() { calls.push('a') } };
-    Object.defineProperty(o, 1, { get: () => { calls.push(1) }, enumerable: true });
-    Object.defineProperty(o, Symbol('foo'), { get: () => { calls.push("Symbol(foo)") }, enumerable: true });
-
-    let obj = {...o};
-
-    assert.sameValue(calls[0], 1);
-    assert.sameValue(calls[1], "z");
-    assert.sameValue(calls[2], "a");
-    assert.sameValue(calls[3], "Symbol(foo)");
-    assert.sameValue(Object.keys(obj).length, 3);
-})();
-
-// Symbol property
-(() => {
-    let symbol = Symbol('foo');
-    let o = {};
-    o[symbol] = 1;
-
-    let obj = {...o, c: 4, d: 5};
-
-    assert.sameValue(obj[symbol], 1);
-    assert.sameValue(obj.c, 4);
-    assert.sameValue(obj.d, 5);
-    assert.sameValue(Object.keys(obj).length, 2);
-})();
-
-// Getter throw
-
-(() => {
-    try {
-        let obj = {...{ get foo() { throw new Error("Getter Exception"); } }};
-        assert(false);
-    } catch(e) {
-        assert.sameValue(e.message, "Getter Exception");
-    }
-})();
-
index aa27e45..5b93282 100644 (file)
@@ -1,3 +1,13 @@
+2017-05-15  Mark Lam  <mark.lam@apple.com>
+
+        Rolling out r214038 and r213697: Crashes when using computed properties with rest destructuring and object spread.
+        https://bugs.webkit.org/show_bug.cgi?id=172147
+
+        Rubber-stamped by Saam Barati.
+
+        * js/parser-syntax-check-expected.txt:
+        * js/script-tests/parser-syntax-check.js:
+
 2017-05-15  Chris Dumez  <cdumez@apple.com>
 
         Unreviewed, rebaseline platform/ios/ios/css/construct-WebKitCSSMatrix.html after r216881.
index fe71077..27fb08b 100644 (file)
@@ -1167,46 +1167,8 @@ PASS Valid:   "var {x: [y, {z: {z: [...z]}}]} = 20" with TypeError
 PASS Valid:   "function f() { var {x: [y, {z: {z: [...z]}}]} = 20 }"
 PASS Invalid: "var [...y, ...z] = 20". Produced the following syntax error: "SyntaxError: Unexpected token ','. Expected a closing ']' following a rest element destructuring pattern."
 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."
-PASS Valid:   "var [...{...y}] = 20" with TypeError
-PASS Valid:   "function f() { var [...{...y}] = 20 }"
-PASS Valid:   "var {a, b, ...r} = {a: 1, b: 2, c: 3};"
-PASS Valid:   "function f() { var {a, b, ...r} = {a: 1, b: 2, c: 3}; }"
-PASS Valid:   "var {a, b, ...{d}} = {a: 1, b: 2, c: 3, d: 4};"
-PASS Valid:   "function f() { var {a, b, ...{d}} = {a: 1, b: 2, c: 3, d: 4}; }"
-PASS Valid:   "var {a, b, ...{d = 15}} = {a: 1, b: 2, c: 3, d: 4};"
-PASS Valid:   "function f() { var {a, b, ...{d = 15}} = {a: 1, b: 2, c: 3, d: 4}; }"
-PASS Valid:   "var {a, b, ...{d = 15, ...r}} = {a: 1, b: 2, c: 3, d: 4};"
-PASS Valid:   "function f() { var {a, b, ...{d = 15, ...r}} = {a: 1, b: 2, c: 3, d: 4}; }"
-PASS Valid:   "(({a, b, ...r}) => {})({a: 1, b: 2, c: 3, d: 4});"
-PASS Valid:   "function f() { (({a, b, ...r}) => {})({a: 1, b: 2, c: 3, d: 4}); }"
-PASS Valid:   "(function ({a, b, ...r}) {})({a: 1, b: 2, c: 3, d: 4});"
-PASS Valid:   "function f() { (function ({a, b, ...r}) {})({a: 1, b: 2, c: 3, d: 4}); }"
-PASS Valid:   "var a, b, c; ({a, b, ...r} = {a: 1, b: 2, c: 3, d: 4});"
-PASS Valid:   "function f() { var a, b, c; ({a, b, ...r} = {a: 1, b: 2, c: 3, d: 4}); }"
-PASS Valid:   "function * foo(o) { ({...{ x = yield }} = o); }"
-PASS Valid:   "function f() { function * foo(o) { ({...{ x = yield }} = o); } }"
-PASS Valid:   "let c = {}; let o = {a: 1, b: 2, ...c};"
-PASS Valid:   "function f() { let c = {}; let o = {a: 1, b: 2, ...c}; }"
-PASS Valid:   "let o = {a: 1, b: 3, ...{}};"
-PASS Valid:   "function f() { let o = {a: 1, b: 3, ...{}}; }"
-PASS Valid:   "let o = {a: 1, b: 2, ...null, c: 3};"
-PASS Valid:   "function f() { let o = {a: 1, b: 2, ...null, c: 3}; }"
-PASS Valid:   "let o = {a: 1, b: 2, ...undefined, c: 3};"
-PASS Valid:   "function f() { let o = {a: 1, b: 2, ...undefined, c: 3}; }"
-PASS Valid:   "let o = {a: 1, b: 2, ...{...{}}, c: 3};"
-PASS Valid:   "function f() { let o = {a: 1, b: 2, ...{...{}}, c: 3}; }"
-PASS Valid:   "let c = {}; let o = {a: 1, b: 2, ...c, d: 3, ...c, e: 5};"
-PASS Valid:   "function f() { let c = {}; let o = {a: 1, b: 2, ...c, d: 3, ...c, e: 5}; }"
-PASS Valid:   "function* gen() { yield {a: 1, b: 2, ...yield yield, d: 3, ...yield, e: 5}; }"
-PASS Valid:   "function f() { function* gen() { yield {a: 1, b: 2, ...yield yield, d: 3, ...yield, e: 5}; } }"
-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."
-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."
-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."
-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."
-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."
-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."
-PASS Invalid: "function * (o) { ({ ...{ x: yield } } = o); }". Produced the following syntax error: "SyntaxError: Unexpected token '('"
-PASS Invalid: "function f() { function * (o) { ({ ...{ x: yield } } = o); } }". Produced the following syntax error: "SyntaxError: Unexpected token '('"
+PASS Invalid: "var [...{...y}] = 20". Produced the following syntax error: "SyntaxError: Unexpected token '...'. Expected a property name."
+PASS Invalid: "function f() { var [...{...y}] = 20 }". Produced the following syntax error: "SyntaxError: Unexpected token '...'. Expected a property name."
 Rest parameter
 PASS Valid:   "function foo(...a) { }"
 PASS Valid:   "function f() { function foo(...a) { } }"
@@ -1274,8 +1236,8 @@ PASS Valid:   "let x = (a = 20, ...[...[b = 40]]) => { }"
 PASS Valid:   "function f() { let x = (a = 20, ...[...[b = 40]]) => { } }"
 PASS Valid:   "let x = (a = 20, ...{b}) => { }"
 PASS Valid:   "function f() { let x = (a = 20, ...{b}) => { } }"
-PASS Valid:   "let x = (a = 20, ...{...b}) => { }"
-PASS Valid:   "function f() { let x = (a = 20, ...{...b}) => { } }"
+PASS Invalid: "let x = (a = 20, ...{...b}) => { }". Produced the following syntax error: "SyntaxError: Unexpected token '...'"
+PASS Invalid: "function f() { let x = (a = 20, ...{...b}) => { } }". Produced the following syntax error: "SyntaxError: Unexpected token '...'"
 PASS Invalid: "let x = (a = 20, ...{124}) => { }". Produced the following syntax error: "SyntaxError: Unexpected token '...'"
 PASS Invalid: "function f() { let x = (a = 20, ...{124}) => { } }". Produced the following syntax error: "SyntaxError: Unexpected token '...'"
 non-simple parameter list
index a71a18d..5ce4e90 100644 (file)
@@ -691,26 +691,7 @@ valid("var [...[{x} = 20, ...y]] = 20;");
 valid("var {x: [y, ...[...[...{z: [...z]}]]]} = 20");
 valid("var {x: [y, {z: {z: [...z]}}]} = 20");
 invalid("var [...y, ...z] = 20");
-valid("var [...{...y}] = 20");
-valid("var {a, b, ...r} = {a: 1, b: 2, c: 3};");
-valid("var {a, b, ...{d}} = {a: 1, b: 2, c: 3, d: 4};");
-valid("var {a, b, ...{d = 15}} = {a: 1, b: 2, c: 3, d: 4};");
-valid("var {a, b, ...{d = 15, ...r}} = {a: 1, b: 2, c: 3, d: 4};");
-valid("(({a, b, ...r}) => {})({a: 1, b: 2, c: 3, d: 4});");
-valid("(function ({a, b, ...r}) {})({a: 1, b: 2, c: 3, d: 4});");
-valid("var a, b, c; ({a, b, ...r} = {a: 1, b: 2, c: 3, d: 4});");
-valid("function * foo(o) { ({...{ x = yield }} = o); }");
-valid("let c = {}; let o = {a: 1, b: 2, ...c};");
-valid("let o = {a: 1, b: 3, ...{}};");
-valid("let o = {a: 1, b: 2, ...null, c: 3};");
-valid("let o = {a: 1, b: 2, ...undefined, c: 3};");
-valid("let o = {a: 1, b: 2, ...{...{}}, c: 3};");
-valid("let c = {}; let o = {a: 1, b: 2, ...c, d: 3, ...c, e: 5};");
-valid("function* gen() { yield {a: 1, b: 2, ...yield yield, d: 3, ...yield, e: 5}; }");
-invalid("var {...r = {a: 2}} = {a: 1, b: 2};");
-invalid("var {...r, b} = {a: 1, b: 2};");
-invalid("var {...r, ...e} = {a: 1, b: 2};");
-invalid("function * (o) { ({ ...{ x: yield } } = o); }");
+invalid("var [...{...y}] = 20");
 
 debug("Rest parameter");
 valid("function foo(...a) { }");
@@ -746,7 +727,7 @@ invalid("let x = (a = 20, ...b, ...c) => { }");
 valid("let x = (a = 20, ...[...b]) => { }");
 valid("let x = (a = 20, ...[...[b = 40]]) => { }");
 valid("let x = (a = 20, ...{b}) => { }");
-valid("let x = (a = 20, ...{...b}) => { }");
+invalid("let x = (a = 20, ...{...b}) => { }");
 invalid("let x = (a = 20, ...{124}) => { }");
 
 debug("non-simple parameter list")
index a2da9df..6954d9b 100644 (file)
@@ -1,3 +1,61 @@
+2017-05-15  Mark Lam  <mark.lam@apple.com>
+
+        Rolling out r214038 and r213697: Crashes when using computed properties with rest destructuring and object spread.
+        https://bugs.webkit.org/show_bug.cgi?id=172147
+
+        Rubber-stamped by Saam Barati.
+
+        I rolled out every thing in those 2 patches except for the change to make
+        CodeBlock::finishCreation() return a bool plus its clients that depend on this.
+        I made this exception because r214931 relies on this change, and this part of
+        the change looks correct.
+
+        * builtins/BuiltinNames.h:
+        * builtins/GlobalOperations.js:
+        (globalPrivate.speciesConstructor):
+        (globalPrivate.copyDataProperties): Deleted.
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::finishCreation):
+        (JSC::CodeBlock::setConstantIdentifierSetRegisters): Deleted.
+        * bytecode/CodeBlock.h:
+        * bytecode/UnlinkedCodeBlock.h:
+        (JSC::UnlinkedCodeBlock::addBitVector):
+        (JSC::UnlinkedCodeBlock::constantRegisters):
+        (JSC::UnlinkedCodeBlock::addSetConstant): Deleted.
+        (JSC::UnlinkedCodeBlock::constantIdentifierSets): Deleted.
+        * bytecompiler/BytecodeGenerator.cpp:
+        * bytecompiler/BytecodeGenerator.h:
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::PropertyListNode::emitBytecode):
+        (JSC::ObjectPatternNode::bindValue):
+        (JSC::ObjectSpreadExpressionNode::emitBytecode): Deleted.
+        * parser/ASTBuilder.h:
+        (JSC::ASTBuilder::createProperty):
+        (JSC::ASTBuilder::appendObjectPatternEntry):
+        (JSC::ASTBuilder::createObjectSpreadExpression): Deleted.
+        (JSC::ASTBuilder::appendObjectPatternRestEntry): Deleted.
+        (JSC::ASTBuilder::setContainsObjectRestElement): Deleted.
+        * parser/NodeConstructors.h:
+        (JSC::PropertyNode::PropertyNode):
+        (JSC::SpreadExpressionNode::SpreadExpressionNode):
+        (JSC::ObjectSpreadExpressionNode::ObjectSpreadExpressionNode): Deleted.
+        * parser/Nodes.h:
+        (JSC::ObjectPatternNode::appendEntry):
+        (JSC::ObjectSpreadExpressionNode::expression): Deleted.
+        (JSC::ObjectPatternNode::setContainsRestElement): Deleted.
+        * parser/Parser.cpp:
+        (JSC::Parser<LexerType>::parseDestructuringPattern):
+        (JSC::Parser<LexerType>::parseProperty):
+        * parser/SyntaxChecker.h:
+        (JSC::SyntaxChecker::createSpreadExpression):
+        (JSC::SyntaxChecker::createProperty):
+        (JSC::SyntaxChecker::operatorStackPop):
+        (JSC::SyntaxChecker::createObjectSpreadExpression): Deleted.
+        * runtime/ObjectConstructor.cpp:
+        (JSC::ObjectConstructor::finishCreation):
+        * runtime/SetPrototype.cpp:
+        (JSC::SetPrototype::finishCreation):
+
 2017-05-15  David Kilzer  <ddkilzer@apple.com>
 
         JSEnvironmentRecord::allocationSizeForScopeSize() and offsetOfVariable(ScopeOffset) should used checked arithmetic
index e1763e4..ff97469 100644 (file)
@@ -159,7 +159,6 @@ namespace JSC {
     macro(stringIncludesInternal) \
     macro(stringSplitFast) \
     macro(stringSubstrInternal) \
-    macro(toObject) \
     macro(makeBoundFunction) \
     macro(hasOwnLengthProperty) \
     macro(importModule) \
index e5cb3c2..22220cf 100644 (file)
@@ -79,29 +79,3 @@ function speciesConstructor(obj, defaultConstructor)
         return constructor;
     @throwTypeError("|this|.constructor[Symbol.species] is not a constructor");
 }
-
-@globalPrivate
-function copyDataProperties(target, source, excludedSet)
-{
-    if (!@isObject(target))
-        @throwTypeError("target needs to be an object");
-    
-    if (source == null)
-        return target;
-    
-    let from = @Object(source);
-    let keys = @Reflect.@ownKeys(from);
-    let keysLength = keys.length;
-    for (let i = 0; i < keysLength; i++) {
-        let nextKey = keys[i];
-        if (!excludedSet.@has(nextKey)) {
-            let desc = @Object.@getOwnPropertyDescriptor(from, nextKey);
-            if (desc.enumerable && desc !== @undefined) {
-                let propValue = from[nextKey];
-                @Object.@defineProperty(target, nextKey, {value: propValue, enumerable: true, writable: true, configurable: true});
-            }
-        }
-    }
-
-    return target;
-}
index de8fa03..f742a4d 100644 (file)
@@ -58,8 +58,6 @@
 #include "JSFunction.h"
 #include "JSLexicalEnvironment.h"
 #include "JSModuleEnvironment.h"
-#include "JSSet.h"
-#include "JSString.h"
 #include "JSTemplateRegistryKey.h"
 #include "LLIntData.h"
 #include "LLIntEntrypoint.h"
@@ -407,8 +405,6 @@ bool CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
 
     if (!setConstantRegisters(unlinkedCodeBlock->constantRegisters(), unlinkedCodeBlock->constantsSourceCodeRepresentation()))
         return false;
-    if (!setConstantIdentifierSetRegisters(vm, unlinkedCodeBlock->constantIdentifierSets()))
-        return false;
     if (unlinkedCodeBlock->usesGlobalObject())
         m_constantRegisters[unlinkedCodeBlock->globalObjectRegister().toConstantIndex()].set(*m_vm, this, m_globalObject.get());
 
@@ -867,29 +863,6 @@ CodeBlock::~CodeBlock()
 #endif // ENABLE(JIT)
 }
 
-bool CodeBlock::setConstantIdentifierSetRegisters(VM& vm, const Vector<ConstantIndentifierSetEntry>& constants)
-{
-    auto scope = DECLARE_THROW_SCOPE(vm);
-    JSGlobalObject* globalObject = m_globalObject.get();
-    ExecState* exec = globalObject->globalExec();
-
-    for (const auto& entry : constants) {
-        Structure* setStructure = globalObject->setStructure();
-        RETURN_IF_EXCEPTION(scope, false);
-        JSSet* jsSet = JSSet::create(exec, vm, setStructure);
-        RETURN_IF_EXCEPTION(scope, false);
-
-        const IdentifierSet& set = entry.first;
-        for (auto& setEntry : set) {
-            JSString* jsString = jsOwnedString(&vm, setEntry.get());
-            jsSet->add(exec, JSValue(jsString));
-            RETURN_IF_EXCEPTION(scope, false);
-        }
-        m_constantRegisters[entry.second].set(vm, this, JSValue(jsSet));
-    }
-    return true;
-}
-
 bool CodeBlock::setConstantRegisters(const Vector<WriteBarrier<Unknown>>& constants, const Vector<SourceCodeRepresentation>& constantsSourceCodeRepresentation)
 {
     auto scope = DECLARE_THROW_SCOPE(*m_vm);
index b42807c..43c1d87 100644 (file)
@@ -920,8 +920,6 @@ private:
 
     void updateAllPredictionsAndCountLiveness(unsigned& numberOfLiveNonArgumentValueProfiles, unsigned& numberOfSamplesInProfiles);
 
-    bool setConstantIdentifierSetRegisters(VM&, const Vector<ConstantIndentifierSetEntry>& constants);
-
     bool setConstantRegisters(const Vector<WriteBarrier<Unknown>>& constants, const Vector<SourceCodeRepresentation>& constantsSourceCodeRepresentation);
 
     void replaceConstant(int index, JSValue value)
index 3630fdd..04304c9 100644 (file)
 #include "UnlinkedFunctionExecutable.h"
 #include "VariableEnvironment.h"
 #include "VirtualRegister.h"
-#include <algorithm>
 #include <wtf/BitVector.h>
-#include <wtf/HashSet.h>
 #include <wtf/TriState.h>
 #include <wtf/Vector.h>
-#include <wtf/text/UniquedStringImpl.h>
 
 namespace JSC {
 
@@ -68,7 +65,6 @@ typedef unsigned UnlinkedArrayProfile;
 typedef unsigned UnlinkedArrayAllocationProfile;
 typedef unsigned UnlinkedObjectAllocationProfile;
 typedef unsigned UnlinkedLLIntCallLinkInfo;
-typedef std::pair<IdentifierSet, unsigned> ConstantIndentifierSetEntry;
 
 struct UnlinkedStringJumpTable {
     struct OffsetLocation {
@@ -186,16 +182,6 @@ public:
         m_bitVectors.append(WTFMove(bitVector));
         return m_bitVectors.size() - 1;
     }
-    
-    void addSetConstant(IdentifierSet& set)
-    {
-        VM& vm = *this->vm();
-        auto locker = lockDuringMarking(vm.heap, *this);
-        unsigned result = m_constantRegisters.size();
-        m_constantRegisters.append(WriteBarrier<Unknown>());
-        m_constantsSourceCodeRepresentation.append(SourceCodeRepresentation::Other);
-        m_constantIdentifierSets.append(ConstantIndentifierSetEntry(set, result));
-    }
 
     unsigned addConstant(JSValue v, SourceCodeRepresentation sourceCodeRepresentation = SourceCodeRepresentation::Other)
     {
@@ -228,7 +214,6 @@ public:
         return m_linkTimeConstants[index];
     }
     const Vector<WriteBarrier<Unknown>>& constantRegisters() { return m_constantRegisters; }
-    const Vector<ConstantIndentifierSetEntry>& constantIdentifierSets() { return m_constantIdentifierSets; }
     const WriteBarrier<Unknown>& constantRegister(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex]; }
     ALWAYS_INLINE bool isConstantRegisterIndex(int index) const { return index >= FirstConstantRegisterIndex; }
     ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].get(); }
@@ -462,7 +447,6 @@ private:
     Vector<Identifier> m_identifiers;
     Vector<BitVector> m_bitVectors;
     Vector<WriteBarrier<Unknown>> m_constantRegisters;
-    Vector<ConstantIndentifierSetEntry> m_constantIdentifierSets;
     Vector<SourceCodeRepresentation> m_constantsSourceCodeRepresentation;
     typedef Vector<WriteBarrier<UnlinkedFunctionExecutable>> FunctionExpressionVector;
     FunctionExpressionVector m_functionDecls;
index 1585e13..9a86b7d 100644 (file)
@@ -1951,27 +1951,6 @@ RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, JSValue v, SourceCodeRe
     return constantID;
 }
 
-RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, IdentifierSet& set)
-{
-    for (const auto& entry : m_codeBlock->constantIdentifierSets()) {
-        if (entry.first != set)
-            continue;
-        
-        return &m_constantPoolRegisters[entry.second];
-    }
-    
-    unsigned index = m_nextConstantOffset;
-    m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
-    ++m_nextConstantOffset;
-    m_codeBlock->addSetConstant(set);
-    RegisterID* m_setRegister = &m_constantPoolRegisters[index];
-    
-    if (dst)
-        return emitMove(dst, m_setRegister);
-    
-    return m_setRegister;
-}
-
 RegisterID* BytecodeGenerator::emitLoadGlobalObject(RegisterID* dst)
 {
     if (!m_globalObjectRegister) {
index 331b145..7e80723 100644 (file)
@@ -587,7 +587,6 @@ namespace JSC {
         RegisterID* emitLoad(RegisterID* dst, bool);
         RegisterID* emitLoad(RegisterID* dst, const Identifier&);
         RegisterID* emitLoad(RegisterID* dst, JSValue, SourceCodeRepresentation = SourceCodeRepresentation::Other);
-        RegisterID* emitLoad(RegisterID* dst, IdentifierSet& excludedList);
         RegisterID* emitLoadGlobalObject(RegisterID* dst);
 
         RegisterID* emitUnaryOp(OpcodeID, RegisterID* dst, RegisterID* src);
index 6ad5794..23e83e3 100644 (file)
 #include "Parser.h"
 #include "StackAlignment.h"
 #include <wtf/Assertions.h>
-#include <wtf/HashSet.h>
 #include <wtf/Threading.h>
 #include <wtf/text/StringBuilder.h>
-#include <wtf/text/UniquedStringImpl.h>
 
 using namespace WTF;
 
@@ -516,7 +514,7 @@ RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, Registe
                 hasComputedProperty = true;
                 break;
             }
-            if (node->m_type & PropertyNode::Constant || node->m_type & PropertyNode::Spread)
+            if (node->m_type & PropertyNode::Constant)
                 continue;
 
             // Duplicates are possible.
@@ -538,9 +536,6 @@ RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, Registe
             if (node->m_type & PropertyNode::Constant) {
                 emitPutConstantProperty(generator, dst, *node);
                 continue;
-            } else if (node->m_type & PropertyNode::Spread) {
-                generator.emitNode(dst, node->m_assign);
-                continue;
             }
 
             RefPtr<RegisterID> value = generator.emitNode(node->m_assign);
@@ -4066,56 +4061,25 @@ void ObjectPatternNode::toString(StringBuilder& builder) const
 void ObjectPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const
 {
     generator.emitRequireObjectCoercible(rhs, ASCIILiteral("Right side of assignment cannot be destructured"));
-    
-    IdentifierSet excludedSet;
-
     for (const auto& target : m_targetPatterns) {
-        if (target.bindingType == BindingType::Element) {
-            RefPtr<RegisterID> temp = generator.newTemporary();
-            if (!target.propertyExpression) {
-                
-                // Should not emit get_by_id for indexed ones.
-                std::optional<uint32_t> optionalIndex = parseIndex(target.propertyName);
-                if (!optionalIndex)
-                    generator.emitGetById(temp.get(), rhs, target.propertyName);
-                else {
-                    RefPtr<RegisterID> pIndex = generator.emitLoad(nullptr, jsNumber(optionalIndex.value()));
-                    generator.emitGetByVal(temp.get(), rhs, pIndex.get());
-                }
-            } else {
-                RefPtr<RegisterID> propertyName = generator.emitNode(target.propertyExpression);
-                generator.emitGetByVal(temp.get(), rhs, propertyName.get());
+        RefPtr<RegisterID> temp = generator.newTemporary();
+        if (!target.propertyExpression) {
+            // Should not emit get_by_id for indexed ones.
+            std::optional<uint32_t> optionalIndex = parseIndex(target.propertyName);
+            if (!optionalIndex)
+                generator.emitGetById(temp.get(), rhs, target.propertyName);
+            else {
+                RefPtr<RegisterID> index = generator.emitLoad(nullptr, jsNumber(optionalIndex.value()));
+                generator.emitGetByVal(temp.get(), rhs, index.get());
             }
-            
-            if (UNLIKELY(m_containsRestElement))
-                excludedSet.add(target.propertyName.impl());
-            
-            if (target.defaultValue)
-                assignDefaultValueIfUndefined(generator, temp.get(), target.defaultValue);
-            target.pattern->bindValue(generator, temp.get());
         } else {
-            RefPtr<RegisterID> excludedSetReg = generator.emitLoad(generator.newTemporary(), excludedSet);
-        
-            RefPtr<RegisterID> newObject = generator.emitNewObject(generator.newTemporary());
-            
-            // load and call @copyDataProperties
-            auto var = generator.variable(generator.propertyNames().builtinNames().copyDataPropertiesPrivateName());
-            
-            RefPtr<RegisterID> scope = generator.newTemporary();
-            generator.moveToDestinationIfNeeded(scope.get(), generator.emitResolveScope(scope.get(), var));
-            RefPtr<RegisterID> copyDataProperties = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
-            
-            CallArguments args(generator, nullptr, 3);
-            unsigned argumentCount = 0;
-            generator.emitLoad(args.thisRegister(), jsUndefined());
-            generator.emitMove(args.argumentRegister(argumentCount++), newObject.get());
-            generator.emitMove(args.argumentRegister(argumentCount++), rhs);
-            generator.emitMove(args.argumentRegister(argumentCount++), excludedSetReg.get());
-
-            RefPtr<RegisterID> result = generator.newTemporary();
-            generator.emitCall(result.get(), copyDataProperties.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd(), DebuggableCall::No);
-            target.pattern->bindValue(generator, result.get());
+            RefPtr<RegisterID> propertyName = generator.emitNode(target.propertyExpression);
+            generator.emitGetByVal(temp.get(), rhs, propertyName.get());
         }
+
+        if (target.defaultValue)
+            assignDefaultValueIfUndefined(generator, temp.get(), target.defaultValue);
+        target.pattern->bindValue(generator, temp.get());
     }
 }
 
@@ -4265,31 +4229,4 @@ RegisterID* SpreadExpressionNode::emitBytecode(BytecodeGenerator&, RegisterID*)
     return 0;
 }
 
-RegisterID* ObjectSpreadExpressionNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> src = generator.newTemporary();
-    generator.emitNode(src.get(), m_expression);
-    IdentifierSet excludedSet;
-    
-    RefPtr<RegisterID> excludedSetReg = generator.emitLoad(generator.newTemporary(), excludedSet);
-        
-    // load and call @copyDataProperties
-    auto var = generator.variable(generator.propertyNames().builtinNames().copyDataPropertiesPrivateName());
-    
-    RefPtr<RegisterID> scope = generator.newTemporary();
-    generator.moveToDestinationIfNeeded(scope.get(), generator.emitResolveScope(scope.get(), var));
-    RefPtr<RegisterID> copyDataProperties = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
-    
-    CallArguments args(generator, nullptr, 3);
-    unsigned argumentCount = 0;
-    generator.emitLoad(args.thisRegister(), jsUndefined());
-    generator.emitMove(args.argumentRegister(argumentCount++), dst);
-    generator.emitMove(args.argumentRegister(argumentCount++), src.get());
-    generator.emitMove(args.argumentRegister(argumentCount++), excludedSetReg.get());
-    
-    generator.emitCall(generator.newTemporary(), copyDataProperties.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd(), DebuggableCall::No);
-    
-    return 0;
-}
-
 } // namespace JSC
index 87baa39..c49aaad 100644 (file)
@@ -275,13 +275,6 @@ public:
         return node;
     }
 
-    ExpressionNode* createObjectSpreadExpression(const JSTokenLocation& location, ExpressionNode* expression, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end)
-    {
-        auto node = new (m_parserArena) ObjectSpreadExpressionNode(location, expression);
-        setExceptionLocation(node, start, divot, end);
-        return node;
-    }
-
     TemplateStringNode* createTemplateString(const JSTokenLocation& location, const Identifier* cooked, const Identifier* raw)
     {
         return new (m_parserArena) TemplateStringNode(location, cooked, raw);
@@ -502,10 +495,6 @@ public:
         }
         return new (m_parserArena) PropertyNode(*propertyName, node, type, putType, superBinding, isClassProperty);
     }
-    PropertyNode* createProperty(ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, bool, SuperBinding superBinding, bool isClassProperty)
-    {
-        return new (m_parserArena) PropertyNode(node, type, putType, superBinding, isClassProperty);
-    }
     PropertyNode* createProperty(VM* vm, ParserArena& parserArena, double propertyName, ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, bool, SuperBinding superBinding, bool isClassProperty)
     {
         return new (m_parserArena) PropertyNode(parserArena.identifierArena().makeNumericIdentifier(vm, propertyName), node, type, putType, superBinding, isClassProperty);
@@ -955,25 +944,15 @@ public:
     
     void appendObjectPatternEntry(ObjectPattern node, const JSTokenLocation& location, bool wasString, const Identifier& identifier, DestructuringPattern pattern, ExpressionNode* defaultValue)
     {
-        node->appendEntry(location, identifier, wasString, pattern, defaultValue, ObjectPatternNode::BindingType::Element);
+        node->appendEntry(location, identifier, wasString, pattern, defaultValue);
         tryInferNameInPattern(pattern, defaultValue);
     }
 
     void appendObjectPatternEntry(ObjectPattern node, const JSTokenLocation& location, ExpressionNode* propertyExpression, DestructuringPattern pattern, ExpressionNode* defaultValue)
     {
-        node->appendEntry(location, propertyExpression, pattern, defaultValue, ObjectPatternNode::BindingType::Element);
+        node->appendEntry(location, propertyExpression, pattern, defaultValue);
         tryInferNameInPattern(pattern, defaultValue);
     }
-    
-    void appendObjectPatternRestEntry(ObjectPattern node, const JSTokenLocation& location, DestructuringPattern pattern)
-    {
-        node->appendEntry(location, nullptr, pattern, nullptr, ObjectPatternNode::BindingType::RestElement);
-    }
-
-    void setContainsObjectRestElement(ObjectPattern node, bool containsRestElement)
-    {
-        node->setContainsRestElement(containsRestElement);
-    }
 
     BindingPattern createBindingLocation(const JSTokenLocation&, const Identifier& boundProperty, const JSTextPosition& start, const JSTextPosition& end, AssignmentContext context)
     {
index 085213f..6f53b64 100644 (file)
@@ -234,19 +234,9 @@ namespace JSC {
         , m_isClassProperty(isClassProperty)
     {
     }
-    
-    inline PropertyNode::PropertyNode(ExpressionNode* assign, Type type, PutType putType, SuperBinding superBinding, bool isClassProperty)
-        : m_name(nullptr)
-        , m_assign(assign)
-        , m_type(type)
-        , m_needsSuperBinding(superBinding == SuperBinding::Needed)
-        , m_putType(putType)
-        , m_isClassProperty(isClassProperty)
-    {
-    }
 
     inline PropertyNode::PropertyNode(ExpressionNode* name, ExpressionNode* assign, Type type, PutType putType, SuperBinding superBinding, bool isClassProperty)
-        : m_name(nullptr)
+        : m_name(0)
         , m_expression(name)
         , m_assign(assign)
         , m_type(type)
@@ -304,12 +294,6 @@ namespace JSC {
         , m_expression(expression)
     {
     }
-    
-    inline ObjectSpreadExpressionNode::ObjectSpreadExpressionNode(const JSTokenLocation& location, ExpressionNode* expression)
-        : ExpressionNode(location)
-        , m_expression(expression)
-    {
-    }
 
     inline ArgumentListNode::ArgumentListNode(const JSTokenLocation& location, ExpressionNode* expr)
         : ExpressionNode(location)
index 6a4f92e..cdc2ce9 100644 (file)
@@ -646,11 +646,10 @@ namespace JSC {
 
     class PropertyNode : public ParserArenaFreeable {
     public:
-        enum Type { Constant = 1, Getter = 2, Setter = 4, Computed = 8, Shorthand = 16, Spread = 32 };
+        enum Type { Constant = 1, Getter = 2, Setter = 4, Computed = 8, Shorthand = 16 };
         enum PutType { Unknown, KnownDirect };
 
         PropertyNode(const Identifier&, ExpressionNode*, Type, PutType, SuperBinding, bool isClassProperty);
-        PropertyNode(ExpressionNode*, Type, PutType, SuperBinding, bool isClassProperty);
         PropertyNode(ExpressionNode* propertyName, ExpressionNode*, Type, PutType, SuperBinding, bool isClassProperty);
 
         ExpressionNode* expressionName() const { return m_expression; }
@@ -666,7 +665,7 @@ namespace JSC {
         const Identifier* m_name;
         ExpressionNode* m_expression;
         ExpressionNode* m_assign;
-        unsigned m_type : 6;
+        unsigned m_type : 5;
         unsigned m_needsSuperBinding : 1;
         unsigned m_putType : 1;
         unsigned m_isClassProperty: 1;
@@ -748,18 +747,6 @@ namespace JSC {
         bool isSpreadExpression() const override { return true; }
         ExpressionNode* m_expression;
     };
-    
-    class ObjectSpreadExpressionNode : public ExpressionNode, public ThrowableExpressionData {
-    public:
-        ObjectSpreadExpressionNode(const JSTokenLocation&, ExpressionNode*);
-        
-        ExpressionNode* expression() const { return m_expression; }
-        
-    private:
-        RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
-        
-        ExpressionNode* m_expression;
-    };
 
     class ArgumentListNode : public ExpressionNode {
     public:
@@ -2127,28 +2114,19 @@ namespace JSC {
         Vector<Entry> m_targetPatterns;
     };
     
-    class ObjectPatternNode : public DestructuringPatternNode, public ThrowableExpressionData, public ParserArenaDeletable {
+    class ObjectPatternNode : public DestructuringPatternNode, public ParserArenaDeletable {
     public:
         using ParserArenaDeletable::operator new;
         
         ObjectPatternNode();
-        enum class BindingType {
-            Element,
-            RestElement
-        };
-        void appendEntry(const JSTokenLocation&, const Identifier& identifier, bool wasString, DestructuringPatternNode* pattern, ExpressionNode* defaultValue, BindingType bindingType)
+        void appendEntry(const JSTokenLocation&, const Identifier& identifier, bool wasString, DestructuringPatternNode* pattern, ExpressionNode* defaultValue)
         {
-            m_targetPatterns.append(Entry{ identifier, nullptr, wasString, pattern, defaultValue, bindingType });
+            m_targetPatterns.append(Entry { identifier, nullptr, wasString, pattern, defaultValue });
         }
 
-        void appendEntry(const JSTokenLocation&, ExpressionNode* propertyExpression, DestructuringPatternNode* pattern, ExpressionNode* defaultValue, BindingType bindingType)
+        void appendEntry(const JSTokenLocation&, ExpressionNode* propertyExpression, DestructuringPatternNode* pattern, ExpressionNode* defaultValue)
         {
-            m_targetPatterns.append(Entry{ Identifier(), propertyExpression, false, pattern, defaultValue, bindingType });
-        }
-        
-        void setContainsRestElement(bool containsRestElement)
-        {
-            m_containsRestElement = containsRestElement;
+            m_targetPatterns.append(Entry { Identifier(), propertyExpression, false, pattern, defaultValue });
         }
 
     private:
@@ -2161,9 +2139,7 @@ namespace JSC {
             bool wasString;
             DestructuringPatternNode* pattern;
             ExpressionNode* defaultValue;
-            BindingType bindingType;
         };
-        bool m_containsRestElement { false };
         Vector<Entry> m_targetPatterns;
     };
 
index 4d6c2e3..86647d9 100644 (file)
@@ -1013,27 +1013,12 @@ template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseDe
         if (hasDestructuringPattern)
             *hasDestructuringPattern = true;
 
-        bool restElementWasFound = false;
-
         do {
             bool wasString = false;
 
             if (match(CLOSEBRACE))
                 break;
 
-            if (UNLIKELY(match(DOTDOTDOT))) {
-                JSTokenLocation location = m_token.m_location;
-                next();
-                auto innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
-                if (kind == DestructuringKind::DestructureToExpressions && !innerPattern)
-                    return 0;
-                propagateError();
-                context.appendObjectPatternRestEntry(objectPattern, location, innerPattern);
-                restElementWasFound = true;
-                context.setContainsObjectRestElement(objectPattern, restElementWasFound);
-                break;
-            }
-
             const Identifier* propertyName = nullptr;
             TreeExpression propertyExpression = 0;
             TreeDestructuringPattern innerPattern = 0;
@@ -1108,7 +1093,7 @@ template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseDe
 
         if (kind == DestructuringKind::DestructureToExpressions && !match(CLOSEBRACE))
             return 0;
-        consumeOrFail(CLOSEBRACE, restElementWasFound ? "Expected a closing '}' following a rest element destructuring pattern" : "Expected either a closing '}' or an ',' after a property destructuring pattern");
+        consumeOrFail(CLOSEBRACE, "Expected either a closing '}' or an ',' after a property destructuring pattern");
         pattern = objectPattern;
         break;
     }
@@ -3804,16 +3789,6 @@ namedProperty:
         context.setEndOffset(node, m_lexer->currentOffset());
         return context.createProperty(propertyName, node, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed), PropertyNode::Unknown, complete, SuperBinding::NotNeeded, isClassProperty);
     }
-    case DOTDOTDOT: {
-        auto spreadLocation = m_token.m_location;
-        auto start = m_token.m_startPosition;
-        auto divot = m_token.m_endPosition;
-        next();
-        TreeExpression elem = parseAssignmentExpressionOrPropagateErrorClass(context);
-        failIfFalse(elem, "Cannot parse subject of a spread operation");
-        auto node = context.createObjectSpreadExpression(spreadLocation, elem, start, divot, m_lastTokenEndPosition);
-        return context.createProperty(node, PropertyNode::Spread, PropertyNode::Unknown, complete, SuperBinding::NotNeeded, isClassProperty);
-    }
     default:
         failIfFalse(m_token.m_type & KeywordTokenFlag, "Expected a property name");
         wasIdent = true; // Treat keyword token as an identifier
index a35ed9f..2f64986 100644 (file)
@@ -76,7 +76,7 @@ public:
         ConditionalExpr, AssignmentExpr, TypeofExpr, NewTargetExpr,
         DeleteExpr, ArrayLiteralExpr, BindingDestructuring, RestParameter,
         ArrayDestructuring, ObjectDestructuring, SourceElementsResult,
-        FunctionBodyResult, SpreadExpr, ObjectSpreadExpr, ArgumentsResult,
+        FunctionBodyResult, SpreadExpr, ArgumentsResult,
         PropertyListResult, ArgumentsListResult, ElementsListResult,
         StatementResult, FormalParameterListResult, ClauseResult,
         ClauseListResult, CommaExpr, DestructuringAssignment,
@@ -194,7 +194,6 @@ public:
     int createArguments() { return ArgumentsResult; }
     int createArguments(int) { return ArgumentsResult; }
     ExpressionType createSpreadExpression(const JSTokenLocation&, ExpressionType, int, int, int) { return SpreadExpr; }
-    ExpressionType createObjectSpreadExpression(const JSTokenLocation&, ExpressionType, int, int, int) { return ObjectSpreadExpr; }
     TemplateString createTemplateString(const JSTokenLocation&, const Identifier*, const Identifier*) { return TemplateStringResult; }
     TemplateStringList createTemplateStringList(TemplateString) { return TemplateStringListResult; }
     TemplateStringList createTemplateStringList(TemplateStringList, TemplateString) { return TemplateStringListResult; }
@@ -213,10 +212,6 @@ public:
         ASSERT(name);
         return Property(name, type);
     }
-    Property createProperty(int, PropertyNode::Type type, PropertyNode::PutType, bool, SuperBinding, bool)
-    {
-        return Property(type);
-    }
     Property createProperty(VM* vm, ParserArena& parserArena, double name, int, PropertyNode::Type type, PropertyNode::PutType, bool complete, SuperBinding, bool)
     {
         if (!complete)
@@ -357,12 +352,6 @@ public:
     void appendObjectPatternEntry(ArrayPattern, const JSTokenLocation&, Expression, DestructuringPattern, Expression)
     {
     }
-    void appendObjectPatternRestEntry(ObjectPattern, const JSTokenLocation&, DestructuringPattern)
-    {
-    }
-    void setContainsObjectRestElement(ObjectPattern, bool)
-    {
-    }
 
     DestructuringPattern createBindingLocation(const JSTokenLocation&, const Identifier&, const JSTextPosition&, const JSTextPosition&, AssignmentContext)
     {
index c73e11a..89d2be5 100644 (file)
@@ -104,7 +104,6 @@ void ObjectConstructor::finishCreation(VM& vm, JSGlobalObject* globalObject, Obj
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().definePropertyPrivateName(), objectConstructorDefineProperty, DontEnum, 3);
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().getPrototypeOfPrivateName(), objectConstructorGetPrototypeOf, DontEnum, 1);
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().getOwnPropertyNamesPrivateName(), objectConstructorGetOwnPropertyNames, DontEnum, 1);
-    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().getOwnPropertyDescriptorPrivateName(), objectConstructorGetOwnPropertyDescriptor, DontEnum, 1);
 }
 
 // ES 19.1.1.1 Object([value])
index 1db99f9..9ed08c4 100644 (file)
@@ -67,7 +67,6 @@ void SetPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject)
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->clear, setProtoFuncClear, DontEnum, 0);
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->deleteKeyword, setProtoFuncDelete, DontEnum, 1);
     JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->has, setProtoFuncHas, DontEnum, 1, JSSetHasIntrinsic);
-    JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().hasPrivateName(), setProtoFuncHas, DontEnum, 1, JSSetHasIntrinsic);
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().entriesPublicName(), setProtoFuncEntries, DontEnum, 0);
 
     JSFunction* values = JSFunction::create(vm, globalObject, 0, vm.propertyNames->builtinNames().valuesPublicName().string(), setProtoFuncValues);
index 88ff471..47bd905 100644 (file)
@@ -1,3 +1,13 @@
+2017-05-15  Mark Lam  <mark.lam@apple.com>
+
+        Rolling out r214038 and r213697: Crashes when using computed properties with rest destructuring and object spread.
+        https://bugs.webkit.org/show_bug.cgi?id=172147
+
+        Rubber-stamped by Saam Barati.
+
+        * wtf/HashSet.h:
+        (WTF::=):
+
 2017-05-14  Chris Dumez  <cdumez@apple.com>
 
         Drop PassRefPtr class from WTF
index 13ad103..7218463 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005, 2006, 2007, 2008, 2011, 2013, 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2005, 2006, 2007, 2008, 2011, 2013 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -123,9 +123,6 @@ namespace WTF {
 
         template<typename OtherCollection>
         bool operator==(const OtherCollection&) const;
-        
-        template<typename OtherCollection>
-        bool operator!=(const OtherCollection&) const;
 
     private:
         HashTableType m_impl;
@@ -380,13 +377,6 @@ namespace WTF {
         }
         return true;
     }
-    
-    template<typename T, typename U, typename V>
-    template<typename OtherCollection>
-    inline bool HashSet<T, U, V>::operator!=(const OtherCollection& otherCollection) const
-    {
-        return !(*this == otherCollection);
-    }
 
 } // namespace WTF