Diff
Modified: trunk/JSTests/ChangeLog (213696 => 213697)
--- trunk/JSTests/ChangeLog 2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/JSTests/ChangeLog 2017-03-10 02:00:33 UTC (rev 213697)
@@ -1,3 +1,20 @@
+2017-03-09 Caio Lima <[email protected]>
+
+ [ESnext] Implement Object Rest - Implementing Object Rest Destructuring
+ https://bugs.webkit.org/show_bug.cgi?id=167962
+
+ Reviewed by Keith Miller.
+
+ * stress/object-rest-deconstruct.js: Added.
+ (let.assert):
+ (let.assertPropDescriptor):
+ (catch):
+ (get 3):
+ (foo):
+ (let.src.get y):
+ (let.src.set y):
+ (let.gen):
+
2017-03-09 Saam Barati <[email protected]>
WebAssembly: Make the Unity AngryBots demo run
Added: trunk/JSTests/stress/object-rest-deconstruct.js (0 => 213697)
--- trunk/JSTests/stress/object-rest-deconstruct.js (rev 0)
+++ trunk/JSTests/stress/object-rest-deconstruct.js 2017-03-10 02:00:33 UTC (rev 213697)
@@ -0,0 +1,246 @@
+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);
+})();
+
Modified: trunk/LayoutTests/ChangeLog (213696 => 213697)
--- trunk/LayoutTests/ChangeLog 2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/LayoutTests/ChangeLog 2017-03-10 02:00:33 UTC (rev 213697)
@@ -1,3 +1,13 @@
+2017-03-09 Caio Lima <[email protected]>
+
+ [ESnext] Implement Object Rest - Implementing Object Rest Destructuring
+ https://bugs.webkit.org/show_bug.cgi?id=167962
+
+ Reviewed by Keith Miller.
+
+ * js/parser-syntax-check-expected.txt:
+ * js/script-tests/parser-syntax-check.js:
+
2017-03-09 Matt Baker <[email protected]>
Web Inspector: Add XHR breakpoints UI
Modified: trunk/LayoutTests/js/parser-syntax-check-expected.txt (213696 => 213697)
--- trunk/LayoutTests/js/parser-syntax-check-expected.txt 2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/LayoutTests/js/parser-syntax-check-expected.txt 2017-03-10 02:00:33 UTC (rev 213697)
@@ -1167,8 +1167,32 @@
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 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."
+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 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 '('"
Rest parameter
PASS Valid: "function foo(...a) { }"
PASS Valid: "function f() { function foo(...a) { } }"
@@ -1236,8 +1260,8 @@
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 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 Valid: "let x = (a = 20, ...{...b}) => { }"
+PASS Valid: "function f() { let x = (a = 20, ...{...b}) => { } }"
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
Modified: trunk/LayoutTests/js/script-tests/parser-syntax-check.js (213696 => 213697)
--- trunk/LayoutTests/js/script-tests/parser-syntax-check.js 2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/LayoutTests/js/script-tests/parser-syntax-check.js 2017-03-10 02:00:33 UTC (rev 213697)
@@ -691,7 +691,19 @@
valid("var {x: [y, ...[...[...{z: [...z]}]]]} = 20");
valid("var {x: [y, {z: {z: [...z]}}]} = 20");
invalid("var [...y, ...z] = 20");
-invalid("var [...{...y}] = 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); }");
+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); }");
debug("Rest parameter");
valid("function foo(...a) { }");
@@ -727,7 +739,7 @@
valid("let x = (a = 20, ...[...b]) => { }");
valid("let x = (a = 20, ...[...[b = 40]]) => { }");
valid("let x = (a = 20, ...{b}) => { }");
-invalid("let x = (a = 20, ...{...b}) => { }");
+valid("let x = (a = 20, ...{...b}) => { }");
invalid("let x = (a = 20, ...{124}) => { }");
debug("non-simple parameter list")
Modified: trunk/Source/_javascript_Core/ChangeLog (213696 => 213697)
--- trunk/Source/_javascript_Core/ChangeLog 2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/_javascript_Core/ChangeLog 2017-03-10 02:00:33 UTC (rev 213697)
@@ -1,3 +1,82 @@
+2017-03-09 Caio Lima <[email protected]>
+
+ [ESnext] Implement Object Rest - Implementing Object Rest Destructuring
+ https://bugs.webkit.org/show_bug.cgi?id=167962
+
+ Reviewed by Keith Miller.
+
+ Object Rest/Spread Destructing proposal is in stage 3[1] and this
+ Patch is a prototype implementation of it. A simple change over the
+ parser was necessary to support the new '...' token on Object Pattern
+ destruction rule. In the bytecode generator side, We changed the
+ bytecode generated on ObjectPatternNode::bindValue to store in an
+ array identifiers of already destructed properties, following spec draft
+ section[2], and then pass it as excludedNames to CopyDataProperties.
+ The rest destruction the calls copyDataProperties to perform the
+ copy of rest properties in rhs.
+
+ We also implemented CopyDataProperties as private JS global operation
+ on builtins/GlobalOperations.js following it's specification on [3].
+ It is implemented using Set object to verify if a property is on
+ excludedNames to keep this algorithm with O(n + m) complexity, where n
+ = number of source's own properties and m = excludedNames.length.
+
+ As a requirement to use JSSets as constants, a change in
+ CodeBlock::create API was necessary, because JSSet creation can throws OOM
+ exception. Now, CodeBlock::finishCreation returns ```false``` if an
+ execption is throwed by
+ CodeBlock::setConstantIdentifierSetRegisters and then we return
+ nullptr to ScriptExecutable::newCodeBlockFor. It is responsible to
+ check if CodeBlock was constructed properly and then, throw OOM
+ exception to the correct scope.
+
+ [1] - https://github.com/sebmarkbage/ecmascript-rest-spread
+ [2] - http://sebmarkbage.github.io/ecmascript-rest-spread/#Rest-RuntimeSemantics-PropertyDestructuringAssignmentEvaluation
+ [3] - http://sebmarkbage.github.io/ecmascript-rest-spread/#AbstractOperations-CopyDataProperties
+
+ * builtins/BuiltinNames.h:
+ * builtins/GlobalOperations.js:
+ (globalPrivate.copyDataProperties):
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::finishCreation):
+ (JSC::CodeBlock::setConstantIdentifierSetRegisters):
+ * bytecode/CodeBlock.h:
+ * bytecode/EvalCodeBlock.h:
+ (JSC::EvalCodeBlock::create):
+ * bytecode/FunctionCodeBlock.h:
+ (JSC::FunctionCodeBlock::create):
+ * bytecode/ModuleProgramCodeBlock.h:
+ (JSC::ModuleProgramCodeBlock::create):
+ * bytecode/ProgramCodeBlock.h:
+ (JSC::ProgramCodeBlock::create):
+ * bytecode/UnlinkedCodeBlock.h:
+ (JSC::UnlinkedCodeBlock::addSetConstant):
+ (JSC::UnlinkedCodeBlock::constantIdentifierSets):
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::emitLoad):
+ * bytecompiler/BytecodeGenerator.h:
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::ObjectPatternNode::bindValue):
+ * parser/ASTBuilder.h:
+ (JSC::ASTBuilder::appendObjectPatternEntry):
+ (JSC::ASTBuilder::appendObjectPatternRestEntry):
+ (JSC::ASTBuilder::setContainsObjectRestElement):
+ * parser/Nodes.h:
+ (JSC::ObjectPatternNode::appendEntry):
+ (JSC::ObjectPatternNode::setContainsRestElement):
+ * parser/Parser.cpp:
+ (JSC::Parser<LexerType>::parseDestructuringPattern):
+ (JSC::Parser<LexerType>::parseProperty):
+ * parser/SyntaxChecker.h:
+ (JSC::SyntaxChecker::operatorStackPop):
+ * runtime/JSGlobalObject.cpp:
+ (JSC::JSGlobalObject::init):
+ * runtime/JSGlobalObjectFunctions.cpp:
+ (JSC::privateToObject):
+ * runtime/JSGlobalObjectFunctions.h:
+ * runtime/ScriptExecutable.cpp:
+ (JSC::ScriptExecutable::newCodeBlockFor):
+
2017-03-09 Mark Lam <[email protected]>
Implement a StackTrace utility object that can capture stack traces for debugging.
Modified: trunk/Source/_javascript_Core/builtins/BuiltinNames.h (213696 => 213697)
--- trunk/Source/_javascript_Core/builtins/BuiltinNames.h 2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/_javascript_Core/builtins/BuiltinNames.h 2017-03-10 02:00:33 UTC (rev 213697)
@@ -158,6 +158,7 @@
macro(stringIncludesInternal) \
macro(stringSplitFast) \
macro(stringSubstrInternal) \
+ macro(toObject) \
macro(makeBoundFunction) \
macro(hasOwnLengthProperty) \
macro(importModule) \
Modified: trunk/Source/_javascript_Core/builtins/GlobalOperations.js (213696 => 213697)
--- trunk/Source/_javascript_Core/builtins/GlobalOperations.js 2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/_javascript_Core/builtins/GlobalOperations.js 2017-03-10 02:00:33 UTC (rev 213697)
@@ -79,3 +79,29 @@
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 === @undefined || source === null)
+ return target;
+
+ let from = @toObject(source);
+ let keys = @Object.@getOwnPropertyNames(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;
+}
Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (213696 => 213697)
--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2017-03-10 02:00:33 UTC (rev 213697)
@@ -58,6 +58,8 @@
#include "JSFunction.h"
#include "JSLexicalEnvironment.h"
#include "JSModuleEnvironment.h"
+#include "JSSet.h"
+#include "JSString.h"
#include "LLIntData.h"
#include "LLIntEntrypoint.h"
#include "LLIntPrototypeLoadAdaptiveStructureWatchpoint.h"
@@ -393,7 +395,7 @@
setNumParameters(unlinkedCodeBlock->numParameters());
}
-void CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock,
+bool CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock,
JSScope* scope)
{
Base::finishCreation(vm);
@@ -402,6 +404,8 @@
vm.functionHasExecutedCache()->removeUnexecutedRange(ownerExecutable->sourceID(), ownerExecutable->typeProfilingStartOffset(), ownerExecutable->typeProfilingEndOffset());
setConstantRegisters(unlinkedCodeBlock->constantRegisters(), unlinkedCodeBlock->constantsSourceCodeRepresentation());
+ if (!setConstantIdentifierSetRegisters(vm, unlinkedCodeBlock->constantIdentifierSets()))
+ return false;
if (unlinkedCodeBlock->usesGlobalObject())
m_constantRegisters[unlinkedCodeBlock->globalObjectRegister().toConstantIndex()].set(*m_vm, this, m_globalObject.get());
@@ -822,6 +826,8 @@
heap()->m_codeBlocks->add(this);
heap()->reportExtraMemoryAllocated(m_instructions.size() * sizeof(Instruction));
+
+ return true;
}
CodeBlock::~CodeBlock()
@@ -857,6 +863,31 @@
#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 HashSet<UniquedStringImpl*>& set = entry.first;
+ for (auto setEntry : set) {
+ JSString* jsString = jsOwnedString(&vm, setEntry);
+ jsSet->add(exec, JSValue(jsString));
+ RETURN_IF_EXCEPTION(scope, false);
+ }
+ m_constantRegisters[entry.second].set(vm, this, JSValue(jsSet));
+ }
+
+ scope.release();
+ return true;
+}
+
void CodeBlock::setConstantRegisters(const Vector<WriteBarrier<Unknown>>& constants, const Vector<SourceCodeRepresentation>& constantsSourceCodeRepresentation)
{
ASSERT(constants.size() == constantsSourceCodeRepresentation.size());
Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.h (213696 => 213697)
--- trunk/Source/_javascript_Core/bytecode/CodeBlock.h 2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.h 2017-03-10 02:00:33 UTC (rev 213697)
@@ -121,7 +121,7 @@
CodeBlock(VM*, Structure*, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock*, JSScope*, RefPtr<SourceProvider>&&, unsigned sourceOffset, unsigned firstLineColumnOffset);
void finishCreation(VM&, CopyParsedBlockTag, CodeBlock& other);
- void finishCreation(VM&, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock*, JSScope*);
+ bool finishCreation(VM&, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock*, JSScope*);
WriteBarrier<JSGlobalObject> m_globalObject;
@@ -917,6 +917,8 @@
void updateAllPredictionsAndCountLiveness(unsigned& numberOfLiveNonArgumentValueProfiles, unsigned& numberOfSamplesInProfiles);
+ bool setConstantIdentifierSetRegisters(VM&, const Vector<ConstantIndentifierSetEntry>& constants);
+
void setConstantRegisters(const Vector<WriteBarrier<Unknown>>& constants, const Vector<SourceCodeRepresentation>& constantsSourceCodeRepresentation);
void replaceConstant(int index, JSValue value)
Modified: trunk/Source/_javascript_Core/bytecode/EvalCodeBlock.h (213696 => 213697)
--- trunk/Source/_javascript_Core/bytecode/EvalCodeBlock.h 2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/_javascript_Core/bytecode/EvalCodeBlock.h 2017-03-10 02:00:33 UTC (rev 213697)
@@ -51,7 +51,8 @@
{
EvalCodeBlock* instance = new (NotNull, allocateCell<EvalCodeBlock>(vm->heap))
EvalCodeBlock(vm, vm->evalCodeBlockStructure.get(), ownerExecutable, unlinkedCodeBlock, scope, WTFMove(sourceProvider));
- instance->finishCreation(*vm, ownerExecutable, unlinkedCodeBlock, scope);
+ if (!instance->finishCreation(*vm, ownerExecutable, unlinkedCodeBlock, scope))
+ return nullptr;
return instance;
}
Modified: trunk/Source/_javascript_Core/bytecode/FunctionCodeBlock.h (213696 => 213697)
--- trunk/Source/_javascript_Core/bytecode/FunctionCodeBlock.h 2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/_javascript_Core/bytecode/FunctionCodeBlock.h 2017-03-10 02:00:33 UTC (rev 213697)
@@ -52,7 +52,8 @@
{
FunctionCodeBlock* instance = new (NotNull, allocateCell<FunctionCodeBlock>(vm->heap))
FunctionCodeBlock(vm, vm->functionCodeBlockStructure.get(), ownerExecutable, unlinkedCodeBlock, scope, WTFMove(sourceProvider), sourceOffset, firstLineColumnOffset);
- instance->finishCreation(*vm, ownerExecutable, unlinkedCodeBlock, scope);
+ if (!instance->finishCreation(*vm, ownerExecutable, unlinkedCodeBlock, scope))
+ return nullptr;
return instance;
}
Modified: trunk/Source/_javascript_Core/bytecode/ModuleProgramCodeBlock.h (213696 => 213697)
--- trunk/Source/_javascript_Core/bytecode/ModuleProgramCodeBlock.h 2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/_javascript_Core/bytecode/ModuleProgramCodeBlock.h 2017-03-10 02:00:33 UTC (rev 213697)
@@ -52,7 +52,8 @@
{
ModuleProgramCodeBlock* instance = new (NotNull, allocateCell<ModuleProgramCodeBlock>(vm->heap))
ModuleProgramCodeBlock(vm, vm->moduleProgramCodeBlockStructure.get(), ownerExecutable, unlinkedCodeBlock, scope, WTFMove(sourceProvider), firstLineColumnOffset);
- instance->finishCreation(*vm, ownerExecutable, unlinkedCodeBlock, scope);
+ if (!instance->finishCreation(*vm, ownerExecutable, unlinkedCodeBlock, scope))
+ return nullptr;
return instance;
}
Modified: trunk/Source/_javascript_Core/bytecode/ProgramCodeBlock.h (213696 => 213697)
--- trunk/Source/_javascript_Core/bytecode/ProgramCodeBlock.h 2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/_javascript_Core/bytecode/ProgramCodeBlock.h 2017-03-10 02:00:33 UTC (rev 213697)
@@ -52,7 +52,8 @@
{
ProgramCodeBlock* instance = new (NotNull, allocateCell<ProgramCodeBlock>(vm->heap))
ProgramCodeBlock(vm, vm->programCodeBlockStructure.get(), ownerExecutable, unlinkedCodeBlock, scope, WTFMove(sourceProvider), firstLineColumnOffset);
- instance->finishCreation(*vm, ownerExecutable, unlinkedCodeBlock, scope);
+ if (!instance->finishCreation(*vm, ownerExecutable, unlinkedCodeBlock, scope))
+ return nullptr;
return instance;
}
Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h (213696 => 213697)
--- trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h 2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h 2017-03-10 02:00:33 UTC (rev 213697)
@@ -41,9 +41,12 @@
#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 {
@@ -65,6 +68,7 @@
typedef unsigned UnlinkedArrayAllocationProfile;
typedef unsigned UnlinkedObjectAllocationProfile;
typedef unsigned UnlinkedLLIntCallLinkInfo;
+typedef std::pair<HashSet<UniquedStringImpl*>, unsigned> ConstantIndentifierSetEntry;
struct UnlinkedStringJumpTable {
struct OffsetLocation {
@@ -182,6 +186,16 @@
m_bitVectors.append(WTFMove(bitVector));
return m_bitVectors.size() - 1;
}
+
+ void addSetConstant(HashSet<UniquedStringImpl*>& 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)
{
@@ -213,6 +227,7 @@
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(); }
@@ -446,6 +461,7 @@
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;
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (213696 => 213697)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2017-03-10 02:00:33 UTC (rev 213697)
@@ -1920,6 +1920,27 @@
return constantID;
}
+RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, HashSet<UniquedStringImpl*>& set)
+{
+ for (ConstantIndentifierSetEntry 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) {
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (213696 => 213697)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2017-03-10 02:00:33 UTC (rev 213697)
@@ -587,6 +587,7 @@
RegisterID* emitLoad(RegisterID* dst, bool);
RegisterID* emitLoad(RegisterID* dst, const Identifier&);
RegisterID* emitLoad(RegisterID* dst, JSValue, SourceCodeRepresentation = SourceCodeRepresentation::Other);
+ RegisterID* emitLoad(RegisterID* dst, HashSet<UniquedStringImpl*>& excludedList);
RegisterID* emitLoadGlobalObject(RegisterID* dst);
RegisterID* emitUnaryOp(OpcodeID, RegisterID* dst, RegisterID* src);
Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (213696 => 213697)
--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2017-03-10 02:00:33 UTC (rev 213697)
@@ -41,8 +41,10 @@
#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;
@@ -4027,25 +4029,56 @@
void ObjectPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const
{
generator.emitRequireObjectCoercible(rhs, ASCIILiteral("Right side of assignment cannot be destructured"));
+
+ HashSet<UniquedStringImpl*> excludedSet;
+
for (const auto& target : m_targetPatterns) {
- 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 (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());
}
+
+ 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> propertyName = generator.emitNode(target.propertyExpression);
- generator.emitGetByVal(temp.get(), rhs, propertyName.get());
+ 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());
}
-
- if (target.defaultValue)
- assignDefaultValueIfUndefined(generator, temp.get(), target.defaultValue);
- target.pattern->bindValue(generator, temp.get());
}
}
Modified: trunk/Source/_javascript_Core/parser/ASTBuilder.h (213696 => 213697)
--- trunk/Source/_javascript_Core/parser/ASTBuilder.h 2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/_javascript_Core/parser/ASTBuilder.h 2017-03-10 02:00:33 UTC (rev 213697)
@@ -942,16 +942,26 @@
void appendObjectPatternEntry(ObjectPattern node, const JSTokenLocation& location, bool wasString, const Identifier& identifier, DestructuringPattern pattern, ExpressionNode* defaultValue)
{
- node->appendEntry(location, identifier, wasString, pattern, defaultValue);
+ node->appendEntry(location, identifier, wasString, pattern, defaultValue, ObjectPatternNode::BindingType::Element);
tryInferNameInPattern(pattern, defaultValue);
}
void appendObjectPatternEntry(ObjectPattern node, const JSTokenLocation& location, ExpressionNode* propertyExpression, DestructuringPattern pattern, ExpressionNode* defaultValue)
{
- node->appendEntry(location, propertyExpression, pattern, defaultValue);
+ node->appendEntry(location, propertyExpression, pattern, defaultValue, ObjectPatternNode::BindingType::Element);
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)
{
return new (m_parserArena) BindingNode(boundProperty, start, end, context);
Modified: trunk/Source/_javascript_Core/parser/Nodes.h (213696 => 213697)
--- trunk/Source/_javascript_Core/parser/Nodes.h 2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/_javascript_Core/parser/Nodes.h 2017-03-10 02:00:33 UTC (rev 213697)
@@ -2129,20 +2129,29 @@
Vector<Entry> m_targetPatterns;
};
- class ObjectPatternNode : public DestructuringPatternNode, public ParserArenaDeletable {
+ class ObjectPatternNode : public DestructuringPatternNode, public ThrowableExpressionData, public ParserArenaDeletable {
public:
using ParserArenaDeletable::operator new;
ObjectPatternNode();
- void appendEntry(const JSTokenLocation&, const Identifier& identifier, bool wasString, DestructuringPatternNode* pattern, ExpressionNode* defaultValue)
+ enum class BindingType {
+ Element,
+ RestElement
+ };
+ void appendEntry(const JSTokenLocation&, const Identifier& identifier, bool wasString, DestructuringPatternNode* pattern, ExpressionNode* defaultValue, BindingType bindingType)
{
- m_targetPatterns.append(Entry{ identifier, nullptr, wasString, pattern, defaultValue });
+ m_targetPatterns.append(Entry{ identifier, nullptr, wasString, pattern, defaultValue, bindingType });
}
- void appendEntry(const JSTokenLocation&, ExpressionNode* propertyExpression, DestructuringPatternNode* pattern, ExpressionNode* defaultValue)
+ void appendEntry(const JSTokenLocation&, ExpressionNode* propertyExpression, DestructuringPatternNode* pattern, ExpressionNode* defaultValue, BindingType bindingType)
{
- m_targetPatterns.append(Entry{ Identifier(), propertyExpression, false, pattern, defaultValue });
+ m_targetPatterns.append(Entry{ Identifier(), propertyExpression, false, pattern, defaultValue, bindingType });
}
+
+ void setContainsRestElement(bool containsRestElement)
+ {
+ m_containsRestElement = containsRestElement;
+ }
private:
void collectBoundIdentifiers(Vector<Identifier>&) const override;
@@ -2154,7 +2163,9 @@
bool wasString;
DestructuringPatternNode* pattern;
ExpressionNode* defaultValue;
+ BindingType bindingType;
};
+ bool m_containsRestElement { false };
Vector<Entry> m_targetPatterns;
};
Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (213696 => 213697)
--- trunk/Source/_javascript_Core/parser/Parser.cpp 2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp 2017-03-10 02:00:33 UTC (rev 213697)
@@ -1002,6 +1002,8 @@
if (hasDestructuringPattern)
*hasDestructuringPattern = true;
+ bool restElementWasFound = false;
+
do {
bool wasString = false;
@@ -1008,6 +1010,19 @@
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;
@@ -1082,7 +1097,7 @@
if (kind == DestructuringKind::DestructureToExpressions && !match(CLOSEBRACE))
return 0;
- consumeOrFail(CLOSEBRACE, "Expected either a closing '}' or an ',' after a property destructuring pattern");
+ consumeOrFail(CLOSEBRACE, restElementWasFound ? "Expected a closing '}' following a rest element destructuring pattern" : "Expected either a closing '}' or an ',' after a property destructuring pattern");
pattern = objectPattern;
break;
}
@@ -3763,6 +3778,10 @@
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: {
+ classifyExpressionError(ErrorIndicatesPattern);
+ FALLTHROUGH;
+ }
default:
failIfFalse(m_token.m_type & KeywordTokenFlag, "Expected a property name");
wasIdent = true; // Treat keyword token as an identifier
Modified: trunk/Source/_javascript_Core/parser/SyntaxChecker.h (213696 => 213697)
--- trunk/Source/_javascript_Core/parser/SyntaxChecker.h 2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/_javascript_Core/parser/SyntaxChecker.h 2017-03-10 02:00:33 UTC (rev 213697)
@@ -352,6 +352,12 @@
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)
{
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (213696 => 213697)
--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp 2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp 2017-03-10 02:00:33 UTC (rev 213697)
@@ -735,6 +735,7 @@
JSFunction* privateFuncGetTemplateObject = JSFunction::create(vm, this, 0, String(), getTemplateObject);
JSFunction* privateFuncImportModule = JSFunction::create(vm, this, 0, String(), globalFuncImportModule);
+ JSFunction* privateFuncToObject = JSFunction::create(vm, this, 0, String(), privateToObject);
JSFunction* privateFuncTypedArrayLength = JSFunction::create(vm, this, 0, String(), typedArrayViewPrivateFuncLength);
JSFunction* privateFuncTypedArrayGetOriginalConstructor = JSFunction::create(vm, this, 0, String(), typedArrayViewPrivateFuncGetOriginalConstructor);
JSFunction* privateFuncTypedArraySort = JSFunction::create(vm, this, 0, String(), typedArrayViewPrivateFuncSort);
@@ -789,6 +790,7 @@
GlobalPropertyInfo(vm.propertyNames->builtinNames().ownEnumerablePropertyKeysPrivateName(), JSFunction::create(vm, this, 0, String(), ownEnumerablePropertyKeys), DontEnum | DontDelete | ReadOnly),
GlobalPropertyInfo(vm.propertyNames->builtinNames().getTemplateObjectPrivateName(), privateFuncGetTemplateObject, DontEnum | DontDelete | ReadOnly),
GlobalPropertyInfo(vm.propertyNames->builtinNames().importModulePrivateName(), privateFuncImportModule, DontEnum | DontDelete | ReadOnly),
+ GlobalPropertyInfo(vm.propertyNames->builtinNames().toObjectPrivateName(), privateFuncToObject, DontEnum | DontDelete | ReadOnly),
GlobalPropertyInfo(vm.propertyNames->builtinNames().enqueueJobPrivateName(), JSFunction::create(vm, this, 0, String(), enqueueJob), DontEnum | DontDelete | ReadOnly),
GlobalPropertyInfo(vm.propertyNames->builtinNames().ErrorPrivateName(), m_errorConstructor.get(), DontEnum | DontDelete | ReadOnly),
GlobalPropertyInfo(vm.propertyNames->builtinNames().RangeErrorPrivateName(), m_rangeErrorConstructor.get(), DontEnum | DontDelete | ReadOnly),
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp (213696 => 213697)
--- trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp 2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp 2017-03-10 02:00:33 UTC (rev 213697)
@@ -735,6 +735,11 @@
thisObject->setPrototype(vm, exec, value, shouldThrowIfCantSet);
return JSValue::encode(jsUndefined());
}
+
+EncodedJSValue JSC_HOST_CALL privateToObject(ExecState* exec)
+{
+ return JSValue::encode(JSValue(exec->argument(0).toObject(exec)));
+}
EncodedJSValue JSC_HOST_CALL globalFuncBuiltinLog(ExecState* exec)
{
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.h (213696 => 213697)
--- trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.h 2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.h 2017-03-10 02:00:33 UTC (rev 213697)
@@ -50,6 +50,7 @@
EncodedJSValue JSC_HOST_CALL globalFuncProtoGetter(ExecState*);
EncodedJSValue JSC_HOST_CALL globalFuncProtoSetter(ExecState*);
EncodedJSValue JSC_HOST_CALL globalFuncBuiltinLog(ExecState*);
+EncodedJSValue JSC_HOST_CALL privateToObject(ExecState*);
EncodedJSValue JSC_HOST_CALL globalFuncImportModule(ExecState*);
double jsToNumber(StringView);
Modified: trunk/Source/_javascript_Core/runtime/ObjectConstructor.cpp (213696 => 213697)
--- trunk/Source/_javascript_Core/runtime/ObjectConstructor.cpp 2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/_javascript_Core/runtime/ObjectConstructor.cpp 2017-03-10 02:00:33 UTC (rev 213697)
@@ -105,6 +105,7 @@
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])
Modified: trunk/Source/_javascript_Core/runtime/ScriptExecutable.cpp (213696 => 213697)
--- trunk/Source/_javascript_Core/runtime/ScriptExecutable.cpp 2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/_javascript_Core/runtime/ScriptExecutable.cpp 2017-03-10 02:00:33 UTC (rev 213697)
@@ -176,14 +176,24 @@
ASSERT(vm->heap.isDeferred());
ASSERT(endColumn() != UINT_MAX);
+ JSGlobalObject* globalObject = scope->globalObject();
+ ExecState* exec = globalObject->globalExec();
+
if (classInfo(*vm) == EvalExecutable::info()) {
EvalExecutable* executable = jsCast<EvalExecutable*>(this);
RELEASE_ASSERT(kind == CodeForCall);
RELEASE_ASSERT(!executable->m_evalCodeBlock);
RELEASE_ASSERT(!function);
- return EvalCodeBlock::create(vm,
+ auto codeBlock = EvalCodeBlock::create(vm,
executable, executable->m_unlinkedEvalCodeBlock.get(), scope,
executable->source().provider());
+ if (!codeBlock) {
+ exception = throwException(
+ exec, throwScope,
+ createOutOfMemoryError(exec));
+ return nullptr;
+ }
+ return codeBlock;
}
if (classInfo(*vm) == ProgramExecutable::info()) {
@@ -191,9 +201,16 @@
RELEASE_ASSERT(kind == CodeForCall);
RELEASE_ASSERT(!executable->m_programCodeBlock);
RELEASE_ASSERT(!function);
- return ProgramCodeBlock::create(vm,
+ auto codeBlock = ProgramCodeBlock::create(vm,
executable, executable->m_unlinkedProgramCodeBlock.get(), scope,
executable->source().provider(), startColumn());
+ if (!codeBlock) {
+ exception = throwException(
+ exec, throwScope,
+ createOutOfMemoryError(exec));
+ return nullptr;
+ }
+ return codeBlock;
}
if (classInfo(*vm) == ModuleProgramExecutable::info()) {
@@ -201,9 +218,16 @@
RELEASE_ASSERT(kind == CodeForCall);
RELEASE_ASSERT(!executable->m_moduleProgramCodeBlock);
RELEASE_ASSERT(!function);
- return ModuleProgramCodeBlock::create(vm,
+ auto codeBlock = ModuleProgramCodeBlock::create(vm,
executable, executable->m_unlinkedModuleProgramCodeBlock.get(), scope,
executable->source().provider(), startColumn());
+ if (!codeBlock) {
+ exception = throwException(
+ exec, throwScope,
+ createOutOfMemoryError(exec));
+ return nullptr;
+ }
+ return codeBlock;
}
RELEASE_ASSERT(classInfo(*vm) == FunctionExecutable::info());
@@ -210,7 +234,6 @@
RELEASE_ASSERT(function);
FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
RELEASE_ASSERT(!executable->codeBlockFor(kind));
- JSGlobalObject* globalObject = scope->globalObject();
ParserError error;
DebuggerMode debuggerMode = globalObject->hasInteractiveDebugger() ? DebuggerOn : DebuggerOff;
UnlinkedFunctionCodeBlock* unlinkedCodeBlock =
Modified: trunk/Source/_javascript_Core/runtime/SetPrototype.cpp (213696 => 213697)
--- trunk/Source/_javascript_Core/runtime/SetPrototype.cpp 2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/_javascript_Core/runtime/SetPrototype.cpp 2017-03-10 02:00:33 UTC (rev 213697)
@@ -67,6 +67,7 @@
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);
Modified: trunk/Source/WTF/ChangeLog (213696 => 213697)
--- trunk/Source/WTF/ChangeLog 2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/WTF/ChangeLog 2017-03-10 02:00:33 UTC (rev 213697)
@@ -1,3 +1,13 @@
+2017-03-09 Caio Lima <[email protected]>
+
+ [ESnext] Implement Object Rest - Implementing Object Rest Destructuring
+ https://bugs.webkit.org/show_bug.cgi?id=167962
+
+ Reviewed by Keith Miller.
+
+ * wtf/HashSet.h:
+ (WTF::=):
+
2017-03-09 Youenn Fablet <[email protected]>
Activate VideoToolbox when WebRTC is enabled on iOS
Modified: trunk/Source/WTF/wtf/HashSet.h (213696 => 213697)
--- trunk/Source/WTF/wtf/HashSet.h 2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/WTF/wtf/HashSet.h 2017-03-10 02:00:33 UTC (rev 213697)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005, 2006, 2007, 2008, 2011, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2005, 2006, 2007, 2008, 2011, 2013, 2017 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
@@ -120,6 +120,9 @@
template<typename OtherCollection>
bool operator==(const OtherCollection&) const;
+
+ template<typename OtherCollection>
+ bool operator!=(const OtherCollection&) const;
private:
HashTableType m_impl;
@@ -362,6 +365,13 @@
}
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