Diff
Modified: trunk/LayoutTests/ChangeLog (197530 => 197531)
--- trunk/LayoutTests/ChangeLog 2016-03-04 00:39:41 UTC (rev 197530)
+++ trunk/LayoutTests/ChangeLog 2016-03-04 00:47:55 UTC (rev 197531)
@@ -1,3 +1,15 @@
+2016-03-03 Keith Miller <[email protected]>
+
+ [ES6] Add support for Symbol.toPrimitive
+ https://bugs.webkit.org/show_bug.cgi?id=154877
+
+ Reviewed by Saam Barati.
+
+ Update test for Symbol.toPrimitive.
+
+ * js/Object-getOwnPropertyNames-expected.txt:
+ * js/script-tests/Object-getOwnPropertyNames.js:
+
2016-03-02 Ryosuke Niwa <[email protected]>
Disallow custom elements inside template elements and share the registry for windowless documents
Modified: trunk/LayoutTests/http/tests/security/cross-frame-access-custom-expected.txt (197530 => 197531)
--- trunk/LayoutTests/http/tests/security/cross-frame-access-custom-expected.txt 2016-03-04 00:39:41 UTC (rev 197530)
+++ trunk/LayoutTests/http/tests/security/cross-frame-access-custom-expected.txt 2016-03-04 00:47:55 UTC (rev 197531)
@@ -17,6 +17,7 @@
CONSOLE MESSAGE: line 82: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
CONSOLE MESSAGE: line 81: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
CONSOLE MESSAGE: line 107: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
+CONSOLE MESSAGE: line 107: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
----- tests for getting/setting interesting properties -----
Modified: trunk/LayoutTests/http/tests/security/cross-frame-access-location-get-expected.txt (197530 => 197531)
--- trunk/LayoutTests/http/tests/security/cross-frame-access-location-get-expected.txt 2016-03-04 00:39:41 UTC (rev 197530)
+++ trunk/LayoutTests/http/tests/security/cross-frame-access-location-get-expected.txt 2016-03-04 00:47:55 UTC (rev 197531)
@@ -1,5 +1,6 @@
CONSOLE MESSAGE: line 107: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
CONSOLE MESSAGE: line 107: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
+CONSOLE MESSAGE: line 107: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
CONSOLE MESSAGE: line 55: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
CONSOLE MESSAGE: line 55: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
CONSOLE MESSAGE: line 55: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
Modified: trunk/LayoutTests/http/tests/security/cross-frame-access-object-setPrototypeOf-expected.txt (197530 => 197531)
--- trunk/LayoutTests/http/tests/security/cross-frame-access-object-setPrototypeOf-expected.txt 2016-03-04 00:39:41 UTC (rev 197530)
+++ trunk/LayoutTests/http/tests/security/cross-frame-access-object-setPrototypeOf-expected.txt 2016-03-04 00:47:55 UTC (rev 197531)
@@ -1,5 +1,6 @@
CONSOLE MESSAGE: line 1: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
CONSOLE MESSAGE: line 22: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
+CONSOLE MESSAGE: line 22: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
CONSOLE MESSAGE: line 25: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
This tests that you can't set the prototype of the window or history objects cross-origin using Object.setPrototypeOf().
Modified: trunk/LayoutTests/js/Object-getOwnPropertyNames-expected.txt (197530 => 197531)
--- trunk/LayoutTests/js/Object-getOwnPropertyNames-expected.txt 2016-03-04 00:39:41 UTC (rev 197530)
+++ trunk/LayoutTests/js/Object-getOwnPropertyNames-expected.txt 2016-03-04 00:47:55 UTC (rev 197531)
@@ -61,7 +61,7 @@
PASS getSortedOwnPropertyNames(Error.prototype) is ['constructor', 'message', 'name', 'toString']
PASS getSortedOwnPropertyNames(Math) is ['E','LN10','LN2','LOG10E','LOG2E','PI','SQRT1_2','SQRT2','abs','acos','acosh','asin','asinh','atan','atan2','atanh','cbrt','ceil','clz32','cos','cosh','exp','expm1','floor','fround','hypot','imul','log','log10','log1p','log2','max','min','pow','random','round','sign','sin','sinh','sqrt','tan','tanh','trunc']
PASS getSortedOwnPropertyNames(JSON) is ['parse', 'stringify']
-PASS getSortedOwnPropertyNames(Symbol) is ['for', 'hasInstance', 'iterator', 'keyFor', 'length', 'name', 'prototype', 'search', 'species', 'toStringTag', 'unscopables']
+PASS getSortedOwnPropertyNames(Symbol) is ['for', 'hasInstance', 'iterator', 'keyFor', 'length', 'name', 'prototype', 'search', 'species', 'toPrimitive', 'toStringTag', 'unscopables']
PASS getSortedOwnPropertyNames(Symbol.prototype) is ['constructor', 'toString', 'valueOf']
PASS getSortedOwnPropertyNames(Map) is ['length', 'name', 'prototype']
PASS getSortedOwnPropertyNames(Map.prototype) is ['clear', 'constructor', 'delete', 'entries', 'forEach', 'get', 'has', 'keys', 'set', 'size', 'values']
Modified: trunk/LayoutTests/js/script-tests/Object-getOwnPropertyNames.js (197530 => 197531)
--- trunk/LayoutTests/js/script-tests/Object-getOwnPropertyNames.js 2016-03-04 00:39:41 UTC (rev 197530)
+++ trunk/LayoutTests/js/script-tests/Object-getOwnPropertyNames.js 2016-03-04 00:47:55 UTC (rev 197531)
@@ -70,7 +70,7 @@
"Error.prototype": "['constructor', 'message', 'name', 'toString']",
"Math": "['E','LN10','LN2','LOG10E','LOG2E','PI','SQRT1_2','SQRT2','abs','acos','acosh','asin','asinh','atan','atan2','atanh','cbrt','ceil','clz32','cos','cosh','exp','expm1','floor','fround','hypot','imul','log','log10','log1p','log2','max','min','pow','random','round','sign','sin','sinh','sqrt','tan','tanh','trunc']",
"JSON": "['parse', 'stringify']",
- "Symbol": "['for', 'hasInstance', 'iterator', 'keyFor', 'length', 'name', 'prototype', 'search', 'species', 'toStringTag', 'unscopables']",
+ "Symbol": "['for', 'hasInstance', 'iterator', 'keyFor', 'length', 'name', 'prototype', 'search', 'species', 'toPrimitive', 'toStringTag', 'unscopables']",
"Symbol.prototype": "['constructor', 'toString', 'valueOf']",
"Map": "['length', 'name', 'prototype']",
"Map.prototype": "['clear', 'constructor', 'delete', 'entries', 'forEach', 'get', 'has', 'keys', 'set', 'size', 'values']",
Modified: trunk/Source/_javascript_Core/ChangeLog (197530 => 197531)
--- trunk/Source/_javascript_Core/ChangeLog 2016-03-04 00:39:41 UTC (rev 197530)
+++ trunk/Source/_javascript_Core/ChangeLog 2016-03-04 00:47:55 UTC (rev 197531)
@@ -1,3 +1,58 @@
+2016-03-03 Keith Miller <[email protected]>
+
+ [ES6] Add support for Symbol.toPrimitive
+ https://bugs.webkit.org/show_bug.cgi?id=154877
+
+ Reviewed by Saam Barati.
+
+ This patch adds suport for Symbol.toPrimitive. Since we don't currently
+ generate snippits for one side of a binary operation we only need to change
+ the JSObject::ToPrimitive function and update some optimizations in the DFG
+ that need to know how conversions to primitive values should work. As of
+ ES6, the date prototype is also no longer special cased in the ToPrimitive
+ operation. Instead, Date.prototype has a Symbol.species function that
+ replicates the old behavior.
+
+ * bytecode/ObjectPropertyConditionSet.cpp:
+ (JSC::generateConditionsForPropertyMissConcurrently):
+ * bytecode/ObjectPropertyConditionSet.h:
+ * dfg/DFGGraph.cpp:
+ (JSC::DFG::Graph::watchConditions):
+ (JSC::DFG::Graph::canOptimizeStringObjectAccess):
+ * dfg/DFGGraph.h:
+ * runtime/CommonIdentifiers.h:
+ * runtime/DatePrototype.cpp:
+ (JSC::DatePrototype::finishCreation):
+ (JSC::dateProtoFuncToPrimitiveSymbol):
+ * runtime/Error.cpp:
+ (JSC::throwTypeError):
+ * runtime/Error.h:
+ * runtime/JSCJSValueInlines.h:
+ (JSC::toPreferredPrimitiveType):
+ * runtime/JSObject.cpp:
+ (JSC::callToPrimitiveFunction):
+ (JSC::JSObject::ordinaryToPrimitive):
+ (JSC::JSObject::defaultValue):
+ (JSC::JSObject::toPrimitive):
+ (JSC::JSObject::getPrimitiveNumber):
+ (JSC::callDefaultValueFunction): Deleted.
+ (JSC::throwTypeError): Deleted.
+ * runtime/JSObject.h:
+ (JSC::JSObject::toPrimitive): Deleted.
+ * runtime/SmallStrings.h:
+ * runtime/SymbolPrototype.cpp:
+ (JSC::SymbolPrototype::finishCreation):
+ * runtime/SymbolPrototype.h:
+ (JSC::SymbolPrototype::create):
+ * tests/es6.yaml:
+ * tests/stress/date-symbol-toprimitive.js: Added.
+ * tests/stress/ropes-symbol-toprimitive.js: Added.
+ (ropify):
+ (String.prototype.Symbol.toPrimitive):
+ * tests/stress/symbol-toprimitive.js: Added.
+ (foo.Symbol.toPrimitive):
+ (catch):
+
2016-03-03 Filip Pizlo <[email protected]>
DFG should be able to compile StringReplace
Modified: trunk/Source/_javascript_Core/bytecode/ObjectPropertyConditionSet.cpp (197530 => 197531)
--- trunk/Source/_javascript_Core/bytecode/ObjectPropertyConditionSet.cpp 2016-03-04 00:39:41 UTC (rev 197530)
+++ trunk/Source/_javascript_Core/bytecode/ObjectPropertyConditionSet.cpp 2016-03-04 00:47:55 UTC (rev 197531)
@@ -349,6 +349,20 @@
});
}
+ObjectPropertyConditionSet generateConditionsForPropertyMissConcurrently(
+ VM& vm, JSGlobalObject* globalObject, Structure* headStructure, UniquedStringImpl* uid)
+{
+ return generateConditions(
+ vm, globalObject, headStructure, nullptr,
+ [&] (Vector<ObjectPropertyCondition>& conditions, JSObject* object) -> bool {
+ ObjectPropertyCondition result = generateCondition(vm, nullptr, object, uid, PropertyCondition::Absence);
+ if (!result)
+ return false;
+ conditions.append(result);
+ return true;
+ }, Concurrent);
+}
+
ObjectPropertyConditionSet generateConditionsForPropertySetterMissConcurrently(
VM& vm, JSGlobalObject* globalObject, Structure* headStructure, UniquedStringImpl* uid)
{
Modified: trunk/Source/_javascript_Core/bytecode/ObjectPropertyConditionSet.h (197530 => 197531)
--- trunk/Source/_javascript_Core/bytecode/ObjectPropertyConditionSet.h 2016-03-04 00:39:41 UTC (rev 197530)
+++ trunk/Source/_javascript_Core/bytecode/ObjectPropertyConditionSet.h 2016-03-04 00:47:55 UTC (rev 197531)
@@ -166,6 +166,9 @@
VM&, JSCell* owner, ExecState*, Structure* headStructure, JSObject* prototype,
UniquedStringImpl* uid);
+
+ObjectPropertyConditionSet generateConditionsForPropertyMissConcurrently(
+ VM&, JSGlobalObject*, Structure* headStructure, UniquedStringImpl* uid);
ObjectPropertyConditionSet generateConditionsForPropertySetterMissConcurrently(
VM&, JSGlobalObject*, Structure* headStructure, UniquedStringImpl* uid);
Modified: trunk/Source/_javascript_Core/dfg/DFGGraph.cpp (197530 => 197531)
--- trunk/Source/_javascript_Core/dfg/DFGGraph.cpp 2016-03-04 00:39:41 UTC (rev 197530)
+++ trunk/Source/_javascript_Core/dfg/DFGGraph.cpp 2016-03-04 00:47:55 UTC (rev 197531)
@@ -890,6 +890,18 @@
return true;
}
+bool Graph::watchConditions(const ObjectPropertyConditionSet& keys)
+{
+ if (!keys.isValid())
+ return false;
+
+ for (const ObjectPropertyCondition& key : keys) {
+ if (!watchCondition(key))
+ return false;
+ }
+ return true;
+}
+
bool Graph::isSafeToLoad(JSObject* base, PropertyOffset offset)
{
return m_safeToLoad.contains(std::make_pair(base, offset));
@@ -1518,6 +1530,9 @@
if (stringPrototypeStructure->isDictionary())
return false;
+ if (!watchConditions(generateConditionsForPropertyMissConcurrently(m_vm, globalObjectFor(codeOrigin), stringObjectStructure, m_vm.propertyNames->toPrimitiveSymbol.impl())))
+ return false;
+
// We're being conservative here. We want DFG's ToString on StringObject to be
// used in both numeric contexts (that would call valueOf()) and string contexts
// (that would call toString()). We don't want the DFG to have to distinguish
Modified: trunk/Source/_javascript_Core/dfg/DFGGraph.h (197530 => 197531)
--- trunk/Source/_javascript_Core/dfg/DFGGraph.h 2016-03-04 00:39:41 UTC (rev 197530)
+++ trunk/Source/_javascript_Core/dfg/DFGGraph.h 2016-03-04 00:47:55 UTC (rev 197531)
@@ -650,6 +650,7 @@
// this also makes it cheap to query if the condition holds. Also makes sure that the GC knows
// what's going on.
bool watchCondition(const ObjectPropertyCondition&);
+ bool watchConditions(const ObjectPropertyConditionSet&);
// Checks if it's known that loading from the given object at the given offset is fine. This is
// computed by tracking which conditions we track with watchCondition().
Modified: trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h (197530 => 197531)
--- trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h 2016-03-04 00:39:41 UTC (rev 197530)
+++ trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h 2016-03-04 00:47:55 UTC (rev 197531)
@@ -276,13 +276,13 @@
macro(match) \
macro(replace) \
macro(split) \
- macro(toPrimitive)
#define JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_WELL_KNOWN_SYMBOL(macro) \
macro(hasInstance) \
macro(iterator) \
macro(search) \
macro(species) \
+ macro(toPrimitive) \
macro(toStringTag) \
macro(unscopables)
Modified: trunk/Source/_javascript_Core/runtime/DatePrototype.cpp (197530 => 197531)
--- trunk/Source/_javascript_Core/runtime/DatePrototype.cpp 2016-03-04 00:39:41 UTC (rev 197530)
+++ trunk/Source/_javascript_Core/runtime/DatePrototype.cpp 2016-03-04 00:47:55 UTC (rev 197531)
@@ -111,6 +111,7 @@
EncodedJSValue JSC_HOST_CALL dateProtoFuncToLocaleDateString(ExecState*);
EncodedJSValue JSC_HOST_CALL dateProtoFuncToLocaleString(ExecState*);
EncodedJSValue JSC_HOST_CALL dateProtoFuncToLocaleTimeString(ExecState*);
+EncodedJSValue JSC_HOST_CALL dateProtoFuncToPrimitiveSymbol(ExecState*);
EncodedJSValue JSC_HOST_CALL dateProtoFuncToString(ExecState*);
EncodedJSValue JSC_HOST_CALL dateProtoFuncToTimeString(ExecState*);
EncodedJSValue JSC_HOST_CALL dateProtoFuncToUTCString(ExecState*);
@@ -499,6 +500,7 @@
UNUSED_PARAM(globalObject);
#endif // ENABLE(INTL)
+ JSC_NATIVE_FUNCTION(vm.propertyNames->toPrimitiveSymbol, dateProtoFuncToPrimitiveSymbol, DontEnum | ReadOnly, 1);
// The constructor will be added later, after DateConstructor has been built.
}
@@ -597,6 +599,27 @@
return JSValue::encode(formatLocaleDate(exec, thisDateObj, thisDateObj->internalNumber(), LocaleTime));
}
+EncodedJSValue JSC_HOST_CALL dateProtoFuncToPrimitiveSymbol(ExecState* exec)
+{
+ JSValue thisValue = exec->thisValue();
+ if (!thisValue.isObject())
+ return throwVMTypeError(exec, "Date.prototype[Symbol.toPrimitive] expected |this| to be an object.");
+ JSObject* thisObject = jsCast<JSObject*>(thisValue);
+
+ if (!exec->argumentCount())
+ return throwVMTypeError(exec, "Date.prototype[Symbol.toPrimitive] expected a first argument.");
+
+ JSValue hintValue = exec->uncheckedArgument(0);
+ PreferredPrimitiveType type = toPreferredPrimitiveType(exec, hintValue);
+ if (exec->hadException())
+ return JSValue::encode(JSValue());
+
+ if (type == NoPreference)
+ type = PreferString;
+
+ return JSValue::encode(thisObject->ordinaryToPrimitive(exec, type));
+}
+
EncodedJSValue JSC_HOST_CALL dateProtoFuncGetTime(ExecState* exec)
{
JSValue thisValue = exec->thisValue();
Modified: trunk/Source/_javascript_Core/runtime/Error.cpp (197530 => 197531)
--- trunk/Source/_javascript_Core/runtime/Error.cpp 2016-03-04 00:39:41 UTC (rev 197530)
+++ trunk/Source/_javascript_Core/runtime/Error.cpp 2016-03-04 00:47:55 UTC (rev 197531)
@@ -219,6 +219,11 @@
return exec->vm().throwException(exec, createTypeError(exec));
}
+JSObject* throwTypeError(ExecState* exec, const String& message)
+{
+ return exec->vm().throwException(exec, createTypeError(exec, message));
+}
+
JSObject* throwSyntaxError(ExecState* exec)
{
return exec->vm().throwException(exec, createSyntaxError(exec, ASCIILiteral("Syntax error")));
Modified: trunk/Source/_javascript_Core/runtime/Error.h (197530 => 197531)
--- trunk/Source/_javascript_Core/runtime/Error.h 2016-03-04 00:39:41 UTC (rev 197530)
+++ trunk/Source/_javascript_Core/runtime/Error.h 2016-03-04 00:47:55 UTC (rev 197531)
@@ -74,6 +74,7 @@
// Convenience wrappers, create an throw an exception with a default message.
JS_EXPORT_PRIVATE JSObject* throwConstructorCannotBeCalledAsFunctionTypeError(ExecState*, const char* constructorName);
JS_EXPORT_PRIVATE JSObject* throwTypeError(ExecState*);
+JS_EXPORT_PRIVATE JSObject* throwTypeError(ExecState*, const String& errorMessage);
JS_EXPORT_PRIVATE JSObject* throwSyntaxError(ExecState*);
JS_EXPORT_PRIVATE JSObject* throwSyntaxError(ExecState*, const String& errorMessage);
inline JSObject* throwRangeError(ExecState* state, const String& errorMessage) { return state->vm().throwException(state, createRangeError(state, errorMessage)); }
Modified: trunk/Source/_javascript_Core/runtime/JSCJSValueInlines.h (197530 => 197531)
--- trunk/Source/_javascript_Core/runtime/JSCJSValueInlines.h 2016-03-04 00:39:41 UTC (rev 197530)
+++ trunk/Source/_javascript_Core/runtime/JSCJSValueInlines.h 2016-03-04 00:47:55 UTC (rev 197531)
@@ -628,6 +628,28 @@
return isCell() ? asCell()->toPrimitive(exec, preferredType) : asValue();
}
+inline PreferredPrimitiveType toPreferredPrimitiveType(ExecState* exec, JSValue value)
+{
+ if (!value.isString()) {
+ throwTypeError(exec, "Primitive hint is not a string.");
+ return NoPreference;
+ }
+
+ StringImpl* hintString = jsCast<JSString*>(value)->value(exec).impl();
+ if (exec->hadException())
+ return NoPreference;
+
+ if (WTF::equal(hintString, "default"))
+ return NoPreference;
+ if (WTF::equal(hintString, "number"))
+ return PreferNumber;
+ if (WTF::equal(hintString, "string"))
+ return PreferString;
+
+ throwTypeError(exec, "Expected primitive hint to match one of 'default', 'number', 'string'.");
+ return NoPreference;
+}
+
inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number, JSValue& value)
{
if (isInt32()) {
Modified: trunk/Source/_javascript_Core/runtime/JSObject.cpp (197530 => 197531)
--- trunk/Source/_javascript_Core/runtime/JSObject.cpp 2016-03-04 00:39:41 UTC (rev 197530)
+++ trunk/Source/_javascript_Core/runtime/JSObject.cpp 2016-03-04 00:47:55 UTC (rev 197531)
@@ -1426,55 +1426,67 @@
}
}
-static ALWAYS_INLINE JSValue callDefaultValueFunction(ExecState* exec, const JSObject* object, PropertyName propertyName)
+enum class TypeHintMode { TakesHint, DoesNotTakeHint };
+
+template<TypeHintMode mode = TypeHintMode::DoesNotTakeHint>
+static ALWAYS_INLINE JSValue callToPrimitiveFunction(ExecState* exec, const JSObject* object, PropertyName propertyName, PreferredPrimitiveType hint)
{
JSValue function = object->get(exec, propertyName);
+ if (exec->hadException())
+ return exec->exception();
+ if (function.isUndefined() && mode == TypeHintMode::TakesHint)
+ return JSValue();
CallData callData;
CallType callType = getCallData(function, callData);
if (callType == CallTypeNone)
return exec->exception();
- // Prevent "toString" and "valueOf" from observing execution if an exception
- // is pending.
- if (exec->hadException())
- return exec->exception();
+ MarkedArgumentBuffer callArgs;
+ if (mode == TypeHintMode::TakesHint) {
+ JSString* hintString;
+ switch (hint) {
+ case NoPreference:
+ hintString = exec->vm().smallStrings.defaultString();
+ break;
+ case PreferNumber:
+ hintString = exec->vm().smallStrings.numberString();
+ break;
+ case PreferString:
+ hintString = exec->vm().smallStrings.stringString();
+ break;
+ }
+ callArgs.append(hintString);
+ }
- JSValue result = call(exec, function, callType, callData, const_cast<JSObject*>(object), exec->emptyList());
+ JSValue result = call(exec, function, callType, callData, const_cast<JSObject*>(object), callArgs);
ASSERT(!result.isGetterSetter());
if (exec->hadException())
return exec->exception();
if (result.isObject())
- return JSValue();
+ return mode == TypeHintMode::DoesNotTakeHint ? JSValue() : throwTypeError(exec, "Symbol.toPrimitive returned an object");
return result;
}
-bool JSObject::getPrimitiveNumber(ExecState* exec, double& number, JSValue& result) const
+// ECMA 7.1.1
+inline JSValue JSObject::ordinaryToPrimitive(ExecState* exec, PreferredPrimitiveType hint) const
{
- result = methodTable(exec->vm())->defaultValue(this, exec, PreferNumber);
- number = result.toNumber(exec);
- return !result.isString();
-}
-
-// ECMA 8.6.2.6
-JSValue JSObject::defaultValue(const JSObject* object, ExecState* exec, PreferredPrimitiveType hint)
-{
// Make sure that whatever default value methods there are on object's prototype chain are
// being watched.
- object->structure()->startWatchingInternalPropertiesIfNecessaryForEntireChain(exec->vm());
-
- // Must call toString first for Date objects.
- if ((hint == PreferString) || (hint != PreferNumber && object->prototype() == exec->lexicalGlobalObject()->datePrototype())) {
- JSValue value = callDefaultValueFunction(exec, object, exec->propertyNames().toString);
+ this->structure()->startWatchingInternalPropertiesIfNecessaryForEntireChain(exec->vm());
+
+ JSValue value;
+ if (hint == PreferString) {
+ value = callToPrimitiveFunction(exec, this, exec->propertyNames().toString, hint);
if (value)
return value;
- value = callDefaultValueFunction(exec, object, exec->propertyNames().valueOf);
+ value = callToPrimitiveFunction(exec, this, exec->propertyNames().valueOf, hint);
if (value)
return value;
} else {
- JSValue value = callDefaultValueFunction(exec, object, exec->propertyNames().valueOf);
+ value = callToPrimitiveFunction(exec, this, exec->propertyNames().valueOf, hint);
if (value)
return value;
- value = callDefaultValueFunction(exec, object, exec->propertyNames().toString);
+ value = callToPrimitiveFunction(exec, this, exec->propertyNames().toString, hint);
if (value)
return value;
}
@@ -1484,6 +1496,27 @@
return exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("No default value")));
}
+JSValue JSObject::defaultValue(const JSObject* object, ExecState* exec, PreferredPrimitiveType hint)
+{
+ return object->ordinaryToPrimitive(exec, hint);
+}
+
+JSValue JSObject::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
+{
+ JSValue value = callToPrimitiveFunction<TypeHintMode::TakesHint>(exec, this, exec->propertyNames().toPrimitiveSymbol, preferredType);
+ if (value)
+ return value;
+
+ return this->methodTable(exec->vm())->defaultValue(this, exec, preferredType);
+}
+
+bool JSObject::getPrimitiveNumber(ExecState* exec, double& number, JSValue& result) const
+{
+ result = toPrimitive(exec, PreferNumber);
+ number = result.toNumber(exec);
+ return !result.isString();
+}
+
const HashTableValue* JSObject::findPropertyHashEntry(PropertyName propertyName) const
{
for (const ClassInfo* info = classInfo(); info; info = info->parentClass) {
@@ -2912,11 +2945,6 @@
return object->defineOwnNonIndexProperty(exec, propertyName, descriptor, throwException);
}
-JSObject* throwTypeError(ExecState* exec, const String& message)
-{
- return exec->vm().throwException(exec, createTypeError(exec, message));
-}
-
void JSObject::convertToDictionary(VM& vm)
{
DeferredStructureTransitionWatchpointFire deferredWatchpointFire;
Modified: trunk/Source/_javascript_Core/runtime/JSObject.h (197530 => 197531)
--- trunk/Source/_javascript_Core/runtime/JSObject.h 2016-03-04 00:39:41 UTC (rev 197530)
+++ trunk/Source/_javascript_Core/runtime/JSObject.h 2016-03-04 00:47:55 UTC (rev 197531)
@@ -504,6 +504,7 @@
JS_EXPORT_PRIVATE static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName);
JS_EXPORT_PRIVATE static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType);
+ JS_EXPORT_PRIVATE JSValue ordinaryToPrimitive(ExecState*, PreferredPrimitiveType) const;
JS_EXPORT_PRIVATE bool hasInstance(ExecState*, JSValue value, JSValue hasInstanceValue);
bool hasInstance(ExecState*, JSValue);
@@ -517,7 +518,7 @@
JS_EXPORT_PRIVATE static void getStructurePropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
JS_EXPORT_PRIVATE static void getGenericPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
- JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const;
+ JS_EXPORT_PRIVATE JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const;
bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const;
JS_EXPORT_PRIVATE double toNumber(ExecState*) const;
JS_EXPORT_PRIVATE JSString* toString(ExecState*) const;
@@ -1452,11 +1453,6 @@
putDirect(vm, offset, value);
}
-inline JSValue JSObject::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
-{
- return methodTable()->defaultValue(this, exec, preferredType);
-}
-
ALWAYS_INLINE JSObject* Register::object() const
{
return asObject(jsValue());
Modified: trunk/Source/_javascript_Core/runtime/SmallStrings.h (197530 => 197531)
--- trunk/Source/_javascript_Core/runtime/SmallStrings.h 2016-03-04 00:39:41 UTC (rev 197530)
+++ trunk/Source/_javascript_Core/runtime/SmallStrings.h 2016-03-04 00:47:55 UTC (rev 197531)
@@ -31,6 +31,7 @@
#include <wtf/Noncopyable.h>
#define JSC_COMMON_STRINGS_EACH_NAME(macro) \
+ macro(default) \
macro(boolean) \
macro(false) \
macro(function) \
Modified: trunk/Source/_javascript_Core/runtime/SymbolPrototype.cpp (197530 => 197531)
--- trunk/Source/_javascript_Core/runtime/SymbolPrototype.cpp 2016-03-04 00:39:41 UTC (rev 197530)
+++ trunk/Source/_javascript_Core/runtime/SymbolPrototype.cpp 2016-03-04 00:47:55 UTC (rev 197531)
@@ -56,11 +56,13 @@
{
}
-void SymbolPrototype::finishCreation(VM& vm)
+void SymbolPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject)
{
Base::finishCreation(vm);
putDirectWithoutTransition(vm, vm.propertyNames->toStringTagSymbol, jsString(&vm, "Symbol"), DontEnum | ReadOnly);
ASSERT(inherits(info()));
+
+ JSC_NATIVE_FUNCTION(vm.propertyNames->toPrimitiveSymbol, symbolProtoFuncValueOf, DontEnum | ReadOnly, 1);
}
bool SymbolPrototype::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot &slot)
Modified: trunk/Source/_javascript_Core/runtime/SymbolPrototype.h (197530 => 197531)
--- trunk/Source/_javascript_Core/runtime/SymbolPrototype.h 2016-03-04 00:39:41 UTC (rev 197530)
+++ trunk/Source/_javascript_Core/runtime/SymbolPrototype.h 2016-03-04 00:47:55 UTC (rev 197531)
@@ -38,10 +38,10 @@
typedef JSNonFinalObject Base;
static const unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot;
- static SymbolPrototype* create(VM& vm, JSGlobalObject*, Structure* structure)
+ static SymbolPrototype* create(VM& vm, JSGlobalObject* globalObject, Structure* structure)
{
SymbolPrototype* prototype = new (NotNull, allocateCell<SymbolPrototype>(vm.heap)) SymbolPrototype(vm, structure);
- prototype->finishCreation(vm);
+ prototype->finishCreation(vm, globalObject);
return prototype;
}
@@ -54,7 +54,7 @@
protected:
SymbolPrototype(VM&, Structure*);
- void finishCreation(VM&);
+ void finishCreation(VM&, JSGlobalObject*);
private:
static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&);
Modified: trunk/Source/_javascript_Core/tests/es6.yaml (197530 => 197531)
--- trunk/Source/_javascript_Core/tests/es6.yaml 2016-03-04 00:39:41 UTC (rev 197530)
+++ trunk/Source/_javascript_Core/tests/es6.yaml 2016-03-04 00:47:55 UTC (rev 197531)
@@ -971,7 +971,7 @@
- path: es6/Proxy_internal_get_calls_CreateListFromArrayLike.js
cmd: runES6 :normal
- path: es6/Proxy_internal_get_calls_Date.prototype.toJSON.js
- cmd: runES6 :fail
+ cmd: runES6 :normal
- path: es6/Proxy_internal_get_calls_Error.prototype.toString.js
cmd: runES6 :normal
- path: es6/Proxy_internal_get_calls_Function.prototype.bind.js
@@ -1009,13 +1009,13 @@
- path: es6/Proxy_internal_get_calls_String.prototype.replace.js
cmd: runES6 :fail
- path: es6/Proxy_internal_get_calls_String.prototype.search.js
- cmd: runES6 :fail
+ cmd: runES6 :normal
- path: es6/Proxy_internal_get_calls_String.prototype.split.js
cmd: runES6 :fail
- path: es6/Proxy_internal_get_calls_String.raw.js
cmd: runES6 :normal
- path: es6/Proxy_internal_get_calls_ToPrimitive.js
- cmd: runES6 :fail
+ cmd: runES6 :normal
- path: es6/Proxy_internal_get_calls_ToPropertyDescriptor.js
cmd: runES6 :fail
- path: es6/Proxy_internal_getOwnPropertyDescriptor_calls_[[Set]].js
@@ -1211,7 +1211,7 @@
- path: es6/well-known_symbols_Symbol.split.js
cmd: runES6 :fail
- path: es6/well-known_symbols_Symbol.toPrimitive.js
- cmd: runES6 :fail
+ cmd: runES6 :normal
- path: es6/well-known_symbols_Symbol.toStringTag.js
cmd: runES6 :normal
- path: es6/well-known_symbols_Symbol.toStringTag_misc._built-ins.js
Added: trunk/Source/_javascript_Core/tests/stress/date-symbol-toprimitive.js (0 => 197531)
--- trunk/Source/_javascript_Core/tests/stress/date-symbol-toprimitive.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/date-symbol-toprimitive.js 2016-03-04 00:47:55 UTC (rev 197531)
@@ -0,0 +1,6 @@
+delete Date.prototype[Symbol.toPrimitive]
+
+let date = new Date();
+
+if (typeof (date + 1) !== "number")
+ throw "symbol was not deleted";
Added: trunk/Source/_javascript_Core/tests/stress/ropes-symbol-toprimitive.js (0 => 197531)
--- trunk/Source/_javascript_Core/tests/stress/ropes-symbol-toprimitive.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/ropes-symbol-toprimitive.js 2016-03-04 00:47:55 UTC (rev 197531)
@@ -0,0 +1,28 @@
+function ropify(a,b,c) {
+ return a + b + c;
+}
+noInline(ropify);
+
+function ropify2(a,b,c) {
+ return a + b + c;
+}
+noInline(ropify2);
+
+let test = new String("test");
+
+for (let i = 0; i < 100000; i++) {
+ if (ropify("a", "b", test) !== "abtest")
+ throw "wrong on warmup";
+}
+
+String.prototype[Symbol.toPrimitive] = function() { return "changed"; }
+
+if (ropify("a", "b", test) !== "abchanged")
+ throw "watchpoint didn't fire";
+
+
+// Test we don't start doing the wrong thing if the prototype chain has been mucked with.
+for (let i = 0; i < 100000; i++) {
+ if (ropify2("a", "b", test) !== "abchanged")
+ throw "wrong on warmup";
+}
Added: trunk/Source/_javascript_Core/tests/stress/symbol-toprimitive.js (0 => 197531)
--- trunk/Source/_javascript_Core/tests/stress/symbol-toprimitive.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/symbol-toprimitive.js 2016-03-04 00:47:55 UTC (rev 197531)
@@ -0,0 +1,18 @@
+// return object
+let foo = { }
+foo[Symbol.toPrimitive] = function() { return {} };
+
+for (i = 0; i < 100000; i++) {
+ let failed = true;
+ try {
+ foo >= 1;
+ } catch (e) {
+ if (e instanceof TypeError)
+ failed = false;
+ }
+
+ if (failed)
+ throw "should have thrown on return of object";
+}
+
+// The general use of Symbol.toPrimitive is covered in the ES6 tests.