Implement ES6 Symbol
authorutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 31 Jan 2015 01:23:56 +0000 (01:23 +0000)
committerutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 31 Jan 2015 01:23:56 +0000 (01:23 +0000)
https://bugs.webkit.org/show_bug.cgi?id=140435

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

This patch implements ES6 Symbol. In this patch, we don't support
Symbol.keyFor, Symbol.for, Object.getOwnPropertySymbols. They will be
supported in the subsequent patches.

Since ES6 Symbol is introduced as new primitive value, we implement
Symbol as a derived class from JSCell. And now JSValue accepts Symbol*
as a new primitive value.

Symbol has a *unique* flagged StringImpl* as an `uid`. Which pointer
value represents the Symbol's identity. So don't compare Symbol's
JSCell pointer value for comparison.
This enables re-producing Symbol primitive value from StringImpl* uid
by executing`Symbol::create(vm, uid)`. This is needed to produce
Symbol primitive values from stored StringImpl* in `Object.getOwnPropertySymbols`.

And Symbol.[[Description]] is folded into the string value of Symbol's uid.
By doing so, we can represent ES6 Symbol without extending current PropertyTable key; StringImpl*.

* CMakeLists.txt:
* DerivedSources.make:
* JavaScriptCore.order:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
* JavaScriptCore.xcodeproj/project.pbxproj:
* builtins/BuiltinExecutables.cpp:
(JSC::BuiltinExecutables::createBuiltinExecutable):
* builtins/BuiltinNames.h:
* dfg/DFGOperations.cpp:
(JSC::DFG::operationPutByValInternal):
* inspector/JSInjectedScriptHost.cpp:
(Inspector::JSInjectedScriptHost::subtype):
* interpreter/Interpreter.cpp:
* jit/JITOperations.cpp:
(JSC::getByVal):
* llint/LLIntData.cpp:
(JSC::LLInt::Data::performAssertions):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::getByVal):
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* llint/LowLevelInterpreter.asm:
* runtime/CommonIdentifiers.h:
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
* runtime/CommonSlowPaths.h:
(JSC::CommonSlowPaths::opIn):
* runtime/ExceptionHelpers.cpp:
(JSC::createUndefinedVariableError):
* runtime/JSCJSValue.cpp:
(JSC::JSValue::synthesizePrototype):
(JSC::JSValue::dumpInContextAssumingStructure):
(JSC::JSValue::toStringSlowCase):
* runtime/JSCJSValue.h:
* runtime/JSCJSValueInlines.h:
(JSC::JSValue::isSymbol):
(JSC::JSValue::isPrimitive):
(JSC::JSValue::toPropertyKey):

It represents ToPropertyKey abstract operation in the ES6 spec.
It cleans up the old implementation's `isName` checks.
And to prevent performance regressions in
    js/regress/fold-get-by-id-to-multi-get-by-offset-rare-int.html
    js/regress/fold-get-by-id-to-multi-get-by-offset.html
we annnotate this function as ALWAYS_INLINE.

(JSC::JSValue::getPropertySlot):
(JSC::JSValue::get):
(JSC::JSValue::equalSlowCaseInline):
(JSC::JSValue::strictEqualSlowCaseInline):
* runtime/JSCell.cpp:
(JSC::JSCell::put):
(JSC::JSCell::putByIndex):
(JSC::JSCell::toPrimitive):
(JSC::JSCell::getPrimitiveNumber):
(JSC::JSCell::toNumber):
(JSC::JSCell::toObject):
* runtime/JSCell.h:
* runtime/JSCellInlines.h:
(JSC::JSCell::isSymbol):
(JSC::JSCell::toBoolean):
(JSC::JSCell::pureToBoolean):
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::visitChildren):
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::symbolPrototype):
(JSC::JSGlobalObject::symbolObjectStructure):
* runtime/JSONObject.cpp:
(JSC::Stringifier::Stringifier):
* runtime/JSSymbolTableObject.cpp:
(JSC::JSSymbolTableObject::getOwnNonIndexPropertyNames):
* runtime/JSType.h:
* runtime/JSTypeInfo.h:
(JSC::TypeInfo::isName): Deleted.
* runtime/MapData.cpp:
(JSC::MapData::find):
(JSC::MapData::add):
(JSC::MapData::remove):
(JSC::MapData::replaceAndPackBackingStore):
* runtime/MapData.h:
(JSC::MapData::clear):
* runtime/NameInstance.h: Removed.
* runtime/NamePrototype.cpp: Removed.
* runtime/ObjectConstructor.cpp:
(JSC::objectConstructorGetOwnPropertyDescriptor):
(JSC::objectConstructorDefineProperty):
* runtime/ObjectPrototype.cpp:
(JSC::objectProtoFuncHasOwnProperty):
(JSC::objectProtoFuncDefineGetter):
(JSC::objectProtoFuncDefineSetter):
(JSC::objectProtoFuncLookupGetter):
(JSC::objectProtoFuncLookupSetter):
(JSC::objectProtoFuncPropertyIsEnumerable):
* runtime/Operations.cpp:
(JSC::jsTypeStringForValue):
(JSC::jsIsObjectType):
* runtime/PrivateName.h:
(JSC::PrivateName::PrivateName):
(JSC::PrivateName::operator==):
(JSC::PrivateName::operator!=):
* runtime/PropertyMapHashTable.h:
(JSC::PropertyTable::find):
(JSC::PropertyTable::get):
* runtime/PropertyName.h:
(JSC::PropertyName::PropertyName):
(JSC::PropertyName::publicName):
* runtime/SmallStrings.h:
* runtime/StringConstructor.cpp:
(JSC::callStringConstructor):

In ES6, String constructor accepts Symbol to execute `String(symbol)`.

* runtime/Structure.cpp:
(JSC::Structure::getPropertyNamesFromStructure):
* runtime/StructureInlines.h:
(JSC::Structure::prototypeForLookup):
* runtime/Symbol.cpp: Added.
(JSC::Symbol::Symbol):
(JSC::SymbolObject::create):
(JSC::Symbol::toPrimitive):
(JSC::Symbol::toBoolean):
(JSC::Symbol::getPrimitiveNumber):
(JSC::Symbol::toObject):
(JSC::Symbol::toNumber):
(JSC::Symbol::destroy):
(JSC::Symbol::descriptiveString):
* runtime/Symbol.h: Added.
(JSC::Symbol::createStructure):
(JSC::Symbol::create):
(JSC::Symbol::privateName):
(JSC::Symbol::finishCreation):
(JSC::asSymbol):
* runtime/SymbolConstructor.cpp: Renamed from Source/JavaScriptCore/runtime/NameConstructor.cpp.
(JSC::SymbolConstructor::SymbolConstructor):
(JSC::SymbolConstructor::finishCreation):
(JSC::callSymbol):
(JSC::SymbolConstructor::getConstructData):
(JSC::SymbolConstructor::getCallData):
* runtime/SymbolConstructor.h: Renamed from Source/JavaScriptCore/runtime/NameConstructor.h.
(JSC::SymbolConstructor::create):
(JSC::SymbolConstructor::createStructure):
* runtime/SymbolObject.cpp: Renamed from Source/JavaScriptCore/runtime/NameInstance.cpp.
(JSC::SymbolObject::SymbolObject):
(JSC::SymbolObject::finishCreation):
(JSC::SymbolObject::defaultValue):

Now JSC doesn't support @@toPrimitive. So instead of it, we implement
Symbol.prototype[@@toPrimitive] as ES5 Symbol.[[DefaultValue]].

* runtime/SymbolObject.h: Added.
(JSC::SymbolObject::create):
(JSC::SymbolObject::internalValue):
(JSC::SymbolObject::createStructure):
* runtime/SymbolPrototype.cpp: Added.
(JSC::SymbolPrototype::SymbolPrototype):
(JSC::SymbolPrototype::finishCreation):
(JSC::SymbolPrototype::getOwnPropertySlot):
(JSC::symbolProtoFuncToString):
(JSC::symbolProtoFuncValueOf):
* runtime/SymbolPrototype.h: Renamed from Source/JavaScriptCore/runtime/NamePrototype.h.
(JSC::SymbolPrototype::create):
(JSC::SymbolPrototype::createStructure):

SymbolPrototype object is ordinary JS object. Not wrapper object of Symbol.
It is tested in js/symbol-prototype-is-ordinary-object.html.

* runtime/VM.cpp:
(JSC::VM::VM):
* runtime/VM.h:

Source/WTF:

Introduce new unique string mechanizm into StringImpl.
It is used for implementing Symbol which holds a [[Description]] value.

* wtf/text/AtomicString.h:
(WTF::AtomicString::add):
(WTF::AtomicString::addWithStringTableProvider):

Previously, we checked `isAtomic()` or `!length()`. This guard can filter out EmptyUnique.
But now, we introduced new unique StringImpl. Since it has an actual string value, we need to check `isUnique()`.

* wtf/text/StringImpl.cpp:
(WTF::StringImpl::~StringImpl):
(WTF::StringImpl::createUnique):

In createUnique, we leverage Substring mechanizm to produce a new unique
string from an existing string.

* wtf/text/StringImpl.h:
(WTF::StringImpl::StringImpl):
(WTF::StringImpl::createUniqueEmpty):
(WTF::StringImpl::flagIsUnique):
(WTF::StringImpl::isUnique):
(WTF::StringImpl::setIsAtomic):
(WTF::StringImpl::createEmptyUnique): Deleted.
(WTF::StringImpl::isEmptyUnique): Deleted.

Instead of EmptyUnique, we introduced new flag to StringImpl, `isUnique`.
While EmptyUnique cannot hold any string values except for empty string,
the unique StringImpl can hold any String values.
We fold the Symbol's descriptiveString value here.

* wtf/text/StringStatics.cpp:
(WTF::StringImpl::hashAndFlagsForUnique):
(WTF::StringImpl::hashAndFlagsForEmptyUnique): Deleted.

LayoutTests:

* js/script-tests/symbol-abstract-equality-comparison.js: Added.
(Pair):
(relationalOperators.forEach):
* js/script-tests/symbol-abstract-relational-comparison.js: Added.
(relationalOperators.forEach):
* js/script-tests/symbol-in-map.js: Added.
(set shouldBe):
* js/script-tests/symbol-object.js: Added.
* js/script-tests/symbol-prototype-is-ordinary-object.js: Added.
* js/script-tests/symbol-strict-equality-comparison.js: Added.
(Pair):
(relationalOperators.forEach):
* js/script-tests/symbol-tostring.js: Added.
* js/script-tests/symbols.js: Renamed from LayoutTests/js/script-tests/names.js.
(forIn):
* js/symbol-abstract-equality-comparison-expected.txt: Added.
* js/symbol-abstract-equality-comparison.html: Copied from LayoutTests/js/names.html.
* js/symbol-abstract-relational-comparison-expected.txt: Added.
* js/symbol-abstract-relational-comparison.html: Copied from LayoutTests/js/names.html.
* js/symbol-in-map-expected.txt: Added.
* js/symbol-in-map.html: Copied from LayoutTests/js/names.html.
* js/symbol-object-expected.txt: Added.
* js/symbol-object.html: Copied from LayoutTests/js/names.html.
* js/symbol-prototype-is-ordinary-object-expected.txt: Added.
* js/symbol-prototype-is-ordinary-object.html: Copied from LayoutTests/js/names.html.
* js/symbol-strict-equality-comparison-expected.txt: Added.
* js/symbol-strict-equality-comparison.html: Copied from LayoutTests/js/names.html.
* js/symbol-tostring-expected.txt: Added.
* js/symbol-tostring.html: Copied from LayoutTests/js/names.html.
* js/symbols-expected.txt: Renamed from LayoutTests/js/names-expected.txt.
* js/symbols.html: Renamed from LayoutTests/js/names.html.

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

86 files changed:
LayoutTests/ChangeLog
LayoutTests/js/script-tests/symbol-abstract-equality-comparison.js [new file with mode: 0644]
LayoutTests/js/script-tests/symbol-abstract-relational-comparison.js [new file with mode: 0644]
LayoutTests/js/script-tests/symbol-in-map.js [new file with mode: 0644]
LayoutTests/js/script-tests/symbol-object.js [new file with mode: 0644]
LayoutTests/js/script-tests/symbol-prototype-is-ordinary-object.js [new file with mode: 0644]
LayoutTests/js/script-tests/symbol-strict-equality-comparison.js [new file with mode: 0644]
LayoutTests/js/script-tests/symbol-tostring.js [new file with mode: 0644]
LayoutTests/js/script-tests/symbols.js [moved from LayoutTests/js/script-tests/names.js with 88% similarity]
LayoutTests/js/symbol-abstract-equality-comparison-expected.txt [new file with mode: 0644]
LayoutTests/js/symbol-abstract-equality-comparison.html [new file with mode: 0644]
LayoutTests/js/symbol-abstract-relational-comparison-expected.txt [new file with mode: 0644]
LayoutTests/js/symbol-abstract-relational-comparison.html [new file with mode: 0644]
LayoutTests/js/symbol-in-map-expected.txt [new file with mode: 0644]
LayoutTests/js/symbol-in-map.html [new file with mode: 0644]
LayoutTests/js/symbol-object-expected.txt [new file with mode: 0644]
LayoutTests/js/symbol-object.html [new file with mode: 0644]
LayoutTests/js/symbol-prototype-is-ordinary-object-expected.txt [new file with mode: 0644]
LayoutTests/js/symbol-prototype-is-ordinary-object.html [new file with mode: 0644]
LayoutTests/js/symbol-strict-equality-comparison-expected.txt [new file with mode: 0644]
LayoutTests/js/symbol-strict-equality-comparison.html [new file with mode: 0644]
LayoutTests/js/symbol-tostring-expected.txt [new file with mode: 0644]
LayoutTests/js/symbol-tostring.html [new file with mode: 0644]
LayoutTests/js/symbols-expected.txt [moved from LayoutTests/js/names-expected.txt with 88% similarity]
LayoutTests/js/symbols.html [moved from LayoutTests/js/names.html with 80% similarity]
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/DerivedSources.make
Source/JavaScriptCore/JavaScriptCore.order
Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/builtins/BuiltinExecutables.cpp
Source/JavaScriptCore/builtins/BuiltinNames.h
Source/JavaScriptCore/dfg/DFGOperations.cpp
Source/JavaScriptCore/inspector/JSInjectedScriptHost.cpp
Source/JavaScriptCore/interpreter/Interpreter.cpp
Source/JavaScriptCore/jit/JITOperations.cpp
Source/JavaScriptCore/llint/LLIntData.cpp
Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
Source/JavaScriptCore/llint/LowLevelInterpreter.asm
Source/JavaScriptCore/runtime/CommonIdentifiers.h
Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
Source/JavaScriptCore/runtime/CommonSlowPaths.h
Source/JavaScriptCore/runtime/ExceptionHelpers.cpp
Source/JavaScriptCore/runtime/JSCJSValue.cpp
Source/JavaScriptCore/runtime/JSCJSValue.h
Source/JavaScriptCore/runtime/JSCJSValueInlines.h
Source/JavaScriptCore/runtime/JSCell.cpp
Source/JavaScriptCore/runtime/JSCell.h
Source/JavaScriptCore/runtime/JSCellInlines.h
Source/JavaScriptCore/runtime/JSGlobalObject.cpp
Source/JavaScriptCore/runtime/JSGlobalObject.h
Source/JavaScriptCore/runtime/JSONObject.cpp
Source/JavaScriptCore/runtime/JSSymbolTableObject.cpp
Source/JavaScriptCore/runtime/JSType.h
Source/JavaScriptCore/runtime/JSTypeInfo.h
Source/JavaScriptCore/runtime/MapData.cpp
Source/JavaScriptCore/runtime/MapData.h
Source/JavaScriptCore/runtime/NameInstance.h [deleted file]
Source/JavaScriptCore/runtime/NamePrototype.cpp [deleted file]
Source/JavaScriptCore/runtime/ObjectConstructor.cpp
Source/JavaScriptCore/runtime/ObjectPrototype.cpp
Source/JavaScriptCore/runtime/Operations.cpp
Source/JavaScriptCore/runtime/PrivateName.h
Source/JavaScriptCore/runtime/PropertyMapHashTable.h
Source/JavaScriptCore/runtime/PropertyName.h
Source/JavaScriptCore/runtime/SmallStrings.h
Source/JavaScriptCore/runtime/StringConstructor.cpp
Source/JavaScriptCore/runtime/Structure.cpp
Source/JavaScriptCore/runtime/StructureInlines.h
Source/JavaScriptCore/runtime/Symbol.cpp [new file with mode: 0644]
Source/JavaScriptCore/runtime/Symbol.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/SymbolConstructor.cpp [moved from Source/JavaScriptCore/runtime/NameConstructor.cpp with 58% similarity]
Source/JavaScriptCore/runtime/SymbolConstructor.h [moved from Source/JavaScriptCore/runtime/NameConstructor.h with 74% similarity]
Source/JavaScriptCore/runtime/SymbolObject.cpp [moved from Source/JavaScriptCore/runtime/NameInstance.cpp with 66% similarity]
Source/JavaScriptCore/runtime/SymbolObject.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/SymbolPrototype.cpp [new file with mode: 0644]
Source/JavaScriptCore/runtime/SymbolPrototype.h [moved from Source/JavaScriptCore/runtime/NamePrototype.h with 72% similarity]
Source/JavaScriptCore/runtime/VM.cpp
Source/JavaScriptCore/runtime/VM.h
Source/WTF/ChangeLog
Source/WTF/wtf/text/AtomicString.h
Source/WTF/wtf/text/StringImpl.cpp
Source/WTF/wtf/text/StringImpl.h
Source/WTF/wtf/text/StringStatics.cpp

index 1b42b06..2916392 100644 (file)
@@ -1,3 +1,42 @@
+2015-01-30  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        Implement ES6 Symbol
+        https://bugs.webkit.org/show_bug.cgi?id=140435
+
+        Reviewed by Geoffrey Garen.
+
+        * js/script-tests/symbol-abstract-equality-comparison.js: Added.
+        (Pair):
+        (relationalOperators.forEach):
+        * js/script-tests/symbol-abstract-relational-comparison.js: Added.
+        (relationalOperators.forEach):
+        * js/script-tests/symbol-in-map.js: Added.
+        (set shouldBe):
+        * js/script-tests/symbol-object.js: Added.
+        * js/script-tests/symbol-prototype-is-ordinary-object.js: Added.
+        * js/script-tests/symbol-strict-equality-comparison.js: Added.
+        (Pair):
+        (relationalOperators.forEach):
+        * js/script-tests/symbol-tostring.js: Added.
+        * js/script-tests/symbols.js: Renamed from LayoutTests/js/script-tests/names.js.
+        (forIn):
+        * js/symbol-abstract-equality-comparison-expected.txt: Added.
+        * js/symbol-abstract-equality-comparison.html: Copied from LayoutTests/js/names.html.
+        * js/symbol-abstract-relational-comparison-expected.txt: Added.
+        * js/symbol-abstract-relational-comparison.html: Copied from LayoutTests/js/names.html.
+        * js/symbol-in-map-expected.txt: Added.
+        * js/symbol-in-map.html: Copied from LayoutTests/js/names.html.
+        * js/symbol-object-expected.txt: Added.
+        * js/symbol-object.html: Copied from LayoutTests/js/names.html.
+        * js/symbol-prototype-is-ordinary-object-expected.txt: Added.
+        * js/symbol-prototype-is-ordinary-object.html: Copied from LayoutTests/js/names.html.
+        * js/symbol-strict-equality-comparison-expected.txt: Added.
+        * js/symbol-strict-equality-comparison.html: Copied from LayoutTests/js/names.html.
+        * js/symbol-tostring-expected.txt: Added.
+        * js/symbol-tostring.html: Copied from LayoutTests/js/names.html.
+        * js/symbols-expected.txt: Renamed from LayoutTests/js/names-expected.txt.
+        * js/symbols.html: Renamed from LayoutTests/js/names.html.
+
 2015-01-30  Dariusz Frankiewicz  <d.frankiewic@samsung.com>
 
         [EFL] Gardening: update some accessibility tests as failed
diff --git a/LayoutTests/js/script-tests/symbol-abstract-equality-comparison.js b/LayoutTests/js/script-tests/symbol-abstract-equality-comparison.js
new file mode 100644 (file)
index 0000000..1118f0f
--- /dev/null
@@ -0,0 +1,49 @@
+description(
+"This tests Abstract Equality Comparison results with Symbols."
+);
+
+var symbol = Symbol("Cocoa");
+var symbolObject = Object(symbol);
+// Test Abstract Relational Comparison.
+var relationalOperators = [
+    "==", "!="
+];
+var object = {};
+var array = [];
+var date = new Date();
+
+function Pair(key, result) {
+    return [ key, result ];
+}
+
+relationalOperators.forEach(function (op) {
+    var targets = [
+        Pair("42", false),
+        Pair("NaN", false),
+        Pair("Infinity", false),
+        Pair("true", false),
+        Pair("false", false),
+        Pair("null", false),
+        Pair("undefined", false),
+        Pair("'Cappuccino'", false),
+        Pair("symbol", true),
+        Pair("Symbol.iterator", false),
+        Pair("object", false),
+        Pair("array", false),
+        Pair("date", false),
+        Pair("symbolObject", true),
+        Pair("Symbol('Cocoa')", false),
+    ];
+
+    targets.forEach(function (pair) {
+        var target = pair[0];
+        var result = pair[1];
+        if (op === "!=") {
+            result = !result;
+        }
+        shouldBe(target + " " + op + " symbol", String(result));
+        shouldBe("symbol " + op + " " + target, String(result));
+    });
+});
+
+successfullyParsed = true;
diff --git a/LayoutTests/js/script-tests/symbol-abstract-relational-comparison.js b/LayoutTests/js/script-tests/symbol-abstract-relational-comparison.js
new file mode 100644 (file)
index 0000000..a2e775b
--- /dev/null
@@ -0,0 +1,37 @@
+description(
+"This tests Abstract Relatioal Comparison results with Symbols."
+);
+
+var symbol = Symbol("Cocoa");
+// Test Abstract Relational Comparison.
+var relationalOperators = [
+    "<", "<=", ">", ">="
+];
+var object = {};
+var array = [];
+var date = new Date();
+
+relationalOperators.forEach(function (op) {
+    var targets = [
+        "42",
+        "NaN",
+        "Infinity",
+        "true",
+        "false",
+        "null",
+        "undefined",
+        "'Cappuccino'",
+        "symbol",
+        "Symbol.iterator",
+        "object",
+        "array",
+        "date",
+    ];
+
+    targets.forEach(function (target) {
+        shouldThrow(target + " " + op + " symbol", "'TypeError: Type error'");
+        shouldThrow("symbol " + op + " " + target, "'TypeError: Type error'");
+    });
+});
+
+successfullyParsed = true;
diff --git a/LayoutTests/js/script-tests/symbol-in-map.js b/LayoutTests/js/script-tests/symbol-in-map.js
new file mode 100644 (file)
index 0000000..f9df40f
--- /dev/null
@@ -0,0 +1,43 @@
+description(
+"This tests Symbols work in ES6 Map."
+);
+
+var symbol = Symbol("Cocoa");
+var symbol2 = Symbol("Matcha");
+var map = new Map();
+
+map.set(symbol, "Cappuccino");
+shouldBe("map.size", "1");
+shouldBeEqualToString("map.get(symbol)", "Cappuccino");
+shouldBeFalse("map.has(Symbol('Cocoa'))");
+shouldBe("map.get(Symbol('Cocoa'))", "undefined");
+shouldBeFalse("map.has('Cocoa')");
+shouldBe("map.get('Cocoa')", "undefined");
+shouldBeFalse("map.has(symbol2)");
+shouldBe("map.get(symbol2)", "undefined");
+
+map.set(symbol2, "Kilimanjaro");
+shouldBe("map.size", "2");
+shouldBeEqualToString("map.get(symbol)", "Cappuccino");
+shouldBeEqualToString("map.get(symbol2)", "Kilimanjaro");
+shouldBeFalse("map.has(Symbol('Matcha'))");
+shouldBe("map.get(Symbol('Matcha'))", "undefined");
+shouldBeFalse("map.has('Matcha')");
+shouldBe("map.get('Matcha')", "undefined");
+
+map.delete(symbol2);
+shouldBeFalse("map.has(symbol2)");
+shouldBe("map.get(symbol2)", "undefined");
+shouldBeTrue("map.has(symbol)");
+shouldBeEqualToString("map.get(symbol)", "Cappuccino");
+
+shouldBe("map.size", "1");
+var key, value;
+map.forEach(function (v, k) {
+    key = k;
+    value = v;
+});
+shouldBe("key", "symbol");
+shouldBeEqualToString("value", "Cappuccino");
+
+successfullyParsed = true;
diff --git a/LayoutTests/js/script-tests/symbol-object.js b/LayoutTests/js/script-tests/symbol-object.js
new file mode 100644 (file)
index 0000000..077c64e
--- /dev/null
@@ -0,0 +1,34 @@
+description(
+"This tests Symbol object behaviors."
+);
+
+// Symbol constructor cannot be called with `new` style.
+// To create Symbol object, call `Object(symbol)`.
+shouldThrow("new Symbol", "\"TypeError: function is not a constructor (evaluating 'new Symbol')\"");
+shouldThrow("new Symbol('Cappuccino')", "\"TypeError: function is not a constructor (evaluating 'new Symbol('Cappuccino')')\"");
+
+var symbolObject = Object(Symbol.iterator);
+shouldBeTrue("symbolObject instanceof Symbol");
+// Since Symbol object's @@toPrimitive returns Symbol value,
+// ToString(symbol) will be called.
+shouldThrow("String(symbolObject)", "'TypeError: Type error'");
+shouldBeEqualToString("symbolObject.toString()", "Symbol(Symbol.iterator)");
+
+var object = {};
+object[symbolObject] = 42;
+// ToPropertyKey(symbolObject) will call toPrimitive(symbolObject), and toPrimitive(symbolObject) will return symbol primitive value. As a result, object[symbolObject] equals to object[symbol in the symbolObject].
+shouldBe("object[symbolObject]", "42");
+shouldBe("object['Symbol(Symbol.iterator)']", "undefined");
+shouldBe("object[Symbol.iterator]", "42");
+
+var symbol = Symbol("Matcha");
+object[symbol] = 'Cocoa';
+shouldBeEqualToString("object[symbol]", "Cocoa");
+shouldBeEqualToString("object[symbol.valueOf()]", "Cocoa");
+shouldBeEqualToString("object[Object(symbol)]", "Cocoa");
+shouldBe("object['Matcha']", "undefined");
+
+// ToObject will be called.
+shouldBe("Symbol.iterator.hello", "undefined");
+
+successfullyParsed = true;
diff --git a/LayoutTests/js/script-tests/symbol-prototype-is-ordinary-object.js b/LayoutTests/js/script-tests/symbol-prototype-is-ordinary-object.js
new file mode 100644 (file)
index 0000000..9a8186e
--- /dev/null
@@ -0,0 +1,8 @@
+description(
+"This tests that Symbol.prototype object is ordinary object (not Symbol wrapper object)."
+);
+
+shouldThrow("Symbol.prototype.toString.call(Symbol.prototype)", "'TypeError: Type error'");
+shouldBeEqualToString("Symbol.prototype.toString.call(Symbol.iterator)", "Symbol(Symbol.iterator)");
+
+successfullyParsed = true;
diff --git a/LayoutTests/js/script-tests/symbol-strict-equality-comparison.js b/LayoutTests/js/script-tests/symbol-strict-equality-comparison.js
new file mode 100644 (file)
index 0000000..b26ff60
--- /dev/null
@@ -0,0 +1,49 @@
+description(
+"This tests Strict Equality Comparison results with Symbols."
+);
+
+var symbol = Symbol("Cocoa");
+var symbolObject = Object(symbol);
+// Test Abstract Relational Comparison.
+var relationalOperators = [
+    "===", "!=="
+];
+var object = {};
+var array = [];
+var date = new Date();
+
+function Pair(key, result) {
+    return [ key, result ];
+}
+
+relationalOperators.forEach(function (op) {
+    var targets = [
+        Pair("42", false),
+        Pair("NaN", false),
+        Pair("Infinity", false),
+        Pair("true", false),
+        Pair("false", false),
+        Pair("null", false),
+        Pair("undefined", false),
+        Pair("'Cappuccino'", false),
+        Pair("symbol", true),
+        Pair("Symbol.iterator", false),
+        Pair("object", false),
+        Pair("array", false),
+        Pair("date", false),
+        Pair("symbolObject", false),
+        Pair("Symbol('Cocoa')", false),
+    ];
+
+    targets.forEach(function (pair) {
+        var target = pair[0];
+        var result = pair[1];
+        if (op === "!==") {
+            result = !result;
+        }
+        shouldBe(target + " " + op + " symbol", String(result));
+        shouldBe("symbol " + op + " " + target, String(result));
+    });
+});
+
+successfullyParsed = true;
diff --git a/LayoutTests/js/script-tests/symbol-tostring.js b/LayoutTests/js/script-tests/symbol-tostring.js
new file mode 100644 (file)
index 0000000..71836da
--- /dev/null
@@ -0,0 +1,14 @@
+description(
+"This tests that ToString(Symbol) behaviors."
+);
+
+shouldBeEqualToString("String(Symbol.iterator)", "Symbol(Symbol.iterator)");
+shouldThrow("String(Symbol.prototype)", "'TypeError: Type error'");
+shouldBeEqualToString("Symbol.prototype.toString.call(Symbol.iterator)", "Symbol(Symbol.iterator)");
+shouldBeEqualToString("Symbol.prototype.toString.call(Symbol('hello'))", "Symbol(hello)");
+shouldBeEqualToString("Symbol.prototype.toString.call(Symbol())", "Symbol()");
+shouldBeEqualToString("Object.prototype.toString.call(Symbol())", "[object Symbol]");
+shouldBeEqualToString("Object.prototype.toString.call(Symbol.prototype)", "[object Symbol]");
+shouldBeEqualToString("Object.prototype.toString.call(Symbol)", "[object Function]");
+
+successfullyParsed = true;
similarity index 88%
rename from LayoutTests/js/script-tests/names.js
rename to LayoutTests/js/script-tests/symbols.js
index 14dc141..e47a0e2 100644 (file)
@@ -1,5 +1,5 @@
 description(
-"This tests an early experimental implementation of ES6-esque private names."
+"This tests an early experimental implementation of ES6-esque Symbols."
 );
 
 function forIn(o)
@@ -10,7 +10,7 @@ function forIn(o)
     return a;
 }
 
-var prop = Name("prop");
+var prop = Symbol("prop");
 var o = {};
 
 shouldBeFalse("prop in o");
diff --git a/LayoutTests/js/symbol-abstract-equality-comparison-expected.txt b/LayoutTests/js/symbol-abstract-equality-comparison-expected.txt
new file mode 100644 (file)
index 0000000..062b07e
--- /dev/null
@@ -0,0 +1,69 @@
+This tests Abstract Equality Comparison results with Symbols.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS 42 == symbol is false
+PASS symbol == 42 is false
+PASS NaN == symbol is false
+PASS symbol == NaN is false
+PASS Infinity == symbol is false
+PASS symbol == Infinity is false
+PASS true == symbol is false
+PASS symbol == true is false
+PASS false == symbol is false
+PASS symbol == false is false
+PASS null == symbol is false
+PASS symbol == null is false
+PASS undefined == symbol is false
+PASS symbol == undefined is false
+PASS 'Cappuccino' == symbol is false
+PASS symbol == 'Cappuccino' is false
+PASS symbol == symbol is true
+PASS symbol == symbol is true
+PASS Symbol.iterator == symbol is false
+PASS symbol == Symbol.iterator is false
+PASS object == symbol is false
+PASS symbol == object is false
+PASS array == symbol is false
+PASS symbol == array is false
+PASS date == symbol is false
+PASS symbol == date is false
+PASS symbolObject == symbol is true
+PASS symbol == symbolObject is true
+PASS Symbol('Cocoa') == symbol is false
+PASS symbol == Symbol('Cocoa') is false
+PASS 42 != symbol is true
+PASS symbol != 42 is true
+PASS NaN != symbol is true
+PASS symbol != NaN is true
+PASS Infinity != symbol is true
+PASS symbol != Infinity is true
+PASS true != symbol is true
+PASS symbol != true is true
+PASS false != symbol is true
+PASS symbol != false is true
+PASS null != symbol is true
+PASS symbol != null is true
+PASS undefined != symbol is true
+PASS symbol != undefined is true
+PASS 'Cappuccino' != symbol is true
+PASS symbol != 'Cappuccino' is true
+PASS symbol != symbol is false
+PASS symbol != symbol is false
+PASS Symbol.iterator != symbol is true
+PASS symbol != Symbol.iterator is true
+PASS object != symbol is true
+PASS symbol != object is true
+PASS array != symbol is true
+PASS symbol != array is true
+PASS date != symbol is true
+PASS symbol != date is true
+PASS symbolObject != symbol is false
+PASS symbol != symbolObject is false
+PASS Symbol('Cocoa') != symbol is true
+PASS symbol != Symbol('Cocoa') is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/symbol-abstract-equality-comparison.html b/LayoutTests/js/symbol-abstract-equality-comparison.html
new file mode 100644 (file)
index 0000000..e40a306
--- /dev/null
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="script-tests/symbol-abstract-equality-comparison.js"></script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/symbol-abstract-relational-comparison-expected.txt b/LayoutTests/js/symbol-abstract-relational-comparison-expected.txt
new file mode 100644 (file)
index 0000000..79071d3
--- /dev/null
@@ -0,0 +1,113 @@
+This tests Abstract Relatioal Comparison results with Symbols.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS 42 < symbol threw exception TypeError: Type error.
+PASS symbol < 42 threw exception TypeError: Type error.
+PASS NaN < symbol threw exception TypeError: Type error.
+PASS symbol < NaN threw exception TypeError: Type error.
+PASS Infinity < symbol threw exception TypeError: Type error.
+PASS symbol < Infinity threw exception TypeError: Type error.
+PASS true < symbol threw exception TypeError: Type error.
+PASS symbol < true threw exception TypeError: Type error.
+PASS false < symbol threw exception TypeError: Type error.
+PASS symbol < false threw exception TypeError: Type error.
+PASS null < symbol threw exception TypeError: Type error.
+PASS symbol < null threw exception TypeError: Type error.
+PASS undefined < symbol threw exception TypeError: Type error.
+PASS symbol < undefined threw exception TypeError: Type error.
+PASS 'Cappuccino' < symbol threw exception TypeError: Type error.
+PASS symbol < 'Cappuccino' threw exception TypeError: Type error.
+PASS symbol < symbol threw exception TypeError: Type error.
+PASS symbol < symbol threw exception TypeError: Type error.
+PASS Symbol.iterator < symbol threw exception TypeError: Type error.
+PASS symbol < Symbol.iterator threw exception TypeError: Type error.
+PASS object < symbol threw exception TypeError: Type error.
+PASS symbol < object threw exception TypeError: Type error.
+PASS array < symbol threw exception TypeError: Type error.
+PASS symbol < array threw exception TypeError: Type error.
+PASS date < symbol threw exception TypeError: Type error.
+PASS symbol < date threw exception TypeError: Type error.
+PASS 42 <= symbol threw exception TypeError: Type error.
+PASS symbol <= 42 threw exception TypeError: Type error.
+PASS NaN <= symbol threw exception TypeError: Type error.
+PASS symbol <= NaN threw exception TypeError: Type error.
+PASS Infinity <= symbol threw exception TypeError: Type error.
+PASS symbol <= Infinity threw exception TypeError: Type error.
+PASS true <= symbol threw exception TypeError: Type error.
+PASS symbol <= true threw exception TypeError: Type error.
+PASS false <= symbol threw exception TypeError: Type error.
+PASS symbol <= false threw exception TypeError: Type error.
+PASS null <= symbol threw exception TypeError: Type error.
+PASS symbol <= null threw exception TypeError: Type error.
+PASS undefined <= symbol threw exception TypeError: Type error.
+PASS symbol <= undefined threw exception TypeError: Type error.
+PASS 'Cappuccino' <= symbol threw exception TypeError: Type error.
+PASS symbol <= 'Cappuccino' threw exception TypeError: Type error.
+PASS symbol <= symbol threw exception TypeError: Type error.
+PASS symbol <= symbol threw exception TypeError: Type error.
+PASS Symbol.iterator <= symbol threw exception TypeError: Type error.
+PASS symbol <= Symbol.iterator threw exception TypeError: Type error.
+PASS object <= symbol threw exception TypeError: Type error.
+PASS symbol <= object threw exception TypeError: Type error.
+PASS array <= symbol threw exception TypeError: Type error.
+PASS symbol <= array threw exception TypeError: Type error.
+PASS date <= symbol threw exception TypeError: Type error.
+PASS symbol <= date threw exception TypeError: Type error.
+PASS 42 > symbol threw exception TypeError: Type error.
+PASS symbol > 42 threw exception TypeError: Type error.
+PASS NaN > symbol threw exception TypeError: Type error.
+PASS symbol > NaN threw exception TypeError: Type error.
+PASS Infinity > symbol threw exception TypeError: Type error.
+PASS symbol > Infinity threw exception TypeError: Type error.
+PASS true > symbol threw exception TypeError: Type error.
+PASS symbol > true threw exception TypeError: Type error.
+PASS false > symbol threw exception TypeError: Type error.
+PASS symbol > false threw exception TypeError: Type error.
+PASS null > symbol threw exception TypeError: Type error.
+PASS symbol > null threw exception TypeError: Type error.
+PASS undefined > symbol threw exception TypeError: Type error.
+PASS symbol > undefined threw exception TypeError: Type error.
+PASS 'Cappuccino' > symbol threw exception TypeError: Type error.
+PASS symbol > 'Cappuccino' threw exception TypeError: Type error.
+PASS symbol > symbol threw exception TypeError: Type error.
+PASS symbol > symbol threw exception TypeError: Type error.
+PASS Symbol.iterator > symbol threw exception TypeError: Type error.
+PASS symbol > Symbol.iterator threw exception TypeError: Type error.
+PASS object > symbol threw exception TypeError: Type error.
+PASS symbol > object threw exception TypeError: Type error.
+PASS array > symbol threw exception TypeError: Type error.
+PASS symbol > array threw exception TypeError: Type error.
+PASS date > symbol threw exception TypeError: Type error.
+PASS symbol > date threw exception TypeError: Type error.
+PASS 42 >= symbol threw exception TypeError: Type error.
+PASS symbol >= 42 threw exception TypeError: Type error.
+PASS NaN >= symbol threw exception TypeError: Type error.
+PASS symbol >= NaN threw exception TypeError: Type error.
+PASS Infinity >= symbol threw exception TypeError: Type error.
+PASS symbol >= Infinity threw exception TypeError: Type error.
+PASS true >= symbol threw exception TypeError: Type error.
+PASS symbol >= true threw exception TypeError: Type error.
+PASS false >= symbol threw exception TypeError: Type error.
+PASS symbol >= false threw exception TypeError: Type error.
+PASS null >= symbol threw exception TypeError: Type error.
+PASS symbol >= null threw exception TypeError: Type error.
+PASS undefined >= symbol threw exception TypeError: Type error.
+PASS symbol >= undefined threw exception TypeError: Type error.
+PASS 'Cappuccino' >= symbol threw exception TypeError: Type error.
+PASS symbol >= 'Cappuccino' threw exception TypeError: Type error.
+PASS symbol >= symbol threw exception TypeError: Type error.
+PASS symbol >= symbol threw exception TypeError: Type error.
+PASS Symbol.iterator >= symbol threw exception TypeError: Type error.
+PASS symbol >= Symbol.iterator threw exception TypeError: Type error.
+PASS object >= symbol threw exception TypeError: Type error.
+PASS symbol >= object threw exception TypeError: Type error.
+PASS array >= symbol threw exception TypeError: Type error.
+PASS symbol >= array threw exception TypeError: Type error.
+PASS date >= symbol threw exception TypeError: Type error.
+PASS symbol >= date threw exception TypeError: Type error.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/symbol-abstract-relational-comparison.html b/LayoutTests/js/symbol-abstract-relational-comparison.html
new file mode 100644 (file)
index 0000000..01b8bd3
--- /dev/null
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="script-tests/symbol-abstract-relational-comparison.js"></script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/symbol-in-map-expected.txt b/LayoutTests/js/symbol-in-map-expected.txt
new file mode 100644 (file)
index 0000000..ed65e3b
--- /dev/null
@@ -0,0 +1,31 @@
+This tests Symbols work in ES6 Map.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS map.size is 1
+PASS map.get(symbol) is "Cappuccino"
+PASS map.has(Symbol('Cocoa')) is false
+PASS map.get(Symbol('Cocoa')) is undefined
+PASS map.has('Cocoa') is false
+PASS map.get('Cocoa') is undefined
+PASS map.has(symbol2) is false
+PASS map.get(symbol2) is undefined
+PASS map.size is 2
+PASS map.get(symbol) is "Cappuccino"
+PASS map.get(symbol2) is "Kilimanjaro"
+PASS map.has(Symbol('Matcha')) is false
+PASS map.get(Symbol('Matcha')) is undefined
+PASS map.has('Matcha') is false
+PASS map.get('Matcha') is undefined
+PASS map.has(symbol2) is false
+PASS map.get(symbol2) is undefined
+PASS map.has(symbol) is true
+PASS map.get(symbol) is "Cappuccino"
+PASS map.size is 1
+PASS key is symbol
+PASS value is "Cappuccino"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/symbol-in-map.html b/LayoutTests/js/symbol-in-map.html
new file mode 100644 (file)
index 0000000..2bc1592
--- /dev/null
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="script-tests/symbol-in-map.js"></script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/symbol-object-expected.txt b/LayoutTests/js/symbol-object-expected.txt
new file mode 100644 (file)
index 0000000..3d59d98
--- /dev/null
@@ -0,0 +1,22 @@
+This tests Symbol object behaviors.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS new Symbol threw exception TypeError: function is not a constructor (evaluating 'new Symbol').
+PASS new Symbol('Cappuccino') threw exception TypeError: function is not a constructor (evaluating 'new Symbol('Cappuccino')').
+PASS symbolObject instanceof Symbol is true
+PASS String(symbolObject) threw exception TypeError: Type error.
+PASS symbolObject.toString() is "Symbol(Symbol.iterator)"
+PASS object[symbolObject] is 42
+PASS object['Symbol(Symbol.iterator)'] is undefined
+PASS object[Symbol.iterator] is 42
+PASS object[symbol] is "Cocoa"
+PASS object[symbol.valueOf()] is "Cocoa"
+PASS object[Object(symbol)] is "Cocoa"
+PASS object['Matcha'] is undefined
+PASS Symbol.iterator.hello is undefined
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/symbol-object.html b/LayoutTests/js/symbol-object.html
new file mode 100644 (file)
index 0000000..5710904
--- /dev/null
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="script-tests/symbol-object.js"></script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/symbol-prototype-is-ordinary-object-expected.txt b/LayoutTests/js/symbol-prototype-is-ordinary-object-expected.txt
new file mode 100644 (file)
index 0000000..8ff3c2b
--- /dev/null
@@ -0,0 +1,11 @@
+This tests that Symbol.prototype object is ordinary object (not Symbol wrapper object).
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Symbol.prototype.toString.call(Symbol.prototype) threw exception TypeError: Type error.
+PASS Symbol.prototype.toString.call(Symbol.iterator) is "Symbol(Symbol.iterator)"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/symbol-prototype-is-ordinary-object.html b/LayoutTests/js/symbol-prototype-is-ordinary-object.html
new file mode 100644 (file)
index 0000000..a2b100a
--- /dev/null
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="script-tests/symbol-prototype-is-ordinary-object.js"></script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/symbol-strict-equality-comparison-expected.txt b/LayoutTests/js/symbol-strict-equality-comparison-expected.txt
new file mode 100644 (file)
index 0000000..9970ca9
--- /dev/null
@@ -0,0 +1,69 @@
+This tests Strict Equality Comparison results with Symbols.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS 42 === symbol is false
+PASS symbol === 42 is false
+PASS NaN === symbol is false
+PASS symbol === NaN is false
+PASS Infinity === symbol is false
+PASS symbol === Infinity is false
+PASS true === symbol is false
+PASS symbol === true is false
+PASS false === symbol is false
+PASS symbol === false is false
+PASS null === symbol is false
+PASS symbol === null is false
+PASS undefined === symbol is false
+PASS symbol === undefined is false
+PASS 'Cappuccino' === symbol is false
+PASS symbol === 'Cappuccino' is false
+PASS symbol === symbol is true
+PASS symbol === symbol is true
+PASS Symbol.iterator === symbol is false
+PASS symbol === Symbol.iterator is false
+PASS object === symbol is false
+PASS symbol === object is false
+PASS array === symbol is false
+PASS symbol === array is false
+PASS date === symbol is false
+PASS symbol === date is false
+PASS symbolObject === symbol is false
+PASS symbol === symbolObject is false
+PASS Symbol('Cocoa') === symbol is false
+PASS symbol === Symbol('Cocoa') is false
+PASS 42 !== symbol is true
+PASS symbol !== 42 is true
+PASS NaN !== symbol is true
+PASS symbol !== NaN is true
+PASS Infinity !== symbol is true
+PASS symbol !== Infinity is true
+PASS true !== symbol is true
+PASS symbol !== true is true
+PASS false !== symbol is true
+PASS symbol !== false is true
+PASS null !== symbol is true
+PASS symbol !== null is true
+PASS undefined !== symbol is true
+PASS symbol !== undefined is true
+PASS 'Cappuccino' !== symbol is true
+PASS symbol !== 'Cappuccino' is true
+PASS symbol !== symbol is false
+PASS symbol !== symbol is false
+PASS Symbol.iterator !== symbol is true
+PASS symbol !== Symbol.iterator is true
+PASS object !== symbol is true
+PASS symbol !== object is true
+PASS array !== symbol is true
+PASS symbol !== array is true
+PASS date !== symbol is true
+PASS symbol !== date is true
+PASS symbolObject !== symbol is true
+PASS symbol !== symbolObject is true
+PASS Symbol('Cocoa') !== symbol is true
+PASS symbol !== Symbol('Cocoa') is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/symbol-strict-equality-comparison.html b/LayoutTests/js/symbol-strict-equality-comparison.html
new file mode 100644 (file)
index 0000000..cba86d6
--- /dev/null
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="script-tests/symbol-strict-equality-comparison.js"></script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/symbol-tostring-expected.txt b/LayoutTests/js/symbol-tostring-expected.txt
new file mode 100644 (file)
index 0000000..be39daf
--- /dev/null
@@ -0,0 +1,17 @@
+This tests that ToString(Symbol) behaviors.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS String(Symbol.iterator) is "Symbol(Symbol.iterator)"
+PASS String(Symbol.prototype) threw exception TypeError: Type error.
+PASS Symbol.prototype.toString.call(Symbol.iterator) is "Symbol(Symbol.iterator)"
+PASS Symbol.prototype.toString.call(Symbol('hello')) is "Symbol(hello)"
+PASS Symbol.prototype.toString.call(Symbol()) is "Symbol()"
+PASS Object.prototype.toString.call(Symbol()) is "[object Symbol]"
+PASS Object.prototype.toString.call(Symbol.prototype) is "[object Symbol]"
+PASS Object.prototype.toString.call(Symbol) is "[object Function]"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/symbol-tostring.html b/LayoutTests/js/symbol-tostring.html
new file mode 100644 (file)
index 0000000..bcd176b
--- /dev/null
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="script-tests/symbol-tostring.js"></script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
similarity index 88%
rename from LayoutTests/js/names-expected.txt
rename to LayoutTests/js/symbols-expected.txt
index f12be86..0a84e70 100644 (file)
@@ -1,4 +1,4 @@
-This tests an early experimental implementation of ES6-esque private names.
+This tests an early experimental implementation of ES6-esque Symbols.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
similarity index 80%
rename from LayoutTests/js/names.html
rename to LayoutTests/js/symbols.html
index 23aef4a..4113455 100644 (file)
@@ -4,7 +4,7 @@
 <script src="../resources/js-test-pre.js"></script>
 </head>
 <body>
-<script src="script-tests/names.js"></script>
+<script src="script-tests/symbols.js"></script>
 <script src="../resources/js-test-post.js"></script>
 </body>
 </html>
index 5d31970..34e2461 100644 (file)
@@ -508,9 +508,6 @@ set(JavaScriptCore_RUNTIME_SOURCES
     runtime/MapPrototype.cpp
     runtime/MathObject.cpp
     runtime/MemoryStatistics.cpp
-    runtime/NameConstructor.cpp
-    runtime/NameInstance.cpp
-    runtime/NamePrototype.cpp
     runtime/NativeErrorConstructor.cpp
     runtime/NativeErrorPrototype.cpp
     runtime/NullGetterFunction.cpp
@@ -551,6 +548,10 @@ set(JavaScriptCore_RUNTIME_SOURCES
     runtime/StructureChain.cpp
     runtime/StructureIDTable.cpp
     runtime/StructureRareData.cpp
+    runtime/Symbol.cpp
+    runtime/SymbolObject.cpp
+    runtime/SymbolPrototype.cpp
+    runtime/SymbolConstructor.cpp
     runtime/SymbolTable.cpp
     runtime/TestRunnerUtils.cpp
     runtime/TypeLocationCache.cpp
@@ -584,7 +585,6 @@ set(JavaScriptCore_LUT_FILES
     runtime/JSONObject.cpp
     runtime/JSPromiseConstructor.cpp
     runtime/JSPromisePrototype.cpp
-    runtime/NamePrototype.cpp
     runtime/NumberConstructor.cpp
     runtime/NumberPrototype.cpp
     runtime/ObjectConstructor.cpp
@@ -592,6 +592,7 @@ set(JavaScriptCore_LUT_FILES
     runtime/RegExpObject.cpp
     runtime/RegExpPrototype.cpp
     runtime/StringConstructor.cpp
+    runtime/SymbolPrototype.cpp
 )
 
 set(JavaScriptCore_LIBRARIES
index 6b18a65..b29b00a 100644 (file)
@@ -1,3 +1,199 @@
+2015-01-30  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        Implement ES6 Symbol
+        https://bugs.webkit.org/show_bug.cgi?id=140435
+
+        Reviewed by Geoffrey Garen.
+
+        This patch implements ES6 Symbol. In this patch, we don't support
+        Symbol.keyFor, Symbol.for, Object.getOwnPropertySymbols. They will be
+        supported in the subsequent patches.
+
+        Since ES6 Symbol is introduced as new primitive value, we implement
+        Symbol as a derived class from JSCell. And now JSValue accepts Symbol*
+        as a new primitive value.
+
+        Symbol has a *unique* flagged StringImpl* as an `uid`. Which pointer
+        value represents the Symbol's identity. So don't compare Symbol's
+        JSCell pointer value for comparison.
+        This enables re-producing Symbol primitive value from StringImpl* uid
+        by executing`Symbol::create(vm, uid)`. This is needed to produce
+        Symbol primitive values from stored StringImpl* in `Object.getOwnPropertySymbols`.
+
+        And Symbol.[[Description]] is folded into the string value of Symbol's uid.
+        By doing so, we can represent ES6 Symbol without extending current PropertyTable key; StringImpl*.
+
+        * CMakeLists.txt:
+        * DerivedSources.make:
+        * JavaScriptCore.order:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * builtins/BuiltinExecutables.cpp:
+        (JSC::BuiltinExecutables::createBuiltinExecutable):
+        * builtins/BuiltinNames.h:
+        * dfg/DFGOperations.cpp:
+        (JSC::DFG::operationPutByValInternal):
+        * inspector/JSInjectedScriptHost.cpp:
+        (Inspector::JSInjectedScriptHost::subtype):
+        * interpreter/Interpreter.cpp:
+        * jit/JITOperations.cpp:
+        (JSC::getByVal):
+        * llint/LLIntData.cpp:
+        (JSC::LLInt::Data::performAssertions):
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::getByVal):
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        * llint/LowLevelInterpreter.asm:
+        * runtime/CommonIdentifiers.h:
+        * runtime/CommonSlowPaths.cpp:
+        (JSC::SLOW_PATH_DECL):
+        * runtime/CommonSlowPaths.h:
+        (JSC::CommonSlowPaths::opIn):
+        * runtime/ExceptionHelpers.cpp:
+        (JSC::createUndefinedVariableError):
+        * runtime/JSCJSValue.cpp:
+        (JSC::JSValue::synthesizePrototype):
+        (JSC::JSValue::dumpInContextAssumingStructure):
+        (JSC::JSValue::toStringSlowCase):
+        * runtime/JSCJSValue.h:
+        * runtime/JSCJSValueInlines.h:
+        (JSC::JSValue::isSymbol):
+        (JSC::JSValue::isPrimitive):
+        (JSC::JSValue::toPropertyKey):
+
+        It represents ToPropertyKey abstract operation in the ES6 spec.
+        It cleans up the old implementation's `isName` checks.
+        And to prevent performance regressions in
+            js/regress/fold-get-by-id-to-multi-get-by-offset-rare-int.html
+            js/regress/fold-get-by-id-to-multi-get-by-offset.html
+        we annnotate this function as ALWAYS_INLINE.
+
+        (JSC::JSValue::getPropertySlot):
+        (JSC::JSValue::get):
+        (JSC::JSValue::equalSlowCaseInline):
+        (JSC::JSValue::strictEqualSlowCaseInline):
+        * runtime/JSCell.cpp:
+        (JSC::JSCell::put):
+        (JSC::JSCell::putByIndex):
+        (JSC::JSCell::toPrimitive):
+        (JSC::JSCell::getPrimitiveNumber):
+        (JSC::JSCell::toNumber):
+        (JSC::JSCell::toObject):
+        * runtime/JSCell.h:
+        * runtime/JSCellInlines.h:
+        (JSC::JSCell::isSymbol):
+        (JSC::JSCell::toBoolean):
+        (JSC::JSCell::pureToBoolean):
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::init):
+        (JSC::JSGlobalObject::visitChildren):
+        * runtime/JSGlobalObject.h:
+        (JSC::JSGlobalObject::symbolPrototype):
+        (JSC::JSGlobalObject::symbolObjectStructure):
+        * runtime/JSONObject.cpp:
+        (JSC::Stringifier::Stringifier):
+        * runtime/JSSymbolTableObject.cpp:
+        (JSC::JSSymbolTableObject::getOwnNonIndexPropertyNames):
+        * runtime/JSType.h:
+        * runtime/JSTypeInfo.h:
+        (JSC::TypeInfo::isName): Deleted.
+        * runtime/MapData.cpp:
+        (JSC::MapData::find):
+        (JSC::MapData::add):
+        (JSC::MapData::remove):
+        (JSC::MapData::replaceAndPackBackingStore):
+        * runtime/MapData.h:
+        (JSC::MapData::clear):
+        * runtime/NameInstance.h: Removed.
+        * runtime/NamePrototype.cpp: Removed.
+        * runtime/ObjectConstructor.cpp:
+        (JSC::objectConstructorGetOwnPropertyDescriptor):
+        (JSC::objectConstructorDefineProperty):
+        * runtime/ObjectPrototype.cpp:
+        (JSC::objectProtoFuncHasOwnProperty):
+        (JSC::objectProtoFuncDefineGetter):
+        (JSC::objectProtoFuncDefineSetter):
+        (JSC::objectProtoFuncLookupGetter):
+        (JSC::objectProtoFuncLookupSetter):
+        (JSC::objectProtoFuncPropertyIsEnumerable):
+        * runtime/Operations.cpp:
+        (JSC::jsTypeStringForValue):
+        (JSC::jsIsObjectType):
+        * runtime/PrivateName.h:
+        (JSC::PrivateName::PrivateName):
+        (JSC::PrivateName::operator==):
+        (JSC::PrivateName::operator!=):
+        * runtime/PropertyMapHashTable.h:
+        (JSC::PropertyTable::find):
+        (JSC::PropertyTable::get):
+        * runtime/PropertyName.h:
+        (JSC::PropertyName::PropertyName):
+        (JSC::PropertyName::publicName):
+        * runtime/SmallStrings.h:
+        * runtime/StringConstructor.cpp:
+        (JSC::callStringConstructor):
+
+        In ES6, String constructor accepts Symbol to execute `String(symbol)`.
+
+        * runtime/Structure.cpp:
+        (JSC::Structure::getPropertyNamesFromStructure):
+        * runtime/StructureInlines.h:
+        (JSC::Structure::prototypeForLookup):
+        * runtime/Symbol.cpp: Added.
+        (JSC::Symbol::Symbol):
+        (JSC::SymbolObject::create):
+        (JSC::Symbol::toPrimitive):
+        (JSC::Symbol::toBoolean):
+        (JSC::Symbol::getPrimitiveNumber):
+        (JSC::Symbol::toObject):
+        (JSC::Symbol::toNumber):
+        (JSC::Symbol::destroy):
+        (JSC::Symbol::descriptiveString):
+        * runtime/Symbol.h: Added.
+        (JSC::Symbol::createStructure):
+        (JSC::Symbol::create):
+        (JSC::Symbol::privateName):
+        (JSC::Symbol::finishCreation):
+        (JSC::asSymbol):
+        * runtime/SymbolConstructor.cpp: Renamed from Source/JavaScriptCore/runtime/NameConstructor.cpp.
+        (JSC::SymbolConstructor::SymbolConstructor):
+        (JSC::SymbolConstructor::finishCreation):
+        (JSC::callSymbol):
+        (JSC::SymbolConstructor::getConstructData):
+        (JSC::SymbolConstructor::getCallData):
+        * runtime/SymbolConstructor.h: Renamed from Source/JavaScriptCore/runtime/NameConstructor.h.
+        (JSC::SymbolConstructor::create):
+        (JSC::SymbolConstructor::createStructure):
+        * runtime/SymbolObject.cpp: Renamed from Source/JavaScriptCore/runtime/NameInstance.cpp.
+        (JSC::SymbolObject::SymbolObject):
+        (JSC::SymbolObject::finishCreation):
+        (JSC::SymbolObject::defaultValue):
+
+        Now JSC doesn't support @@toPrimitive. So instead of it, we implement
+        Symbol.prototype[@@toPrimitive] as ES5 Symbol.[[DefaultValue]].
+
+        * runtime/SymbolObject.h: Added.
+        (JSC::SymbolObject::create):
+        (JSC::SymbolObject::internalValue):
+        (JSC::SymbolObject::createStructure):
+        * runtime/SymbolPrototype.cpp: Added.
+        (JSC::SymbolPrototype::SymbolPrototype):
+        (JSC::SymbolPrototype::finishCreation):
+        (JSC::SymbolPrototype::getOwnPropertySlot):
+        (JSC::symbolProtoFuncToString):
+        (JSC::symbolProtoFuncValueOf):
+        * runtime/SymbolPrototype.h: Renamed from Source/JavaScriptCore/runtime/NamePrototype.h.
+        (JSC::SymbolPrototype::create):
+        (JSC::SymbolPrototype::createStructure):
+
+        SymbolPrototype object is ordinary JS object. Not wrapper object of Symbol.
+        It is tested in js/symbol-prototype-is-ordinary-object.html.
+
+        * runtime/VM.cpp:
+        (JSC::VM::VM):
+        * runtime/VM.h:
+
 2015-01-30  Geoffrey Garen  <ggaren@apple.com>
 
         Use FastMalloc (bmalloc) instead of BlockAllocator for GC pages
index 12afea2..4a2623e 100644 (file)
@@ -48,7 +48,6 @@ all : \
     JSPromiseConstructor.lut.h \
     KeywordLookup.h \
     Lexer.lut.h \
-    NamePrototype.lut.h \
     NumberConstructor.lut.h \
     NumberPrototype.lut.h \
     ObjectConstructor.lut.h \
@@ -57,6 +56,7 @@ all : \
     RegExpJitTables.h \
     RegExpObject.lut.h \
     StringConstructor.lut.h \
+    SymbolPrototype.lut.h \
     udis86_itab.h \
     Bytecodes.h \
     InitBytecodes.asm \
index fd684f6..26be0ee 100644 (file)
@@ -4599,14 +4599,8 @@ __ZN3JSCL24regExpConstructorDollar6EPNS_9ExecStateENS_7JSValueENS_12PropertyName
 __ZN3JSC5LexerIhE23parseIdentifierSlowCaseILb1EEENS_11JSTokenTypeEPNS_11JSTokenDataEjb
 __ZN3JSC4Yarr13YarrGeneratorILNS0_18YarrJITCompileModeE1EE33generatePatternCharacterNonGreedyEm
 __ZN3JSC4Yarr13YarrGeneratorILNS0_18YarrJITCompileModeE1EE34backtrackPatternCharacterNonGreedyEm
-__ZN3JSC13NamePrototypeC1EPNS_9ExecStateEPNS_9StructureE
-__ZN3JSC12NameInstanceC2ERNS_2VMEPNS_9StructureEPNS_8JSStringE
-__ZN3JSC13NamePrototype14finishCreationEPNS_9ExecStateE
-__ZN3JSC15NameConstructorC1EPNS_14JSGlobalObjectEPNS_9StructureE
-__ZN3JSC15NameConstructor14finishCreationEPNS_9ExecStateEPNS_13NamePrototypeE
 _JSStringIsEqualToUTF8CString
 _JSStringIsEqual
-__ZN3JSC12NameInstance7destroyEPNS_6JSCellE
 __ZN3WTF3MD5C1Ev
 __ZN3WTF3MD58addBytesEPKhm
 __ZN3WTFL12MD5TransformEPjPKj
@@ -4756,9 +4750,7 @@ __ZN3JSC22createOutOfMemoryErrorEPNS_14JSGlobalObjectE
 __ZN3JSCL17mathProtoFuncACosEPNS_9ExecStateE
 __ZN3JSC11JSNameScope3putEPNS_6JSCellEPNS_9ExecStateENS_12PropertyNameENS_7JSValueERNS_15PutPropertySlotE
 __ZN3JSC14symbolTablePutINS_11JSNameScopeEEEbPT_PNS_9ExecStateENS_12PropertyNameENS_7JSValueEb
-__ZN3JSC15NameConstructor11getCallDataEPNS_6JSCellERNS_8CallDataE
 __ZN3JSCL20constructPrivateNameEPNS_9ExecStateE
-__ZN3JSC12NameInstanceC1ERNS_2VMEPNS_9StructureEPNS_8JSStringE
 __ZN3JSCL29objectProtoFuncToLocaleStringEPNS_9ExecStateE
 __ZN3JSC13JSNotAnObject24getOwnPropertyDescriptorEPNS_8JSObjectEPNS_9ExecStateENS_12PropertyNameERNS_18PropertyDescriptorE
 __ZN3JSCL20isNonLatin1IdentPartEi
index be98652..ba18a37 100644 (file)
     <ClCompile Include="..\runtime\MapPrototype.cpp" />
     <ClCompile Include="..\runtime\MathObject.cpp" />
     <ClCompile Include="..\runtime\MemoryStatistics.cpp" />
-    <ClCompile Include="..\runtime\NameConstructor.cpp" />
-    <ClCompile Include="..\runtime\NameInstance.cpp" />
-    <ClCompile Include="..\runtime\NamePrototype.cpp" />
     <ClCompile Include="..\runtime\NativeErrorConstructor.cpp" />
     <ClCompile Include="..\runtime\NativeErrorPrototype.cpp" />
     <ClCompile Include="..\runtime\NullGetterFunction.cpp" />
     <ClCompile Include="..\runtime\StructureChain.cpp" />
     <ClCompile Include="..\runtime\StructureIDTable.cpp" />
     <ClCompile Include="..\runtime\StructureRareData.cpp" />
+    <ClCompile Include="..\runtime\Symbol.cpp" />
+    <ClCompile Include="..\runtime\SymbolConstructor.cpp" />
+    <ClCompile Include="..\runtime\SymbolObject.cpp" />
+    <ClCompile Include="..\runtime\SymbolPrototype.cpp" />
     <ClCompile Include="..\runtime\SymbolTable.cpp" />
     <ClCompile Include="..\runtime\TestRunnerUtils.cpp" />
     <ClCompile Include="..\runtime\TypedArrayController.cpp" />
     <ClInclude Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\JSPromisePrototype.lut.h" />
     <ClInclude Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\KeywordLookup.lut.h" />
     <ClInclude Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\Lexer.lut.h" />
-    <ClInclude Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\NamePrototype.lut.h" />
     <ClInclude Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\NumberConstructor.lut.h" />
     <ClInclude Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\NumberPrototype.lut.h" />
     <ClInclude Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\ObjectConstructor.lut.h" />
     <ClInclude Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\RegExpObject.lut.h" />
     <ClInclude Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\RegExpPrototype.lut.h" />
     <ClInclude Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\StringConstructor.lut.h" />
+    <ClInclude Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\SymbolPrototype.lut.h" />
     <ClInclude Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\JSCBuiltins.h" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\runtime\MathObject.h" />
     <ClInclude Include="..\runtime\MemoryStatistics.h" />
     <ClInclude Include="..\runtime\Microtask.h" />
-    <ClInclude Include="..\runtime\NameConstructor.h" />
-    <ClInclude Include="..\runtime\NameInstance.h" />
-    <ClInclude Include="..\runtime\NamePrototype.h" />
     <ClInclude Include="..\runtime\NativeErrorConstructor.h" />
     <ClInclude Include="..\runtime\NativeErrorPrototype.h" />
     <ClInclude Include="..\runtime\NullGetterFunction.h" />
     <ClInclude Include="..\runtime\StructureRareData.h" />
     <ClInclude Include="..\runtime\StructureRareDataInlines.h" />
     <ClInclude Include="..\runtime\StructureTransitionTable.h" />
+    <ClInclude Include="..\runtime\Symbol.h" />
+    <ClInclude Include="..\runtime\SymbolConstructor.h" />
+    <ClInclude Include="..\runtime\SymbolObject.h" />
+    <ClInclude Include="..\runtime\SymbolPrototype.h" />
     <ClInclude Include="..\runtime\SymbolTable.h" />
     <ClInclude Include="..\runtime\TestRunnerUtils.h" />
     <ClInclude Include="..\runtime\Tracing.h" />
index 515a32c..ac53065 100644 (file)
     <ClCompile Include="..\runtime\MathObject.cpp">
       <Filter>runtime</Filter>
     </ClCompile>
-    <ClCompile Include="..\runtime\NameConstructor.cpp">
-      <Filter>runtime</Filter>
-    </ClCompile>
-    <ClCompile Include="..\runtime\NameInstance.cpp">
-      <Filter>runtime</Filter>
-    </ClCompile>
-    <ClCompile Include="..\runtime\NamePrototype.cpp">
-      <Filter>runtime</Filter>
-    </ClCompile>
     <ClCompile Include="..\runtime\NativeErrorConstructor.cpp">
       <Filter>runtime</Filter>
     </ClCompile>
     <ClCompile Include="..\runtime\StructureIDTable.cpp">
       <Filter>runtime</Filter>
     </ClCompile>
+    <ClCompile Include="..\runtime\Symbol.cpp">
+      <Filter>runtime</Filter>
+    </ClInclude>
+    <ClCompile Include="..\runtime\SymbolConstructor.cpp">
+      <Filter>runtime</Filter>
+    </ClCompile>
+    <ClCompile Include="..\runtime\SymbolObject.cpp">
+      <Filter>runtime</Filter>
+    </ClCompile>
+    <ClCompile Include="..\runtime\SymbolPrototype.cpp">
+      <Filter>runtime</Filter>
+    </ClCompile>
     <ClCompile Include="..\runtime\SymbolTable.cpp">
       <Filter>runtime</Filter>
     </ClCompile>
     <ClInclude Include="..\runtime\MathObject.h">
       <Filter>runtime</Filter>
     </ClInclude>
-    <ClInclude Include="..\runtime\NameConstructor.h">
-      <Filter>runtime</Filter>
-    </ClInclude>
-    <ClInclude Include="..\runtime\NameInstance.h">
-      <Filter>runtime</Filter>
-    </ClInclude>
-    <ClInclude Include="..\runtime\NamePrototype.h">
-      <Filter>runtime</Filter>
-    </ClInclude>
     <ClInclude Include="..\runtime\NativeErrorConstructor.h">
       <Filter>runtime</Filter>
     </ClInclude>
     <ClInclude Include="..\runtime\StructureTransitionTable.h">
       <Filter>runtime</Filter>
     </ClInclude>
+    <ClInclude Include="..\runtime\Symbol.h">
+      <Filter>runtime</Filter>
+    </ClInclude>
+    <ClInclude Include="..\runtime\SymbolConstructor.h">
+      <Filter>runtime</Filter>
+    </ClInclude>
+    <ClInclude Include="..\runtime\SymbolObject.h">
+      <Filter>runtime</Filter>
+    </ClInclude>
+    <ClInclude Include="..\runtime\SymbolPrototype.h">
+      <Filter>runtime</Filter>
+    </ClInclude>
     <ClInclude Include="..\runtime\SymbolTable.h">
       <Filter>runtime</Filter>
     </ClInclude>
     <ClInclude Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\RegExpObject.lut.h">
       <Filter>Derived Sources</Filter>
     </ClInclude>
-    <ClInclude Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\NamePrototype.lut.h">
+    <ClInclude Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\SymbolPrototype.lut.h">
       <Filter>Derived Sources</Filter>
     </ClInclude>
     <ClInclude Include="..\heap\CodeBlockSet.h">
index 6a71fd2..253df2d 100644 (file)
                65C0285D1717966800351E35 /* ARMv7DOpcode.h in Headers */ = {isa = PBXBuildFile; fileRef = 65C0285B1717966800351E35 /* ARMv7DOpcode.h */; };
                65FB5117184EEE7000C12B70 /* ProtoCallFrame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65FB5116184EE9BC00C12B70 /* ProtoCallFrame.cpp */; };
                6AD2CB4D19B9140100065719 /* DebuggerEvalEnabler.h in Headers */ = {isa = PBXBuildFile; fileRef = 6AD2CB4C19B9140100065719 /* DebuggerEvalEnabler.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               705B41AB1A6E501E00716757 /* Symbol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 705B41A31A6E501E00716757 /* Symbol.cpp */; };
+               705B41AC1A6E501E00716757 /* Symbol.h in Headers */ = {isa = PBXBuildFile; fileRef = 705B41A41A6E501E00716757 /* Symbol.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               705B41AD1A6E501E00716757 /* SymbolConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 705B41A51A6E501E00716757 /* SymbolConstructor.cpp */; };
+               705B41AE1A6E501E00716757 /* SymbolConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = 705B41A61A6E501E00716757 /* SymbolConstructor.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               705B41AF1A6E501E00716757 /* SymbolObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 705B41A71A6E501E00716757 /* SymbolObject.cpp */; };
+               705B41B01A6E501E00716757 /* SymbolObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 705B41A81A6E501E00716757 /* SymbolObject.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               705B41B11A6E501E00716757 /* SymbolPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 705B41A91A6E501E00716757 /* SymbolPrototype.cpp */; };
+               705B41B21A6E501E00716757 /* SymbolPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = 705B41AA1A6E501E00716757 /* SymbolPrototype.h */; settings = {ATTRIBUTES = (Private, ); }; };
                7C008CD2186F8A9300955C24 /* JSPromiseFunctions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C008CD0186F8A9300955C24 /* JSPromiseFunctions.cpp */; };
                7C008CD3186F8A9300955C24 /* JSPromiseFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C008CD1186F8A9300955C24 /* JSPromiseFunctions.h */; settings = {ATTRIBUTES = (Private, ); }; };
                7C008CDA187124BB00955C24 /* JSPromiseDeferred.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C008CD8187124BB00955C24 /* JSPromiseDeferred.cpp */; };
                86E3C61C167BABEE006D760A /* JSVirtualMachine.mm in Sources */ = {isa = PBXBuildFile; fileRef = 86E3C610167BAB87006D760A /* JSVirtualMachine.mm */; };
                86E3C61D167BABEE006D760A /* JSVirtualMachineInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 86E3C611167BAB87006D760A /* JSVirtualMachineInternal.h */; settings = {ATTRIBUTES = (Private, ); }; };
                86E85539111B9968001AF51E /* JSStringBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 86E85538111B9968001AF51E /* JSStringBuilder.h */; };
-               86EBF2FF1560F06A008E9222 /* NameConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86EBF2F91560F036008E9222 /* NameConstructor.cpp */; };
-               86EBF3001560F06A008E9222 /* NameConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = 86EBF2FA1560F036008E9222 /* NameConstructor.h */; };
-               86EBF3011560F06A008E9222 /* NameInstance.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86EBF2FB1560F036008E9222 /* NameInstance.cpp */; };
-               86EBF3021560F06A008E9222 /* NameInstance.h in Headers */ = {isa = PBXBuildFile; fileRef = 86EBF2FC1560F036008E9222 /* NameInstance.h */; };
-               86EBF3031560F06A008E9222 /* NamePrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86EBF2FD1560F036008E9222 /* NamePrototype.cpp */; };
-               86EBF3041560F06A008E9222 /* NamePrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = 86EBF2FE1560F036008E9222 /* NamePrototype.h */; };
                86EC9DC41328DF82002B2AD7 /* DFGByteCodeParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86EC9DB41328DF82002B2AD7 /* DFGByteCodeParser.cpp */; };
                86EC9DC51328DF82002B2AD7 /* DFGByteCodeParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 86EC9DB51328DF82002B2AD7 /* DFGByteCodeParser.h */; settings = {ATTRIBUTES = (Private, ); }; };
                86EC9DC61328DF82002B2AD7 /* DFGGenerationInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 86EC9DB61328DF82002B2AD7 /* DFGGenerationInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
                65FB5116184EE9BC00C12B70 /* ProtoCallFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProtoCallFrame.cpp; sourceTree = "<group>"; };
                6AD2CB4C19B9140100065719 /* DebuggerEvalEnabler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebuggerEvalEnabler.h; sourceTree = "<group>"; };
                704FD35305697E6D003DBED9 /* BooleanObject.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = BooleanObject.h; sourceTree = "<group>"; tabWidth = 8; };
+               705B41A31A6E501E00716757 /* Symbol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Symbol.cpp; sourceTree = "<group>"; };
+               705B41A41A6E501E00716757 /* Symbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Symbol.h; sourceTree = "<group>"; };
+               705B41A51A6E501E00716757 /* SymbolConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SymbolConstructor.cpp; sourceTree = "<group>"; };
+               705B41A61A6E501E00716757 /* SymbolConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SymbolConstructor.h; sourceTree = "<group>"; };
+               705B41A71A6E501E00716757 /* SymbolObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SymbolObject.cpp; sourceTree = "<group>"; };
+               705B41A81A6E501E00716757 /* SymbolObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SymbolObject.h; sourceTree = "<group>"; };
+               705B41A91A6E501E00716757 /* SymbolPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SymbolPrototype.cpp; sourceTree = "<group>"; };
+               705B41AA1A6E501E00716757 /* SymbolPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SymbolPrototype.h; sourceTree = "<group>"; };
                7C008CD0186F8A9300955C24 /* JSPromiseFunctions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = JSPromiseFunctions.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
                7C008CD1186F8A9300955C24 /* JSPromiseFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPromiseFunctions.h; sourceTree = "<group>"; };
                7C008CD8187124BB00955C24 /* JSPromiseDeferred.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPromiseDeferred.cpp; sourceTree = "<group>"; };
                86E3C610167BAB87006D760A /* JSVirtualMachine.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = JSVirtualMachine.mm; sourceTree = "<group>"; };
                86E3C611167BAB87006D760A /* JSVirtualMachineInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSVirtualMachineInternal.h; sourceTree = "<group>"; };
                86E85538111B9968001AF51E /* JSStringBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStringBuilder.h; sourceTree = "<group>"; };
-               86EBF2F91560F036008E9222 /* NameConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NameConstructor.cpp; sourceTree = "<group>"; };
-               86EBF2FA1560F036008E9222 /* NameConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NameConstructor.h; sourceTree = "<group>"; };
-               86EBF2FB1560F036008E9222 /* NameInstance.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NameInstance.cpp; sourceTree = "<group>"; };
-               86EBF2FC1560F036008E9222 /* NameInstance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NameInstance.h; sourceTree = "<group>"; };
-               86EBF2FD1560F036008E9222 /* NamePrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NamePrototype.cpp; sourceTree = "<group>"; };
-               86EBF2FE1560F036008E9222 /* NamePrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NamePrototype.h; sourceTree = "<group>"; };
                86EC9DB41328DF82002B2AD7 /* DFGByteCodeParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGByteCodeParser.cpp; path = dfg/DFGByteCodeParser.cpp; sourceTree = "<group>"; };
                86EC9DB51328DF82002B2AD7 /* DFGByteCodeParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGByteCodeParser.h; path = dfg/DFGByteCodeParser.h; sourceTree = "<group>"; };
                86EC9DB61328DF82002B2AD7 /* DFGGenerationInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGGenerationInfo.h; path = dfg/DFGGenerationInfo.h; sourceTree = "<group>"; };
                                90213E3B123A40C200D422F3 /* MemoryStatistics.cpp */,
                                90213E3C123A40C200D422F3 /* MemoryStatistics.h */,
                                7C008CE5187631B600955C24 /* Microtask.h */,
-                               86EBF2F91560F036008E9222 /* NameConstructor.cpp */,
-                               86EBF2FA1560F036008E9222 /* NameConstructor.h */,
-                               86EBF2FB1560F036008E9222 /* NameInstance.cpp */,
-                               86EBF2FC1560F036008E9222 /* NameInstance.h */,
-                               86EBF2FD1560F036008E9222 /* NamePrototype.cpp */,
-                               86EBF2FE1560F036008E9222 /* NamePrototype.h */,
                                BC02E9080E1839DB000F9297 /* NativeErrorConstructor.cpp */,
                                BC02E9090E1839DB000F9297 /* NativeErrorConstructor.h */,
                                BC02E90A0E1839DB000F9297 /* NativeErrorPrototype.cpp */,
                                C2FE18A316BAEC4000AF3061 /* StructureRareData.h */,
                                C20BA92C16BB1C1500B3AEA2 /* StructureRareDataInlines.h */,
                                BC9041470EB9250900FE26FA /* StructureTransitionTable.h */,
+                               705B41A31A6E501E00716757 /* Symbol.cpp */,
+                               705B41A41A6E501E00716757 /* Symbol.h */,
+                               705B41A51A6E501E00716757 /* SymbolConstructor.cpp */,
+                               705B41A61A6E501E00716757 /* SymbolConstructor.h */,
+                               705B41A71A6E501E00716757 /* SymbolObject.cpp */,
+                               705B41A81A6E501E00716757 /* SymbolObject.h */,
+                               705B41A91A6E501E00716757 /* SymbolPrototype.cpp */,
+                               705B41AA1A6E501E00716757 /* SymbolPrototype.h */,
                                0F919D2715856770004A4E7D /* SymbolTable.cpp */,
                                14A396A60CD2933100B5B4FF /* SymbolTable.h */,
                                0FA2C17917D7CF84009D015F /* TestRunnerUtils.cpp */,
                                0F3D0BBD194A414300FC9CF9 /* ConstantStructureCheck.h in Headers */,
                                7C008CE7187631B600955C24 /* Microtask.h in Headers */,
                                86C568E211A213EE0007F7F0 /* MIPSAssembler.h in Headers */,
-                               86EBF3001560F06A008E9222 /* NameConstructor.h in Headers */,
-                               86EBF3021560F06A008E9222 /* NameInstance.h in Headers */,
-                               86EBF3041560F06A008E9222 /* NamePrototype.h in Headers */,
                                BC02E9110E1839DB000F9297 /* NativeErrorConstructor.h in Headers */,
                                BC02E9130E1839DB000F9297 /* NativeErrorPrototype.h in Headers */,
                                99CC0B6318BE9950006CEBCC /* CodeGeneratorReplayInputs.py in Headers */,
                                BCCF0D080EF0AAB900413C8F /* StructureStubInfo.h in Headers */,
                                BC9041480EB9250900FE26FA /* StructureTransitionTable.h in Headers */,
                                C2DF44301707AC0100A5CA96 /* SuperRegion.h in Headers */,
+                               705B41AC1A6E501E00716757 /* Symbol.h in Headers */,
+                               705B41AE1A6E501E00716757 /* SymbolConstructor.h in Headers */,
+                               705B41B01A6E501E00716757 /* SymbolObject.h in Headers */,
+                               705B41B21A6E501E00716757 /* SymbolPrototype.h in Headers */,
                                BC18C46B0E16F5CD00B34460 /* SymbolTable.h in Headers */,
                                A784A26411D16622005776AC /* SyntaxChecker.h in Headers */,
                                0F24E54F17EE274900ABB217 /* TempRegisterSet.h in Headers */,
                                14469DDF107EC7E700650446 /* MathObject.cpp in Sources */,
                                90213E3D123A40C200D422F3 /* MemoryStatistics.cpp in Sources */,
                                0FB5467D14F5CFD6002C2989 /* MethodOfGettingAValueProfile.cpp in Sources */,
-                               86EBF2FF1560F06A008E9222 /* NameConstructor.cpp in Sources */,
-                               86EBF3011560F06A008E9222 /* NameInstance.cpp in Sources */,
-                               86EBF3031560F06A008E9222 /* NamePrototype.cpp in Sources */,
                                14469DE0107EC7E700650446 /* NativeErrorConstructor.cpp in Sources */,
                                14469DE1107EC7E700650446 /* NativeErrorPrototype.cpp in Sources */,
                                148F21B7107EC5470042EC2C /* Nodes.cpp in Sources */,
                                0F766D3815AE4A1C008F363E /* StructureStubClearingWatchpoint.cpp in Sources */,
                                BCCF0D0C0EF0B8A500413C8F /* StructureStubInfo.cpp in Sources */,
                                C2DF442F1707AC0100A5CA96 /* SuperRegion.cpp in Sources */,
+                               705B41AB1A6E501E00716757 /* Symbol.cpp in Sources */,
+                               705B41AD1A6E501E00716757 /* SymbolConstructor.cpp in Sources */,
+                               705B41AF1A6E501E00716757 /* SymbolObject.cpp in Sources */,
+                               705B41B11A6E501E00716757 /* SymbolPrototype.cpp in Sources */,
                                0F919D2815856773004A4E7D /* SymbolTable.cpp in Sources */,
                                0FC314131814559100033232 /* TempRegisterSet.cpp in Sources */,
                                0FA2C17B17D7CF84009D015F /* TestRunnerUtils.cpp in Sources */,
index ef6737e..9fcdaa1 100644 (file)
@@ -75,7 +75,7 @@ UnlinkedFunctionExecutable* BuiltinExecutables::createBuiltinExecutable(const So
         
         if (closedVariable == m_vm.propertyNames->undefinedKeyword.impl())
             continue;
-        RELEASE_ASSERT(closedVariable->isEmptyUnique());
+        RELEASE_ASSERT(closedVariable->isUnique());
     }
     body->overrideName(name);
     UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&m_vm, source, body, UnlinkedBuiltinFunction);
index 67e1f56..9b8896b 100644 (file)
@@ -31,7 +31,7 @@
 
 namespace JSC {
     
-#define INITIALISE_BUILTIN_NAMES(name) , m_##name(vm, #name), m_##name##PrivateName(Identifier::from(PrivateName()))
+#define INITIALISE_BUILTIN_NAMES(name) , m_##name(vm, #name), m_##name##PrivateName(Identifier::from(PrivateName(ASCIILiteral("Symbol." #name))))
 #define DECLARE_BUILTIN_NAMES(name) const Identifier m_##name; const Identifier m_##name##PrivateName;;
 #define DECLARE_BUILTIN_IDENTIFIER_ACCESSOR(name) \
     const Identifier& name##PublicName() const { return m_##name; } \
index 795e605..92e9cc2 100644 (file)
 #include "JSLexicalEnvironment.h"
 #include "VM.h"
 #include "JSNameScope.h"
-#include "NameInstance.h"
 #include "ObjectConstructor.h"
 #include "JSCInlines.h"
 #include "Repatch.h"
 #include "StringConstructor.h"
+#include "Symbol.h"
 #include "TypeProfilerLog.h"
 #include "TypedArrayInlines.h"
 #include <wtf/InlineASM.h>
@@ -110,25 +110,15 @@ ALWAYS_INLINE static void JIT_OPERATION operationPutByValInternal(ExecState* exe
         }
     }
 
-    if (isName(property)) {
-        PutPropertySlot slot(baseValue, strict);
-        if (direct) {
-            RELEASE_ASSERT(baseValue.isObject());
-            asObject(baseValue)->putDirect(*vm, jsCast<NameInstance*>(property.asCell())->privateName(), value, slot);
-        } else
-            baseValue.put(exec, jsCast<NameInstance*>(property.asCell())->privateName(), value, slot);
-        return;
-    }
-
     // Don't put to an object if toString throws an exception.
-    Identifier ident = property.toString(exec)->toIdentifier(exec);
+    PropertyName propertyName = property.toPropertyKey(exec);
     if (!vm->exception()) {
         PutPropertySlot slot(baseValue, strict);
         if (direct) {
             RELEASE_ASSERT(baseValue.isObject());
-            asObject(baseValue)->putDirect(*vm, ident, value, slot);
+            asObject(baseValue)->putDirect(*vm, propertyName, value, slot);
         } else
-            baseValue.put(exec, ident, value, slot);
+            baseValue.put(exec, propertyName, value, slot);
     }
 }
 
@@ -306,11 +296,8 @@ EncodedJSValue JIT_OPERATION operationGetByVal(ExecState* exec, EncodedJSValue e
         }
     }
 
-    if (isName(property))
-        return JSValue::encode(baseValue.get(exec, jsCast<NameInstance*>(property.asCell())->privateName()));
-
-    Identifier ident = property.toString(exec)->toIdentifier(exec);
-    return JSValue::encode(baseValue.get(exec, ident));
+    PropertyName propertyName = property.toPropertyKey(exec);
+    return JSValue::encode(baseValue.get(exec, propertyName));
 }
 
 EncodedJSValue JIT_OPERATION operationGetByValCell(ExecState* exec, JSCell* base, EncodedJSValue encodedProperty)
@@ -337,11 +324,8 @@ EncodedJSValue JIT_OPERATION operationGetByValCell(ExecState* exec, JSCell* base
         }
     }
 
-    if (isName(property))
-        return JSValue::encode(JSValue(base).get(exec, jsCast<NameInstance*>(property.asCell())->privateName()));
-
-    Identifier ident = property.toString(exec)->toIdentifier(exec);
-    return JSValue::encode(JSValue(base).get(exec, ident));
+    PropertyName propertyName = property.toPropertyKey(exec);
+    return JSValue::encode(JSValue(base).get(exec, propertyName));
 }
 
 ALWAYS_INLINE EncodedJSValue getByValCellInt(ExecState* exec, JSCell* base, int32_t index)
index 297e491..5855b58 100644 (file)
@@ -122,6 +122,8 @@ JSValue JSInjectedScriptHost::subtype(ExecState* exec)
         return exec->vm().smallStrings.booleanString();
     if (value.isNumber())
         return exec->vm().smallStrings.numberString();
+    if (value.isSymbol())
+        return exec->vm().smallStrings.symbolString();
 
     JSObject* object = asObject(value);
     if (object && object->isErrorInstance())
index d11a481..ebe2402 100644 (file)
@@ -54,7 +54,6 @@
 #include "LLIntThunks.h"
 #include "LegacyProfiler.h"
 #include "LiteralParser.h"
-#include "NameInstance.h"
 #include "ObjectPrototype.h"
 #include "JSCInlines.h"
 #include "Parser.h"
@@ -67,6 +66,7 @@
 #include "StackVisitor.h"
 #include "StrictEvalActivation.h"
 #include "StrongInlines.h"
+#include "Symbol.h"
 #include "VMEntryScope.h"
 #include "VirtualRegister.h"
 
index 37aa45d..3885c06 100644 (file)
@@ -159,7 +159,7 @@ EncodedJSValue JIT_OPERATION operationGetByIdOptimize(ExecState* exec, Structure
 {
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
-    Identifier ident = uid->isEmptyUnique() ? Identifier::from(PrivateName(uid)) : Identifier(vm, uid);
+    Identifier ident = uid->isUnique() ? Identifier::from(PrivateName(uid)) : Identifier(vm, uid);
 
     JSValue baseValue = JSValue::decode(base);
     PropertySlot slot(baseValue);
@@ -466,11 +466,8 @@ static void putByVal(CallFrame* callFrame, JSValue baseValue, JSValue subscript,
                 object->methodTable(vm)->putByIndex(object, callFrame, i, value, callFrame->codeBlock()->isStrictMode());
         } else
             baseValue.putByIndex(callFrame, i, value, callFrame->codeBlock()->isStrictMode());
-    } else if (isName(subscript)) {
-        PutPropertySlot slot(baseValue, callFrame->codeBlock()->isStrictMode());
-        baseValue.put(callFrame, jsCast<NameInstance*>(subscript.asCell())->privateName(), value, slot);
     } else {
-        Identifier property = subscript.toString(callFrame)->toIdentifier(callFrame);
+        PropertyName property = subscript.toPropertyKey(callFrame);
         if (!callFrame->vm().exception()) { // Don't put to an object if toString threw an exception.
             PutPropertySlot slot(baseValue, callFrame->codeBlock()->isStrictMode());
             baseValue.put(callFrame, property, value, slot);
@@ -483,11 +480,8 @@ static void directPutByVal(CallFrame* callFrame, JSObject* baseObject, JSValue s
     if (LIKELY(subscript.isUInt32())) {
         uint32_t i = subscript.asUInt32();
         baseObject->putDirectIndex(callFrame, i, value);
-    } else if (isName(subscript)) {
-        PutPropertySlot slot(baseObject, callFrame->codeBlock()->isStrictMode());
-        baseObject->putDirect(callFrame->vm(), jsCast<NameInstance*>(subscript.asCell())->privateName(), value, slot);
     } else {
-        Identifier property = subscript.toString(callFrame)->toIdentifier(callFrame);
+        PropertyName property = subscript.toPropertyKey(callFrame);
         if (!callFrame->vm().exception()) { // Don't put to an object if toString threw an exception.
             PutPropertySlot slot(baseObject, callFrame->codeBlock()->isStrictMode());
             baseObject->putDirect(callFrame->vm(), property, value, slot);
@@ -1467,10 +1461,7 @@ static JSValue getByVal(ExecState* exec, JSValue baseValue, JSValue subscript, R
         return baseValue.get(exec, i);
     }
 
-    if (isName(subscript))
-        return baseValue.get(exec, jsCast<NameInstance*>(subscript.asCell())->privateName());
-
-    Identifier property = subscript.toString(exec)->toIdentifier(exec);
+    PropertyName property = subscript.toPropertyKey(exec);
     return baseValue.get(exec, property);
 }
 
@@ -1605,10 +1596,8 @@ EncodedJSValue JIT_OPERATION operationGetByValString(ExecState* exec, EncodedJSV
             if (!isJSString(baseValue))
                 ctiPatchCallByReturnAddress(exec->codeBlock(), ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationGetByValDefault));
         }
-    } else if (isName(subscript))
-        result = baseValue.get(exec, jsCast<NameInstance*>(subscript.asCell())->privateName());
-    else {
-        Identifier property = subscript.toString(exec)->toIdentifier(exec);
+    } else {
+        PropertyName property = subscript.toPropertyKey(exec);
         result = baseValue.get(exec, property);
     }
 
index 997e3b9..ab01501 100644 (file)
@@ -132,8 +132,8 @@ void Data::performAssertions(VM& vm)
     ASSERT(maxFrameExtentForSlowPathCall == 64);
 #endif
     ASSERT(StringType == 6);
-    ASSERT(ObjectType == 17);
-    ASSERT(FinalObjectType == 18);
+    ASSERT(ObjectType == 18);
+    ASSERT(FinalObjectType == 19);
     ASSERT(MasqueradesAsUndefined == 1);
     ASSERT(ImplementsHasInstance == 2);
     ASSERT(ImplementsDefaultHasInstance == 8);
index 85bac26..a3022cb 100644 (file)
@@ -744,10 +744,7 @@ inline JSValue getByVal(ExecState* exec, JSValue baseValue, JSValue subscript)
         return baseValue.get(exec, i);
     }
 
-    if (isName(subscript))
-        return baseValue.get(exec, jsCast<NameInstance*>(subscript.asCell())->privateName());
-    
-    Identifier property = subscript.toString(exec)->toIdentifier(exec);
+    PropertyName property = subscript.toPropertyKey(exec);
     return baseValue.get(exec, property);
 }
 
@@ -797,13 +794,7 @@ LLINT_SLOW_PATH_DECL(slow_path_put_by_val)
         LLINT_END();
     }
 
-    if (isName(subscript)) {
-        PutPropertySlot slot(baseValue, exec->codeBlock()->isStrictMode());
-        baseValue.put(exec, jsCast<NameInstance*>(subscript.asCell())->privateName(), value, slot);
-        LLINT_END();
-    }
-
-    Identifier property = subscript.toString(exec)->toIdentifier(exec);
+    PropertyName property = subscript.toPropertyKey(exec);
     LLINT_CHECK_EXCEPTION();
     PutPropertySlot slot(baseValue, exec->codeBlock()->isStrictMode());
     baseValue.put(exec, property, value, slot);
@@ -822,11 +813,8 @@ LLINT_SLOW_PATH_DECL(slow_path_put_by_val_direct)
     if (LIKELY(subscript.isUInt32())) {
         uint32_t i = subscript.asUInt32();
         baseObject->putDirectIndex(exec, i, value);
-    } else if (isName(subscript)) {
-        PutPropertySlot slot(baseObject, exec->codeBlock()->isStrictMode());
-        baseObject->putDirect(exec->vm(), jsCast<NameInstance*>(subscript.asCell())->privateName(), value, slot);
     } else {
-        Identifier property = subscript.toString(exec)->toIdentifier(exec);
+        PropertyName property = subscript.toPropertyKey(exec);
         if (!exec->vm().exception()) { // Don't put to an object if toString threw an exception.
             PutPropertySlot slot(baseObject, exec->codeBlock()->isStrictMode());
             baseObject->putDirect(exec->vm(), property, value, slot);
@@ -848,11 +836,9 @@ LLINT_SLOW_PATH_DECL(slow_path_del_by_val)
     uint32_t i;
     if (subscript.getUInt32(i))
         couldDelete = baseObject->methodTable()->deletePropertyByIndex(baseObject, exec, i);
-    else if (isName(subscript))
-        couldDelete = baseObject->methodTable()->deleteProperty(baseObject, exec, jsCast<NameInstance*>(subscript.asCell())->privateName());
     else {
         LLINT_CHECK_EXCEPTION();
-        Identifier property = subscript.toString(exec)->toIdentifier(exec);
+        PropertyName property = subscript.toPropertyKey(exec);
         LLINT_CHECK_EXCEPTION();
         couldDelete = baseObject->methodTable()->deleteProperty(baseObject, exec, property);
     }
index f106d54..043a00a 100644 (file)
@@ -153,8 +153,8 @@ const SlowPutArrayStorageShape = 30
 
 # Type constants.
 const StringType = 6
-const ObjectType = 17
-const FinalObjectType = 18
+const ObjectType = 18
+const FinalObjectType = 19
 
 # Type flags constants.
 const MasqueradesAsUndefined = 1
index 569ee4f..65815cc 100644 (file)
@@ -52,6 +52,7 @@
     macro(Set)\
     macro(SetIterator)\
     macro(String) \
+    macro(Symbol) \
     macro(SyntaxError) \
     macro(TypeError) \
     macro(URIError) \
     macro(with) \
     macro(yield)
 
-#define JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(macro) \
+#define JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_WELL_KNOWN_SYMBOL(macro) \
+    macro(hasInstance) \
+    macro(isConcatSpreadable) \
     macro(iterator) \
+    macro(match) \
+    macro(replace) \
+    macro(search) \
+    macro(species) \
+    macro(split) \
+    macro(toPrimitive) \
+    macro(toStringTag) \
+    macro(unscopable)
+
+#define JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(macro) \
+    JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_WELL_KNOWN_SYMBOL(macro) \
     macro(iteratorNext) \
     macro(resolve) \
     macro(reject) \
index 08091a8..dfb9412 100644 (file)
@@ -486,11 +486,9 @@ SLOW_PATH_DECL(slow_path_del_by_val)
     uint32_t i;
     if (subscript.getUInt32(i))
         couldDelete = baseObject->methodTable()->deletePropertyByIndex(baseObject, exec, i);
-    else if (isName(subscript))
-        couldDelete = baseObject->methodTable()->deleteProperty(baseObject, exec, jsCast<NameInstance*>(subscript.asCell())->privateName());
     else {
         CHECK_EXCEPTION();
-        Identifier property = subscript.toString(exec)->toIdentifier(exec);
+        PropertyName property = subscript.toPropertyKey(exec);
         CHECK_EXCEPTION();
         couldDelete = baseObject->methodTable()->deleteProperty(baseObject, exec, property);
     }
@@ -575,7 +573,7 @@ SLOW_PATH_DECL(slow_path_get_direct_pname)
     JSValue baseValue = OP_C(2).jsValue();
     JSValue property = OP(3).jsValue();
     ASSERT(property.isString());
-    RETURN(baseValue.get(exec, property.toString(exec)->toIdentifier(exec)));
+    RETURN(baseValue.get(exec, property.toPropertyKey(exec)));
 }
 
 SLOW_PATH_DECL(slow_path_get_structure_property_enumerator)
index a56358c..bfe483d 100644 (file)
@@ -30,8 +30,8 @@
 #include "CodeSpecializationKind.h"
 #include "ExceptionHelpers.h"
 #include "JSStackInlines.h"
-#include "NameInstance.h"
 #include "StackAlignment.h"
+#include "Symbol.h"
 #include "VM.h"
 #include <wtf/StdLibExtras.h>
 
@@ -82,10 +82,7 @@ inline bool opIn(ExecState* exec, JSValue propName, JSValue baseVal)
     if (propName.getUInt32(i))
         return baseObj->hasProperty(exec, i);
 
-    if (isName(propName))
-        return baseObj->hasProperty(exec, jsCast<NameInstance*>(propName.asCell())->privateName());
-
-    Identifier property = propName.toString(exec)->toIdentifier(exec);
+    PropertyName property = propName.toPropertyKey(exec);
     if (exec->vm().exception())
         return false;
     return baseObj->hasProperty(exec, property);
index 5555395..105aaef 100644 (file)
@@ -82,7 +82,7 @@ JSObject* createStackOverflowError(JSGlobalObject* globalObject)
 JSObject* createUndefinedVariableError(ExecState* exec, const Identifier& ident)
 {
     
-    if (ident.impl()->isEmptyUnique()) {
+    if (ident.impl()->isUnique()) {
         String message(makeString("Can't find private variable: @", exec->propertyNames().getPublicName(ident).string()));
         return createReferenceError(exec, message);
     }
index c233f4c..48756ba 100644 (file)
@@ -99,8 +99,10 @@ JSValue JSValue::toThisSlowCase(ExecState* exec, ECMAMode ecmaMode) const
 JSObject* JSValue::synthesizePrototype(ExecState* exec) const
 {
     if (isCell()) {
-        ASSERT(isString());
-        return exec->lexicalGlobalObject()->stringPrototype();
+        if (isString())
+            return exec->lexicalGlobalObject()->stringPrototype();
+        ASSERT(isSymbol());
+        return exec->lexicalGlobalObject()->symbolPrototype();
     }
 
     if (isNumber())
@@ -231,7 +233,7 @@ void JSValue::dumpInContextAssumingStructure(
                     out.print(" (atomic)");
                 if (impl->isAtomic())
                     out.print(" (identifier)");
-                if (impl->isEmptyUnique())
+                if (impl->isUnique())
                     out.print(" (unique)");
             } else
                 out.print(" (unresolved)");
@@ -364,6 +366,10 @@ JSString* JSValue::toStringSlowCase(ExecState* exec) const
         return vm.smallStrings.nullString();
     if (isUndefined())
         return vm.smallStrings.undefinedString();
+    if (isSymbol()) {
+        throwTypeError(exec);
+        return jsEmptyString(exec);
+    }
 
     ASSERT(isCell());
     JSValue value = asCell()->toPrimitive(exec, PreferString);
index c1fa0d1..fa6bba5 100644 (file)
@@ -217,6 +217,7 @@ public:
     bool isMachineInt() const;
     bool isNumber() const;
     bool isString() const;
+    bool isSymbol() const;
     bool isPrimitive() const;
     bool isGetterSetter() const;
     bool isCustomGetterSetter() const;
@@ -242,6 +243,7 @@ public:
     // been set in the ExecState already.
     double toNumber(ExecState*) const;
     JSString* toString(ExecState*) const;
+    PropertyName toPropertyKey(ExecState*) const;
     WTF::String toWTFString(ExecState*) const;
     WTF::String toWTFStringInline(ExecState*) const;
     JSObject* toObject(ExecState*) const;
index 1510b41..d876dbe 100644 (file)
@@ -26,6 +26,7 @@
 #ifndef JSValueInlines_h
 #define JSValueInlines_h
 
+#include "Identifier.h"
 #include "InternalFunction.h"
 #include "JSCJSValue.h"
 #include "JSCellInlines.h"
@@ -549,9 +550,14 @@ inline bool JSValue::isString() const
     return isCell() && asCell()->isString();
 }
 
+inline bool JSValue::isSymbol() const
+{
+    return isCell() && asCell()->isSymbol();
+}
+
 inline bool JSValue::isPrimitive() const
 {
-    return !isCell() || asCell()->isString();
+    return !isCell() || asCell()->isString() || asCell()->isSymbol();
 }
 
 inline bool JSValue::isGetterSetter() const
@@ -604,6 +610,17 @@ ALWAYS_INLINE bool JSValue::getUInt32(uint32_t& v) const
     return false;
 }
 
+ALWAYS_INLINE PropertyName JSValue::toPropertyKey(ExecState* exec) const
+{
+    if (isString())
+        return asString(*this)->toIdentifier(exec);
+
+    JSValue primitive = toPrimitive(exec, PreferString);
+    if (primitive.isSymbol())
+        return asSymbol(primitive)->privateName();
+    return primitive.toString(exec)->toIdentifier(exec);
+}
+
 inline JSValue JSValue::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
 {
     return isCell() ? asCell()->toPrimitive(exec, preferredType) : asValue();
@@ -692,7 +709,7 @@ ALWAYS_INLINE bool JSValue::getPropertySlot(ExecState* exec, PropertyName proper
     // and if it's a string there are special properties to check first.
     JSObject* object;
     if (UNLIKELY(!isObject())) {
-        if (isCell() && asString(*this)->getStringPropertySlot(exec, propertyName, slot))
+        if (isString() && asString(*this)->getStringPropertySlot(exec, propertyName, slot))
             return true;
         object = synthesizePrototype(exec);
     } else
@@ -713,7 +730,7 @@ ALWAYS_INLINE JSValue JSValue::get(ExecState* exec, unsigned propertyName, Prope
     // and if it's a string there are special properties to check first.
     JSObject* object;
     if (UNLIKELY(!isObject())) {
-        if (isCell() && asString(*this)->getStringPropertySlot(exec, propertyName, slot))
+        if (isString() && asString(*this)->getStringPropertySlot(exec, propertyName, slot))
             return slot.getValue(exec, propertyName);
         object = synthesizePrototype(exec);
     } else
@@ -806,6 +823,14 @@ ALWAYS_INLINE bool JSValue::equalSlowCaseInline(ExecState* exec, JSValue v1, JSV
             continue;
         }
 
+        bool sym1 = v1.isSymbol();
+        bool sym2 = v2.isSymbol();
+        if (sym1 || sym2) {
+            if (sym1 && sym2)
+                return asSymbol(v1)->privateName() == asSymbol(v2)->privateName();
+            return false;
+        }
+
         if (s1 || s2) {
             double d1 = v1.toNumber(exec);
             double d2 = v2.toNumber(exec);
@@ -831,6 +856,8 @@ ALWAYS_INLINE bool JSValue::strictEqualSlowCaseInline(ExecState* exec, JSValue v
 
     if (v1.asCell()->isString() && v2.asCell()->isString())
         return WTF::equal(*asString(v1)->value(exec).impl(), *asString(v2)->value(exec).impl());
+    if (v1.asCell()->isSymbol() && v2.asCell()->isSymbol())
+        return asSymbol(v1)->privateName() == asSymbol(v2)->privateName();
 
     return v1 == v2;
 }
index 694081d..2c403c8 100644 (file)
@@ -96,7 +96,7 @@ ConstructType JSCell::getConstructData(JSCell*, ConstructData& constructData)
 
 void JSCell::put(JSCell* cell, ExecState* exec, PropertyName identifier, JSValue value, PutPropertySlot& slot)
 {
-    if (cell->isString()) {
+    if (cell->isString() || cell->isSymbol()) {
         JSValue(cell).putToPrimitive(exec, identifier, value, slot);
         return;
     }
@@ -106,7 +106,7 @@ void JSCell::put(JSCell* cell, ExecState* exec, PropertyName identifier, JSValue
 
 void JSCell::putByIndex(JSCell* cell, ExecState* exec, unsigned identifier, JSValue value, bool shouldThrow)
 {
-    if (cell->isString()) {
+    if (cell->isString() || cell->isSymbol()) {
         PutPropertySlot slot(cell, shouldThrow);
         JSValue(cell).putToPrimitive(exec, Identifier::from(exec, identifier), value, slot);
         return;
@@ -138,6 +138,8 @@ JSValue JSCell::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredTyp
 {
     if (isString())
         return static_cast<const JSString*>(this)->toPrimitive(exec, preferredType);
+    if (isSymbol())
+        return static_cast<const Symbol*>(this)->toPrimitive(exec, preferredType);
     return static_cast<const JSObject*>(this)->toPrimitive(exec, preferredType);
 }
 
@@ -145,6 +147,8 @@ bool JSCell::getPrimitiveNumber(ExecState* exec, double& number, JSValue& value)
 {
     if (isString())
         return static_cast<const JSString*>(this)->getPrimitiveNumber(exec, number, value);
+    if (isSymbol())
+        return static_cast<const Symbol*>(this)->getPrimitiveNumber(exec, number, value);
     return static_cast<const JSObject*>(this)->getPrimitiveNumber(exec, number, value);
 }
 
@@ -152,6 +156,8 @@ double JSCell::toNumber(ExecState* exec) const
 { 
     if (isString())
         return static_cast<const JSString*>(this)->toNumber(exec);
+    if (isSymbol())
+        return static_cast<const Symbol*>(this)->toNumber(exec);
     return static_cast<const JSObject*>(this)->toNumber(exec);
 }
 
@@ -159,6 +165,8 @@ JSObject* JSCell::toObject(ExecState* exec, JSGlobalObject* globalObject) const
 {
     if (isString())
         return static_cast<const JSString*>(this)->toObject(exec, globalObject);
+    if (isSymbol())
+        return static_cast<const Symbol*>(this)->toObject(exec, globalObject);
     ASSERT(isObject());
     return jsCast<JSObject*>(const_cast<JSCell*>(this));
 }
index f57a5c8..4839f64 100644 (file)
@@ -85,6 +85,7 @@ protected:
 public:
     // Querying the type.
     bool isString() const;
+    bool isSymbol() const;
     bool isObject() const;
     bool isGetterSetter() const;
     bool isCustomGetterSetter() const;
index 151ae77..b2fa406 100644 (file)
@@ -35,6 +35,7 @@
 #include "JSString.h"
 #include "MarkedBlock.h"
 #include "Structure.h"
+#include "Symbol.h"
 #include <wtf/CompilationThread.h>
 
 namespace JSC {
@@ -164,6 +165,11 @@ inline bool JSCell::isString() const
     return m_type == StringType;
 }
 
+inline bool JSCell::isSymbol() const
+{
+    return m_type == SymbolType;
+}
+
 inline bool JSCell::isGetterSetter() const
 {
     return m_type == GetterSetterType;
@@ -247,15 +253,19 @@ inline const ClassInfo* JSCell::classInfo() const
 
 inline bool JSCell::toBoolean(ExecState* exec) const
 {
-    if (isString()) 
+    if (isString())
         return static_cast<const JSString*>(this)->toBoolean();
+    if (isSymbol())
+        return static_cast<const Symbol*>(this)->toBoolean();
     return !structure()->masqueradesAsUndefined(exec->lexicalGlobalObject());
 }
 
 inline TriState JSCell::pureToBoolean() const
 {
-    if (isString()) 
+    if (isString())
         return static_cast<const JSString*>(this)->toBoolean() ? TrueTriState : FalseTriState;
+    if (isSymbol())
+        return static_cast<const Symbol*>(this)->toBoolean() ? TrueTriState : FalseTriState;
     return MixedTriState;
 }
 
index 8312c00..82f5f9d 100644 (file)
@@ -94,9 +94,6 @@
 #include "MapPrototype.h"
 #include "MathObject.h"
 #include "Microtask.h"
-#include "NameConstructor.h"
-#include "NameInstance.h"
-#include "NamePrototype.h"
 #include "NativeErrorConstructor.h"
 #include "NativeErrorPrototype.h"
 #include "NullGetterFunction.h"
 #include "StrictEvalActivation.h"
 #include "StringConstructor.h"
 #include "StringPrototype.h"
+#include "Symbol.h"
+#include "SymbolConstructor.h"
+#include "SymbolPrototype.h"
 #include "VariableWatchpointSetInlines.h"
 #include "WeakMapConstructor.h"
 #include "WeakMapPrototype.h"
@@ -425,15 +425,6 @@ putDirectWithoutTransition(vm, vm.propertyNames-> jsName, lowerName ## Construct
     JSConsole* consoleObject = JSConsole::create(vm, m_consoleStructure.get());
     putDirectWithoutTransition(vm, Identifier(exec, "console"), consoleObject, DontEnum);
     
-    if (m_experimentsEnabled) {
-        NamePrototype* privateNamePrototype = NamePrototype::create(exec, NamePrototype::createStructure(vm, this, m_objectPrototype.get()));
-        m_privateNameStructure.set(vm, this, NameInstance::createStructure(vm, this, privateNamePrototype));
-        
-        JSCell* privateNameConstructor = NameConstructor::create(vm, NameConstructor::createStructure(vm, this, m_functionPrototype.get()), privateNamePrototype);
-        privateNamePrototype->putDirectWithoutTransition(vm, vm.propertyNames->constructor, privateNameConstructor, DontEnum);
-        putDirectWithoutTransition(vm, Identifier(exec, "Name"), privateNameConstructor, DontEnum);
-    }
-    
     resetPrototype(vm, prototype());
 }
 
@@ -695,7 +686,7 @@ void JSGlobalObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
     visitor.append(&thisObject->m_functionStructure);
     visitor.append(&thisObject->m_boundFunctionStructure);
     visitor.append(&thisObject->m_namedFunctionStructure);
-    visitor.append(&thisObject->m_privateNameStructure);
+    visitor.append(&thisObject->m_symbolObjectStructure);
     visitor.append(&thisObject->m_regExpMatchesArrayStructure);
     visitor.append(&thisObject->m_regExpStructure);
     visitor.append(&thisObject->m_consoleStructure);
index d1d4497..9f504f7 100644 (file)
@@ -35,6 +35,7 @@
 #include "StringPrototype.h"
 #include "StructureChain.h"
 #include "StructureRareDataInlines.h"
+#include "SymbolPrototype.h"
 #include "VM.h"
 #include "Watchpoint.h"
 #include <JavaScriptCore/JSBase.h>
@@ -91,6 +92,7 @@ struct HashTable;
     macro(Map, map, map, JSMap, Map) \
     macro(Date, date, date, DateInstance, Date) \
     macro(String, string, stringObject, StringObject, String) \
+    macro(Symbol, symbol, symbolObject, SymbolObject, Symbol) \
     macro(Boolean, boolean, booleanObject, BooleanObject, Boolean) \
     macro(Number, number, numberObject, NumberObject, Number) \
     macro(Error, error, error, ErrorInstance, Error) \
@@ -393,6 +395,7 @@ public:
     ArrayPrototype* arrayPrototype() const { return m_arrayPrototype.get(); }
     BooleanPrototype* booleanPrototype() const { return m_booleanPrototype.get(); }
     StringPrototype* stringPrototype() const { return m_stringPrototype.get(); }
+    SymbolPrototype* symbolPrototype() const { return m_symbolPrototype.get(); }
     NumberPrototype* numberPrototype() const { return m_numberPrototype.get(); }
     DatePrototype* datePrototype() const { return m_datePrototype.get(); }
     RegExpPrototype* regExpPrototype() const { return m_regExpPrototype.get(); }
@@ -451,6 +454,7 @@ public:
     Structure* regExpStructure() const { return m_regExpStructure.get(); }
     Structure* setStructure() const { return m_setStructure.get(); }
     Structure* stringObjectStructure() const { return m_stringObjectStructure.get(); }
+    Structure* symbolObjectStructure() const { return m_symbolObjectStructure.get(); }
     Structure* iteratorResultStructure() const { return m_iteratorResultStructure.get(); }
     static ptrdiff_t iteratorResultStructureOffset() { return OBJECT_OFFSETOF(JSGlobalObject, m_iteratorResultStructure); }
 
index 4974e88..990743a 100644 (file)
@@ -226,7 +226,8 @@ Stringifier::Stringifier(ExecState* exec, const Local<Unknown>& replacer, const
             if (name.isObject()) {
                 if (!asObject(name)->inherits(NumberObject::info()) && !asObject(name)->inherits(StringObject::info()))
                     continue;
-            }
+            } else if (!name.isNumber() && !name.isString())
+                continue;
 
             m_arrayReplacerPropertyNames.add(name.toString(exec)->toIdentifier(exec));
         }
index 38d8b7f..b8fb228 100644 (file)
@@ -61,7 +61,7 @@ void JSSymbolTableObject::getOwnNonIndexPropertyNames(JSObject* object, ExecStat
         ConcurrentJITLocker locker(thisObject->symbolTable()->m_lock);
         SymbolTable::Map::iterator end = thisObject->symbolTable()->end(locker);
         for (SymbolTable::Map::iterator it = thisObject->symbolTable()->begin(locker); it != end; ++it) {
-            if (it->key->isEmptyUnique())
+            if (it->key->isUnique())
                 continue;
             if (!(it->value.getAttributes() & DontEnum) || shouldIncludeDontEnumProperties(mode))
                 propertyNames.add(Identifier(exec, it->key.get()));
index ab14172..f86b54c 100644 (file)
@@ -33,6 +33,7 @@ enum JSType : uint8_t {
     // The CellType value must come before any JSType that is a JSCell.
     CellType,
     StringType,
+    SymbolType,
 
     GetterSetterType,
     CustomGetterSetterType,
@@ -52,7 +53,6 @@ enum JSType : uint8_t {
     FinalObjectType,
     JSCalleeType,
     JSFunctionType,
-    NameInstanceType,
     NumberObjectType,
     ErrorInstanceType,
     PureForwardingProxyType,
index 49118f3..f695968 100644 (file)
@@ -77,7 +77,6 @@ public:
     static bool isObject(JSType type) { return type >= ObjectType; }
     bool isFinalObject() const { return type() == FinalObjectType; }
     bool isNumberObject() const { return type() == NumberObjectType; }
-    bool isName() const { return type() == NameInstanceType; }
 
     unsigned flags() const { return (static_cast<unsigned>(m_flags2) << 8) | static_cast<unsigned>(m_flags); }
     bool masqueradesAsUndefined() const { return isSetOnFlags1(MasqueradesAsUndefined); }
index d7ca294..b05691c 100644 (file)
@@ -60,6 +60,12 @@ MapData::Entry* MapData::find(CallFrame* callFrame, KeyType key)
             return 0;
         return &m_entries[iter->value];
     }
+    if (key.value.isSymbol()) {
+        auto iter = m_symbolKeyedTable.find(asSymbol(key.value)->privateName().uid());
+        if (iter == m_symbolKeyedTable.end())
+            return 0;
+        return &m_entries[iter->value];
+    }
     if (key.value.isCell()) {
         auto iter = m_cellKeyedTable.find(key.value.asCell());
         if (iter == m_cellKeyedTable.end())
@@ -107,6 +113,8 @@ MapData::Entry* MapData::add(CallFrame* callFrame, KeyType key)
 {
     if (key.value.isString())
         return add(callFrame, m_stringKeyedTable, asString(key.value)->value(callFrame).impl(), key);
+    if (key.value.isSymbol())
+        return add(callFrame, m_symbolKeyedTable, asSymbol(key.value)->privateName().uid(), key);
     if (key.value.isCell())
         return add(callFrame, m_cellKeyedTable, key.value.asCell(), key);
     return add(callFrame, m_valueKeyedTable, JSValue::encode(key.value), key);
@@ -128,6 +136,12 @@ bool MapData::remove(CallFrame* callFrame, KeyType key)
             return false;
         location = iter->value;
         m_stringKeyedTable.remove(iter);
+    }  else if (key.value.isSymbol()) {
+        auto iter = m_symbolKeyedTable.find(asSymbol(key.value)->privateName().uid());
+        if (iter == m_symbolKeyedTable.end())
+            return false;
+        location = iter->value;
+        m_symbolKeyedTable.remove(iter);
     } else if (key.value.isCell()) {
         auto iter = m_cellKeyedTable.find(key.value.asCell());
         if (iter == m_cellKeyedTable.end())
@@ -173,6 +187,8 @@ void MapData::replaceAndPackBackingStore(Entry* destination, int32_t newCapacity
         ptr->value = m_entries[ptr->value].value.get().asInt32();
     for (auto ptr = m_stringKeyedTable.begin(); ptr != m_stringKeyedTable.end(); ++ptr)
         ptr->value = m_entries[ptr->value].value.get().asInt32();
+    for (auto ptr = m_symbolKeyedTable.begin(); ptr != m_symbolKeyedTable.end(); ++ptr)
+        ptr->value = m_entries[ptr->value].value.get().asInt32();
 
     ASSERT((m_size - newEnd) == m_deletedCount);
     m_deletedCount = 0;
index c0504a6..b1d5306 100644 (file)
@@ -112,6 +112,7 @@ private:
     typedef HashMap<JSCell*, int32_t, typename WTF::DefaultHash<JSCell*>::Hash, WTF::HashTraits<JSCell*>, IndexTraits> CellKeyedMap;
     typedef HashMap<EncodedJSValue, int32_t, EncodedJSValueHash, EncodedJSValueHashTraits, IndexTraits> ValueKeyedMap;
     typedef HashMap<StringImpl*, int32_t, typename WTF::DefaultHash<StringImpl*>::Hash, WTF::HashTraits<StringImpl*>, IndexTraits> StringKeyedMap;
+    typedef HashMap<AtomicStringImpl*, int32_t, typename WTF::DefaultHash<AtomicStringImpl*>::Hash, WTF::HashTraits<AtomicStringImpl*>, IndexTraits> SymbolKeyedMap;
 
     size_t capacityInBytes() { return m_capacity * sizeof(Entry); }
 
@@ -134,6 +135,7 @@ private:
     CellKeyedMap m_cellKeyedTable;
     ValueKeyedMap m_valueKeyedTable;
     StringKeyedMap m_stringKeyedTable;
+    SymbolKeyedMap m_symbolKeyedTable;
     int32_t m_capacity;
     int32_t m_size;
     int32_t m_deletedCount;
@@ -146,6 +148,7 @@ ALWAYS_INLINE void MapData::clear()
     m_cellKeyedTable.clear();
     m_valueKeyedTable.clear();
     m_stringKeyedTable.clear();
+    m_symbolKeyedTable.clear();
     m_capacity = 0;
     m_size = 0;
     m_deletedCount = 0;
diff --git a/Source/JavaScriptCore/runtime/NameInstance.h b/Source/JavaScriptCore/runtime/NameInstance.h
deleted file mode 100644 (file)
index 55842d5..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef NameInstance_h
-#define NameInstance_h
-
-#include "JSDestructibleObject.h"
-#include "PrivateName.h"
-
-namespace JSC {
-
-class NameInstance : public JSDestructibleObject {
-public:
-    typedef JSDestructibleObject Base;
-
-    DECLARE_INFO;
-
-    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
-    {
-        return Structure::create(vm, globalObject, prototype, TypeInfo(NameInstanceType, StructureFlags), info());
-    }
-
-    static NameInstance* create(VM& vm, Structure* structure, JSString* nameString)
-    {
-        NameInstance* name = new (NotNull, allocateCell<NameInstance>(vm.heap)) NameInstance(vm, structure, nameString);
-        name->finishCreation(vm);
-        return name;
-    }
-
-    const PrivateName& privateName() { return m_privateName; }
-    JSString* nameString() { return m_nameString.get(); }
-
-protected:
-    static void destroy(JSCell*);
-
-    NameInstance(VM&, Structure*, JSString*);
-
-    void finishCreation(VM& vm)
-    {
-        Base::finishCreation(vm);
-        ASSERT(inherits(info()));
-    }
-
-    PrivateName m_privateName;
-    WriteBarrier<JSString> m_nameString;
-};
-
-inline bool isName(JSValue v)
-{
-    return v.isCell() && v.asCell()->type() == NameInstanceType;
-}
-
-} // namespace JSC
-
-#endif // NameInstance_h
diff --git a/Source/JavaScriptCore/runtime/NamePrototype.cpp b/Source/JavaScriptCore/runtime/NamePrototype.cpp
deleted file mode 100644 (file)
index bf08d9a..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "NamePrototype.h"
-
-#include "Error.h"
-#include "JSCInlines.h"
-
-namespace JSC {
-
-static EncodedJSValue JSC_HOST_CALL privateNameProtoFuncToString(ExecState*);
-
-}
-
-#include "NamePrototype.lut.h"
-
-namespace JSC {
-
-const ClassInfo NamePrototype::s_info = { "Name", &Base::s_info, &privateNamePrototypeTable, CREATE_METHOD_TABLE(NamePrototype) };
-
-/* Source for NamePrototype.lut.h
-@begin privateNamePrototypeTable
-  toString          privateNameProtoFuncToString         DontEnum|Function 0
-@end
-*/
-
-NamePrototype::NamePrototype(ExecState* exec, Structure* structure)
-    : Base(exec->vm(), structure, jsEmptyString(exec))
-{
-}
-
-void NamePrototype::finishCreation(VM& vm)
-{
-    Base::finishCreation(vm);
-    ASSERT(inherits(info()));
-}
-
-bool NamePrototype::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot &slot)
-{
-    return getStaticFunctionSlot<Base>(exec, privateNamePrototypeTable, jsCast<NamePrototype*>(object), propertyName, slot);
-}
-
-// ------------------------------ Functions ---------------------------
-
-EncodedJSValue JSC_HOST_CALL privateNameProtoFuncToString(ExecState* exec)
-{
-    JSValue thisValue = exec->thisValue();
-    if (!thisValue.isObject())
-        return throwVMTypeError(exec);
-
-    JSObject* thisObject = asObject(thisValue);
-    if (!thisObject->inherits(NameInstance::info()))
-        return throwVMTypeError(exec);
-
-    return JSValue::encode(jsCast<NameInstance*>(thisObject)->nameString());
-}
-
-} // namespace JSC
index a87a4fc..602e575 100644 (file)
@@ -173,7 +173,7 @@ EncodedJSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState
 {
     if (!exec->argument(0).isObject())
         return throwVMError(exec, createTypeError(exec, ASCIILiteral("Requested property descriptor of a value that is not an object.")));
-    Identifier propertyName = exec->argument(1).toString(exec)->toIdentifier(exec);
+    PropertyName propertyName = exec->argument(1).toPropertyKey(exec);
     if (exec->hadException())
         return JSValue::encode(jsNull());
     JSObject* object = asObject(exec->argument(0));
@@ -316,7 +316,7 @@ EncodedJSValue JSC_HOST_CALL objectConstructorDefineProperty(ExecState* exec)
     if (!exec->argument(0).isObject())
         return throwVMError(exec, createTypeError(exec, ASCIILiteral("Properties can only be defined on Objects.")));
     JSObject* O = asObject(exec->argument(0));
-    Identifier propertyName = exec->argument(1).toString(exec)->toIdentifier(exec);
+    PropertyName propertyName = exec->argument(1).toPropertyKey(exec);
     if (exec->hadException())
         return JSValue::encode(jsNull());
     PropertyDescriptor descriptor;
index 33b4420..a74b2a5 100644 (file)
@@ -85,7 +85,7 @@ EncodedJSValue JSC_HOST_CALL objectProtoFuncValueOf(ExecState* exec)
 EncodedJSValue JSC_HOST_CALL objectProtoFuncHasOwnProperty(ExecState* exec)
 {
     JSValue thisValue = exec->thisValue().toThis(exec, StrictMode);
-    return JSValue::encode(jsBoolean(thisValue.toObject(exec)->hasOwnProperty(exec, exec->argument(0).toString(exec)->toIdentifier(exec))));
+    return JSValue::encode(jsBoolean(thisValue.toObject(exec)->hasOwnProperty(exec, exec->argument(0).toPropertyKey(exec))));
 }
 
 EncodedJSValue JSC_HOST_CALL objectProtoFuncIsPrototypeOf(ExecState* exec)
@@ -122,7 +122,7 @@ EncodedJSValue JSC_HOST_CALL objectProtoFuncDefineGetter(ExecState* exec)
     descriptor.setGetter(get);
     descriptor.setEnumerable(true);
     descriptor.setConfigurable(true);
-    thisObject->methodTable(exec->vm())->defineOwnProperty(thisObject, exec, exec->argument(0).toString(exec)->toIdentifier(exec), descriptor, false);
+    thisObject->methodTable(exec->vm())->defineOwnProperty(thisObject, exec, exec->argument(0).toPropertyKey(exec), descriptor, false);
 
     return JSValue::encode(jsUndefined());
 }
@@ -142,7 +142,7 @@ EncodedJSValue JSC_HOST_CALL objectProtoFuncDefineSetter(ExecState* exec)
     descriptor.setSetter(set);
     descriptor.setEnumerable(true);
     descriptor.setConfigurable(true);
-    thisObject->methodTable(exec->vm())->defineOwnProperty(thisObject, exec, exec->argument(0).toString(exec)->toIdentifier(exec), descriptor, false);
+    thisObject->methodTable(exec->vm())->defineOwnProperty(thisObject, exec, exec->argument(0).toPropertyKey(exec), descriptor, false);
 
     return JSValue::encode(jsUndefined());
 }
@@ -154,7 +154,7 @@ EncodedJSValue JSC_HOST_CALL objectProtoFuncLookupGetter(ExecState* exec)
         return JSValue::encode(jsUndefined());
 
     PropertySlot slot(thisObject);
-    if (thisObject->getPropertySlot(exec, exec->argument(0).toString(exec)->toIdentifier(exec), slot)
+    if (thisObject->getPropertySlot(exec, exec->argument(0).toPropertyKey(exec), slot)
         && slot.isAccessor()) {
         GetterSetter* getterSetter = slot.getterSetter();
         return getterSetter->isGetterNull() ? JSValue::encode(jsUndefined()) : JSValue::encode(getterSetter->getter());
@@ -170,7 +170,7 @@ EncodedJSValue JSC_HOST_CALL objectProtoFuncLookupSetter(ExecState* exec)
         return JSValue::encode(jsUndefined());
 
     PropertySlot slot(thisObject);
-    if (thisObject->getPropertySlot(exec, exec->argument(0).toString(exec)->toIdentifier(exec), slot)
+    if (thisObject->getPropertySlot(exec, exec->argument(0).toPropertyKey(exec), slot)
         && slot.isAccessor()) {
         GetterSetter* getterSetter = slot.getterSetter();
         return getterSetter->isSetterNull() ? JSValue::encode(jsUndefined()) : JSValue::encode(getterSetter->setter());
@@ -182,7 +182,7 @@ EncodedJSValue JSC_HOST_CALL objectProtoFuncLookupSetter(ExecState* exec)
 EncodedJSValue JSC_HOST_CALL objectProtoFuncPropertyIsEnumerable(ExecState* exec)
 {
     JSObject* thisObject = exec->thisValue().toThis(exec, StrictMode).toObject(exec);
-    Identifier propertyName = exec->argument(0).toString(exec)->toIdentifier(exec);
+    PropertyName propertyName = exec->argument(0).toPropertyKey(exec);
 
     PropertyDescriptor descriptor;
     bool enumerable = thisObject->getOwnPropertyDescriptor(exec, propertyName, descriptor) && descriptor.enumerable();
index 36d832f..0c9ccb6 100644 (file)
@@ -65,6 +65,8 @@ JSValue jsTypeStringForValue(VM& vm, JSGlobalObject* globalObject, JSValue v)
         return vm.smallStrings.numberString();
     if (v.isString())
         return vm.smallStrings.stringString();
+    if (v.isSymbol())
+        return vm.smallStrings.symbolString();
     if (v.isObject()) {
         // Return "undefined" for objects that should be treated
         // as null when doing comparisons.
@@ -89,7 +91,7 @@ bool jsIsObjectType(CallFrame* callFrame, JSValue v)
         return v.isNull();
 
     JSType type = v.asCell()->type();
-    if (type == StringType)
+    if (type == StringType || type == SymbolType)
         return false;
     if (type >= ObjectType) {
         if (asObject(v)->structure(callFrame->vm())->masqueradesAsUndefined(callFrame->lexicalGlobalObject()))
index 55ee634..2141644 100644 (file)
@@ -33,17 +33,26 @@ namespace JSC {
 class PrivateName {
 public:
     PrivateName()
-        : m_impl(StringImpl::createEmptyUnique())
+        : m_impl(StringImpl::createUniqueEmpty())
     {
+        ASSERT(m_impl->isUnique());
+    }
+    PrivateName(const String& description)
+        : m_impl(StringImpl::createUnique(description.impl()))
+    {
+        ASSERT(m_impl->isUnique());
     }
     explicit PrivateName(StringImpl* uid)
         : m_impl(uid)
     {
-        ASSERT(m_impl->isEmptyUnique());
+        ASSERT(m_impl->isUnique());
     }
 
     AtomicStringImpl* uid() const { return static_cast<AtomicStringImpl*>(m_impl.get()); }
 
+    bool operator==(const PrivateName& other) const { return uid() == other.uid(); }
+    bool operator!=(const PrivateName& other) const { return uid() != other.uid(); }
+
 private:
     RefPtr<StringImpl> m_impl;
 };
index d7334c0..0370a35 100644 (file)
@@ -271,7 +271,7 @@ inline PropertyTable::const_iterator PropertyTable::end() const
 inline PropertyTable::find_iterator PropertyTable::find(const KeyType& key)
 {
     ASSERT(key);
-    ASSERT(key->isAtomic() || key->isEmptyUnique());
+    ASSERT(key->isAtomic() || key->isUnique());
     unsigned hash = key->existingHash();
     unsigned step = 0;
 
@@ -305,7 +305,7 @@ inline PropertyTable::find_iterator PropertyTable::find(const KeyType& key)
 inline PropertyTable::ValueType* PropertyTable::get(const KeyType& key)
 {
     ASSERT(key);
-    ASSERT(key->isAtomic() || key->isEmptyUnique());
+    ASSERT(key->isAtomic() || key->isUnique());
 
     if (!m_keyCount)
         return nullptr;
index 22a8ff8..3074c72 100644 (file)
@@ -93,7 +93,7 @@ public:
         : m_impl(static_cast<AtomicStringImpl*>(propertyName.uid()))
     {
         ASSERT(m_impl);
-        ASSERT(m_impl->isEmptyUnique());
+        ASSERT(m_impl->isUnique());
         ASSERT(m_impl->isAtomic());
     }
 
@@ -104,7 +104,7 @@ public:
 
     AtomicStringImpl* publicName() const
     {
-        return m_impl->isEmptyUnique() ? nullptr : m_impl;
+        return m_impl->isUnique() ? nullptr : m_impl;
     }
 
     static const uint32_t NotAnIndex = UINT_MAX;
index 31b39f0..fd2b76a 100644 (file)
@@ -38,6 +38,7 @@
     macro(object) \
     macro(undefined) \
     macro(string) \
+    macro(symbol) \
     macro(true)
 
 namespace WTF {
index 4bae904..becacbe 100644 (file)
@@ -110,7 +110,10 @@ static EncodedJSValue JSC_HOST_CALL callStringConstructor(ExecState* exec)
 {
     if (!exec->argumentCount())
         return JSValue::encode(jsEmptyString(exec));
-    return JSValue::encode(exec->uncheckedArgument(0).toString(exec));
+    JSValue argument = exec->uncheckedArgument(0);
+    if (argument.isSymbol())
+        return JSValue::encode(jsString(exec, asSymbol(argument)->descriptiveString()));
+    return JSValue::encode(argument.toString(exec));
 }
 
 CallType StringConstructor::getCallData(JSCell*, CallData& callData)
index 86d0b6f..3fcb426 100644 (file)
@@ -947,7 +947,7 @@ void Structure::getPropertyNamesFromStructure(VM& vm, PropertyNameArray& propert
     PropertyTable::iterator end = propertyTable()->end();
     for (PropertyTable::iterator iter = propertyTable()->begin(); iter != end; ++iter) {
         ASSERT(hasNonEnumerableProperties() || !(iter->attributes & DontEnum));
-        if (!iter->key->isEmptyUnique() && (!(iter->attributes & DontEnum) || shouldIncludeDontEnumProperties(mode))) {
+        if (!iter->key->isUnique() && (!(iter->attributes & DontEnum) || shouldIncludeDontEnumProperties(mode))) {
             if (knownUnique)
                 propertyNames.addKnownUnique(iter->key);
             else
index 269292b..f17bc1b 100644 (file)
@@ -168,6 +168,8 @@ inline JSValue Structure::prototypeForLookup(JSGlobalObject* globalObject) const
 {
     if (isObject())
         return m_prototype.get();
+    if (typeInfo().type() == SymbolType)
+        return globalObject->symbolPrototype();
 
     ASSERT(typeInfo().type() == StringType);
     return globalObject->stringPrototype();
diff --git a/Source/JavaScriptCore/runtime/Symbol.cpp b/Source/JavaScriptCore/runtime/Symbol.cpp
new file mode 100644 (file)
index 0000000..294f67e
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Symbol.h"
+
+#include "Error.h"
+#include "JSCInlines.h"
+#include "SymbolObject.h"
+
+namespace JSC {
+
+const ClassInfo Symbol::s_info = { "symbol", nullptr, nullptr, CREATE_METHOD_TABLE(Symbol) };
+
+Symbol::Symbol(VM& vm)
+    : Base(vm, vm.symbolStructure.get())
+    , m_privateName()
+{
+}
+
+Symbol::Symbol(VM& vm, const String& string)
+    : Base(vm, vm.symbolStructure.get())
+    , m_privateName(string)
+{
+}
+
+Symbol::Symbol(VM& vm, AtomicStringImpl* uid)
+    : Base(vm, vm.symbolStructure.get())
+    , m_privateName(uid)
+{
+}
+
+inline SymbolObject* SymbolObject::create(VM& vm, JSGlobalObject* globalObject, Symbol* symbol)
+{
+    SymbolObject* object = new (NotNull, allocateCell<SymbolObject>(vm.heap)) SymbolObject(vm, globalObject->symbolObjectStructure());
+    object->finishCreation(vm, symbol);
+    return object;
+}
+
+JSValue Symbol::toPrimitive(ExecState*, PreferredPrimitiveType) const
+{
+    return const_cast<Symbol*>(this);
+}
+
+bool Symbol::toBoolean() const
+{
+    return true;
+}
+
+bool Symbol::getPrimitiveNumber(ExecState* exec, double& number, JSValue& result) const
+{
+    result = this;
+    number = toNumber(exec);
+    return true;
+}
+
+JSObject* Symbol::toObject(ExecState* exec, JSGlobalObject* globalObject) const
+{
+    return SymbolObject::create(exec->vm(), globalObject, const_cast<Symbol*>(this));
+}
+
+double Symbol::toNumber(ExecState* exec) const
+{
+    throwTypeError(exec);
+    return 0.0;
+}
+
+void Symbol::destroy(JSCell* cell)
+{
+    static_cast<Symbol*>(cell)->Symbol::~Symbol();
+}
+
+String Symbol::descriptiveString() const
+{
+    StringBuilder builder;
+    builder.appendLiteral("Symbol(");
+    builder.append(privateName().uid());
+    builder.append(')');
+    return builder.toString();
+}
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/Symbol.h b/Source/JavaScriptCore/runtime/Symbol.h
new file mode 100644 (file)
index 0000000..27b01fc
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Symbol_h
+#define Symbol_h
+
+#include "JSCell.h"
+#include "JSString.h"
+#include "PrivateName.h"
+
+namespace JSC {
+
+class Symbol : public JSCell {
+public:
+    typedef JSCell Base;
+
+    DECLARE_EXPORT_INFO;
+
+    static const bool needsDestruction = true;
+    static const bool hasImmortalStructure = true;
+
+    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+    {
+        return Structure::create(vm, globalObject, prototype, TypeInfo(SymbolType, StructureFlags), info());
+    }
+
+    static Symbol* create(VM& vm)
+    {
+        Symbol* symbol = new (NotNull, allocateCell<Symbol>(vm.heap)) Symbol(vm);
+        symbol->finishCreation(vm);
+        return symbol;
+    }
+
+    static Symbol* create(ExecState* exec, JSString* description)
+    {
+        VM& vm = exec->vm();
+        String desc = description->value(exec);
+        Symbol* symbol = new (NotNull, allocateCell<Symbol>(vm.heap)) Symbol(vm, desc);
+        symbol->finishCreation(vm);
+        return symbol;
+    }
+
+    static Symbol* create(VM& vm, AtomicStringImpl* uid)
+    {
+        Symbol* symbol = new (NotNull, allocateCell<Symbol>(vm.heap)) Symbol(vm, uid);
+        symbol->finishCreation(vm);
+        return symbol;
+    }
+
+    const PrivateName& privateName() const { return m_privateName; }
+    String descriptiveString() const;
+
+    JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
+    JS_EXPORT_PRIVATE bool toBoolean() const;
+    bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const;
+    JSObject* toObject(ExecState*, JSGlobalObject*) const;
+    double toNumber(ExecState*) const;
+
+protected:
+    static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | StructureIsImmortal;
+
+    static void destroy(JSCell*);
+
+    Symbol(VM&);
+    Symbol(VM&, const String&);
+    Symbol(VM&, AtomicStringImpl* uid);
+
+    void finishCreation(VM& vm)
+    {
+        Base::finishCreation(vm);
+        ASSERT(inherits(info()));
+    }
+
+    PrivateName m_privateName;
+};
+
+Symbol* asSymbol(JSValue);
+
+inline Symbol* asSymbol(JSValue value)
+{
+    ASSERT(value.asCell()->isSymbol());
+    return jsCast<Symbol*>(value.asCell());
+}
+
+} // namespace JSC
+
+#endif // Symbol_h
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  */
 
 #include "config.h"
-#include "NameConstructor.h"
+#include "SymbolConstructor.h"
 
-#include "JSGlobalObject.h"
-#include "NamePrototype.h"
+#include "Error.h"
 #include "JSCInlines.h"
+#include "JSGlobalObject.h"
+#include "SymbolPrototype.h"
 
 namespace JSC {
 
-STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(NameConstructor);
+STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(SymbolConstructor);
 
-const ClassInfo NameConstructor::s_info = { "Function", &Base::s_info, 0, CREATE_METHOD_TABLE(NameConstructor) };
+const ClassInfo SymbolConstructor::s_info = { "Function", &Base::s_info, 0, CREATE_METHOD_TABLE(SymbolConstructor) };
 
-NameConstructor::NameConstructor(VM& vm, Structure* structure)
+SymbolConstructor::SymbolConstructor(VM& vm, Structure* structure)
     : InternalFunction(vm, structure)
 {
 }
 
-void NameConstructor::finishCreation(VM& vm, NamePrototype* prototype)
+#define INITIALIZE_WELL_KNOWN_SYMBOLS(name) \
+    putDirectWithoutTransition(vm, Identifier(&vm, #name), Symbol::create(vm, vm.propertyNames->name##PrivateName.impl()), DontEnum | DontDelete | ReadOnly);
+
+void SymbolConstructor::finishCreation(VM& vm, SymbolPrototype* prototype)
 {
     Base::finishCreation(vm, prototype->classInfo()->className);
     putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, DontEnum | DontDelete | ReadOnly);
-    putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), DontDelete | ReadOnly | DontEnum);
+    putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(0), DontDelete | ReadOnly | DontEnum);
+
+    JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_WELL_KNOWN_SYMBOL(INITIALIZE_WELL_KNOWN_SYMBOLS)
 }
 
-static EncodedJSValue JSC_HOST_CALL constructPrivateName(ExecState* exec)
+static EncodedJSValue JSC_HOST_CALL callSymbol(ExecState* exec)
 {
-    JSValue publicName = exec->argument(0);
-    return JSValue::encode(NameInstance::create(exec->vm(), exec->lexicalGlobalObject()->privateNameStructure(), publicName.toString(exec)));
+    JSValue description = exec->argument(0);
+    if (description.isUndefined())
+        return JSValue::encode(Symbol::create(exec->vm()));
+    return JSValue::encode(Symbol::create(exec, description.toString(exec)));
 }
 
-ConstructType NameConstructor::getConstructData(JSCell*, ConstructData& constructData)
+ConstructType SymbolConstructor::getConstructData(JSCell*, ConstructData&)
 {
-    constructData.native.function = constructPrivateName;
-    return ConstructTypeHost;
+    return ConstructTypeNone;
 }
 
-CallType NameConstructor::getCallData(JSCell*, CallData& callData)
+CallType SymbolConstructor::getCallData(JSCell*, CallData& callData)
 {
-    callData.native.function = constructPrivateName;
+    callData.native.function = callSymbol;
     return CallTypeHost;
 }
 
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef NameConstructor_h
-#define NameConstructor_h
+#ifndef SymbolConstructor_h
+#define SymbolConstructor_h
 
 #include "InternalFunction.h"
-#include "NameInstance.h"
+#include "Symbol.h"
 
 namespace JSC {
 
-class NamePrototype;
+class SymbolPrototype;
 
-class NameConstructor : public InternalFunction {
+class SymbolConstructor : public InternalFunction {
 public:
     typedef InternalFunction Base;
 
-    static NameConstructor* create(VM& vm, Structure* structure, NamePrototype* prototype)
+    static SymbolConstructor* create(VM& vm, Structure* structure, SymbolPrototype* prototype)
     {
-        NameConstructor* constructor = new (NotNull, allocateCell<NameConstructor>(vm.heap)) NameConstructor(vm, structure);
+        SymbolConstructor* constructor = new (NotNull, allocateCell<SymbolConstructor>(vm.heap)) SymbolConstructor(vm, structure);
         constructor->finishCreation(vm, prototype);
         return constructor;
     }
 
     DECLARE_INFO;
 
-    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) 
-    { 
-        return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info()); 
+    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+    {
+        return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
     }
 
 protected:
-    void finishCreation(VM&, NamePrototype*);
-    
+    void finishCreation(VM&, SymbolPrototype*);
+
 private:
-    NameConstructor(VM&, Structure*);
+    SymbolConstructor(VM&, Structure*);
     static ConstructType getConstructData(JSCell*, ConstructData&);
     static CallType getCallData(JSCell*, CallData&);
 };
 
 } // namespace JSC
 
-#endif // NameConstructor_h
+#endif // SymbolConstructor_h
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  */
 
 #include "config.h"
-#include "NameInstance.h"
+#include "SymbolObject.h"
 
-#include "JSScope.h"
 #include "JSCInlines.h"
 
 namespace JSC {
 
-const ClassInfo NameInstance::s_info = { "Name", &Base::s_info, 0, CREATE_METHOD_TABLE(NameInstance) };
+STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(SymbolObject);
 
-NameInstance::NameInstance(VM& vm, Structure* structure, JSString* nameString)
-    : Base(vm, structure)
+const ClassInfo SymbolObject::s_info = { "Symbol", &JSWrapperObject::s_info, nullptr, CREATE_METHOD_TABLE(SymbolObject) };
+
+SymbolObject::SymbolObject(VM& vm, Structure* structure)
+    : JSWrapperObject(vm, structure)
+{
+}
+
+void SymbolObject::finishCreation(VM& vm, Symbol* symbol)
 {
-    m_nameString.set(vm, this, nameString);
+    Base::finishCreation(vm);
+    ASSERT(inherits(info()));
+    setInternalValue(vm, symbol);
 }
 
-void NameInstance::destroy(JSCell* cell)
+JSValue SymbolObject::defaultValue(const JSObject* object, ExecState*, PreferredPrimitiveType)
 {
-    static_cast<NameInstance*>(cell)->NameInstance::~NameInstance();
+    const SymbolObject* symbolObject = jsCast<const SymbolObject*>(object);
+    return symbolObject->internalValue();
 }
 
 } // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/SymbolObject.h b/Source/JavaScriptCore/runtime/SymbolObject.h
new file mode 100644 (file)
index 0000000..46a0491
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *  Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef SymbolObject_h
+#define SymbolObject_h
+
+#include "JSWrapperObject.h"
+#include "Symbol.h"
+
+namespace JSC {
+
+class SymbolObject : public JSWrapperObject {
+public:
+    typedef JSWrapperObject Base;
+
+    static SymbolObject* create(VM& vm, Structure* structure)
+    {
+        Symbol* symbol = Symbol::create(vm);
+        SymbolObject* object = new (NotNull, allocateCell<SymbolObject>(vm.heap)) SymbolObject(vm, structure);
+        object->finishCreation(vm, symbol);
+        return object;
+    }
+    static SymbolObject* create(VM& vm, Structure* structure, Symbol* symbol)
+    {
+        SymbolObject* object = new (NotNull, allocateCell<SymbolObject>(vm.heap)) SymbolObject(vm, structure);
+        object->finishCreation(vm, symbol);
+        return object;
+    }
+    static SymbolObject* create(VM&, JSGlobalObject*, Symbol*);
+
+    DECLARE_EXPORT_INFO;
+
+    Symbol* internalValue() const { return asSymbol(JSWrapperObject::internalValue());}
+
+    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+    {
+        return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
+    }
+
+    static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType);
+
+protected:
+    JS_EXPORT_PRIVATE void finishCreation(VM&, Symbol*);
+    JS_EXPORT_PRIVATE SymbolObject(VM&, Structure*);
+};
+
+} // namespace JSC
+
+#endif // SymbolObject_h
diff --git a/Source/JavaScriptCore/runtime/SymbolPrototype.cpp b/Source/JavaScriptCore/runtime/SymbolPrototype.cpp
new file mode 100644 (file)
index 0000000..b8db161
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "SymbolPrototype.h"
+
+#include "Error.h"
+#include "JSCInlines.h"
+
+namespace JSC {
+
+static EncodedJSValue JSC_HOST_CALL symbolProtoFuncToString(ExecState*);
+static EncodedJSValue JSC_HOST_CALL symbolProtoFuncValueOf(ExecState*);
+
+}
+
+#include "SymbolPrototype.lut.h"
+
+namespace JSC {
+
+const ClassInfo SymbolPrototype::s_info = { "Symbol", &Base::s_info, &symbolPrototypeTable, CREATE_METHOD_TABLE(SymbolPrototype) };
+
+/* Source for SymbolPrototype.lut.h
+@begin symbolPrototypeTable
+  toString          symbolProtoFuncToString         DontEnum|Function 0
+  valueOf           symbolProtoFuncValueOf          DontEnum|Function 0
+@end
+*/
+
+SymbolPrototype::SymbolPrototype(VM& vm, Structure* structure)
+    : Base(vm, structure)
+{
+}
+
+void SymbolPrototype::finishCreation(VM& vm)
+{
+    Base::finishCreation(vm);
+    ASSERT(inherits(info()));
+}
+
+bool SymbolPrototype::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot &slot)
+{
+    return getStaticFunctionSlot<Base>(exec, symbolPrototypeTable, jsCast<SymbolPrototype*>(object), propertyName, slot);
+}
+
+// ------------------------------ Functions ---------------------------
+
+EncodedJSValue JSC_HOST_CALL symbolProtoFuncToString(ExecState* exec)
+{
+    JSValue thisValue = exec->thisValue();
+    Symbol* symbol = nullptr;
+    if (thisValue.isSymbol())
+        symbol = asSymbol(thisValue);
+    else if (!thisValue.isObject())
+        return throwVMTypeError(exec);
+    else {
+        JSObject* thisObject = asObject(thisValue);
+        if (!thisObject->inherits(SymbolObject::info()))
+            return throwVMTypeError(exec);
+        symbol = asSymbol(jsCast<SymbolObject*>(thisObject)->internalValue());
+    }
+
+    return JSValue::encode(jsString(exec, symbol->descriptiveString()));
+}
+
+EncodedJSValue JSC_HOST_CALL symbolProtoFuncValueOf(ExecState* exec)
+{
+    JSValue thisValue = exec->thisValue();
+    if (thisValue.isSymbol())
+        return JSValue::encode(thisValue);
+
+    if (!thisValue.isObject())
+        return throwVMTypeError(exec);
+
+    JSObject* thisObject = asObject(thisValue);
+    if (!thisObject->inherits(SymbolObject::info()))
+        return throwVMTypeError(exec);
+
+    return JSValue::encode(jsCast<SymbolObject*>(thisObject)->internalValue());
+}
+
+} // namespace JSC
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef NamePrototype_h
-#define NamePrototype_h
+#ifndef SymbolPrototype_h
+#define SymbolPrototype_h
 
-#include "NameInstance.h"
+#include "Symbol.h"
+#include "SymbolObject.h"
 
 namespace JSC {
 
-class NamePrototype : public NameInstance {
+// In the ES6 spec, Symbol.prototype object is an ordinary JS object, not one of the symbol wrapper object instance.
+class SymbolPrototype : public JSDestructibleObject {
 public:
-    typedef NameInstance Base;
+    typedef JSDestructibleObject Base;
 
-    static NamePrototype* create(ExecState* exec, Structure* structure)
+    static SymbolPrototype* create(VM& vm, JSGlobalObject*, Structure* structure)
     {
-        VM& vm = exec->vm();
-        NamePrototype* prototype = new (NotNull, allocateCell<NamePrototype>(vm.heap)) NamePrototype(exec, structure);
+        SymbolPrototype* prototype = new (NotNull, allocateCell<SymbolPrototype>(vm.heap)) SymbolPrototype(vm, structure);
         prototype->finishCreation(vm);
         return prototype;
     }
-    
+
     DECLARE_INFO;
 
     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
     {
-        return Structure::create(vm, globalObject, prototype, TypeInfo(NameInstanceType, StructureFlags), info());
+        return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
     }
 
 protected:
-    NamePrototype(ExecState*, Structure*);
+    SymbolPrototype(VM&, Structure*);
     void finishCreation(VM&);
 
-    static const unsigned StructureFlags = OverridesGetOwnPropertySlot | NameInstance::StructureFlags;
+    static const unsigned StructureFlags = OverridesGetOwnPropertySlot | Base::StructureFlags;
 
 private:
     static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&);
@@ -61,4 +63,4 @@ private:
 
 } // namespace JSC
 
-#endif // NamePrototype_h
+#endif // SymbolPrototype_h
index 7a88344..80ed9ca 100644 (file)
@@ -220,6 +220,7 @@ VM::VM(VMType vmType, HeapType heapType)
     programExecutableStructure.set(*this, ProgramExecutable::createStructure(*this, 0, jsNull()));
     functionExecutableStructure.set(*this, FunctionExecutable::createStructure(*this, 0, jsNull()));
     regExpStructure.set(*this, RegExp::createStructure(*this, 0, jsNull()));
+    symbolStructure.set(*this, Symbol::createStructure(*this, 0, jsNull()));
     symbolTableStructure.set(*this, SymbolTable::createStructure(*this, 0, jsNull()));
     structureChainStructure.set(*this, StructureChain::createStructure(*this, 0, jsNull()));
     sparseArrayValueMapStructure.set(*this, SparseArrayValueMap::createStructure(*this, 0, jsNull()));
index f884282..ce337b8 100644 (file)
@@ -264,6 +264,7 @@ public:
     Strong<Structure> programExecutableStructure;
     Strong<Structure> functionExecutableStructure;
     Strong<Structure> regExpStructure;
+    Strong<Structure> symbolStructure;
     Strong<Structure> symbolTableStructure;
     Strong<Structure> structureChainStructure;
     Strong<Structure> sparseArrayValueMapStructure;
index e5dc9b6..327528f 100644 (file)
@@ -1,3 +1,45 @@
+2015-01-30  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        Implement ES6 Symbol
+        https://bugs.webkit.org/show_bug.cgi?id=140435
+
+        Reviewed by Geoffrey Garen.
+
+        Introduce new unique string mechanizm into StringImpl.
+        It is used for implementing Symbol which holds a [[Description]] value.
+
+        * wtf/text/AtomicString.h:
+        (WTF::AtomicString::add):
+        (WTF::AtomicString::addWithStringTableProvider):
+
+        Previously, we checked `isAtomic()` or `!length()`. This guard can filter out EmptyUnique.
+        But now, we introduced new unique StringImpl. Since it has an actual string value, we need to check `isUnique()`.
+
+        * wtf/text/StringImpl.cpp:
+        (WTF::StringImpl::~StringImpl):
+        (WTF::StringImpl::createUnique):
+
+        In createUnique, we leverage Substring mechanizm to produce a new unique
+        string from an existing string.
+
+        * wtf/text/StringImpl.h:
+        (WTF::StringImpl::StringImpl):
+        (WTF::StringImpl::createUniqueEmpty):
+        (WTF::StringImpl::flagIsUnique):
+        (WTF::StringImpl::isUnique):
+        (WTF::StringImpl::setIsAtomic):
+        (WTF::StringImpl::createEmptyUnique): Deleted.
+        (WTF::StringImpl::isEmptyUnique): Deleted.
+
+        Instead of EmptyUnique, we introduced new flag to StringImpl, `isUnique`.
+        While EmptyUnique cannot hold any string values except for empty string,
+        the unique StringImpl can hold any String values.
+        We fold the Symbol's descriptiveString value here.
+
+        * wtf/text/StringStatics.cpp:
+        (WTF::StringImpl::hashAndFlagsForUnique):
+        (WTF::StringImpl::hashAndFlagsForEmptyUnique): Deleted.
+
 2015-01-30  Geoffrey Garen  <ggaren@apple.com>
 
         Use FastMalloc (bmalloc) instead of BlockAllocator for GC pages
index a79076c..bae9d36 100644 (file)
@@ -184,7 +184,7 @@ public:
     ALWAYS_INLINE static RefPtr<StringImpl> add(StringImpl* string)
     {
         if (!string || string->isAtomic()) {
-            ASSERT_WITH_MESSAGE(!string || !string->length() || isInAtomicStringTable(string), "The atomic string comes from an other thread!");
+            ASSERT_WITH_MESSAGE(!string || !string->length() || string->isUnique() || isInAtomicStringTable(string), "The atomic string comes from an other thread!");
             return string;
         }
         return addSlowCase(*string);
@@ -198,7 +198,7 @@ public:
     ALWAYS_INLINE static RefPtr<StringImpl> addWithStringTableProvider(StringTableProvider& stringTableProvider, StringImpl* string)
     {
         if (!string || string->isAtomic()) {
-            ASSERT_WITH_MESSAGE(!string || !string->length() || isInAtomicStringTable(string), "The atomic string comes from an other thread!");
+            ASSERT_WITH_MESSAGE(!string || !string->length() || string->isUnique() || isInAtomicStringTable(string), "The atomic string comes from an other thread!");
             return string;
         }
         return addSlowCase(*stringTableProvider.atomicStringTable(), *string);
index 28a23b4..c249f4d 100644 (file)
@@ -109,7 +109,7 @@ StringImpl::~StringImpl()
 
     STRING_STATS_REMOVE_STRING(*this);
 
-    if (isAtomic() && m_length)
+    if (isAtomic() && length() && !isUnique())
         AtomicString::remove(this);
 
     BufferOwnership ownership = bufferOwnership();
@@ -286,6 +286,16 @@ Ref<StringImpl> StringImpl::create(const LChar* string)
     return create(string, length);
 }
 
+Ref<StringImpl> StringImpl::createUnique(PassRefPtr<StringImpl> rep)
+{
+    unsigned length = rep->length();
+    if (!length)
+        return createUniqueEmpty();
+    Ref<StringImpl> string = createSubstringSharingImpl(rep, 0, length);
+    string->m_hashAndFlags = hashAndFlagsForUnique(string->m_hashAndFlags);
+    return string;
+}
+
 bool StringImpl::containsOnlyWhitespace()
 {
     // FIXME: The definition of whitespace here includes a number of characters
index b66b0cc..9cb0214 100644 (file)
@@ -280,7 +280,7 @@ private:
         // We expect m_length to be initialized to 0 as we use it
         // to represent a null terminated buffer.
         , m_data8(reinterpret_cast<const LChar*>(&m_length))
-        , m_hashAndFlags(hashAndFlagsForEmptyUnique())
+        , m_hashAndFlags(hashAndFlagsForUnique(s_hashFlag8BitBuffer | BufferInternal))
     {
         ASSERT(m_data8);
 
@@ -378,11 +378,13 @@ public:
         return constructInternal<T>(resultImpl, length);
     }
 
-    static Ref<StringImpl> createEmptyUnique()
+    ALWAYS_INLINE static Ref<StringImpl> createUniqueEmpty()
     {
         return adoptRef(*new StringImpl(CreateEmptyUnique));
     }
 
+    WTF_EXPORT_STRING_API static Ref<StringImpl> createUnique(PassRefPtr<StringImpl> rep);
+
     // Reallocate the StringImpl. The originalString must be only owned by the PassRefPtr,
     // and the buffer ownership must be BufferInternal. Just like the input pointer of realloc(),
     // the originalString can't be used after this function.
@@ -392,6 +394,7 @@ public:
     static unsigned flagsOffset() { return OBJECT_OFFSETOF(StringImpl, m_hashAndFlags); }
     static unsigned flagIs8Bit() { return s_hashFlag8BitBuffer; }
     static unsigned flagIsAtomic() { return s_hashFlagIsAtomic; }
+    static unsigned flagIsUnique() { return s_hashFlagIsUnique; }
     static unsigned dataOffset() { return OBJECT_OFFSETOF(StringImpl, m_data8); }
 
     template<typename CharType, size_t inlineCapacity, typename OverflowHandler>
@@ -451,16 +454,13 @@ public:
 
     WTF_EXPORT_STRING_API size_t sizeInBytes() const;
 
-    bool isEmptyUnique() const
-    {
-        return !length() && !isStatic();
-    }
+    bool isUnique() const { return m_hashAndFlags & s_hashFlagIsUnique; }
 
     bool isAtomic() const { return m_hashAndFlags & s_hashFlagIsAtomic; }
     void setIsAtomic(bool isAtomic)
     {
         ASSERT(!isStatic());
-        ASSERT(!isEmptyUnique());
+        ASSERT(!isUnique());
         if (isAtomic)
             m_hashAndFlags |= s_hashFlagIsAtomic;
         else
@@ -772,17 +772,18 @@ private:
     template <typename CharType> static Ref<StringImpl> reallocateInternal(PassRefPtr<StringImpl>, unsigned, CharType*&);
     template <typename CharType> static Ref<StringImpl> createInternal(const CharType*, unsigned);
     WTF_EXPORT_PRIVATE NEVER_INLINE unsigned hashSlowCase() const;
-    WTF_EXPORT_PRIVATE unsigned hashAndFlagsForEmptyUnique();
+    WTF_EXPORT_PRIVATE static unsigned hashAndFlagsForUnique(unsigned flags);
 
     // The bottom bit in the ref count indicates a static (immortal) string.
     static const unsigned s_refCountFlagIsStaticString = 0x1;
     static const unsigned s_refCountIncrement = 0x2; // This allows us to ref / deref without disturbing the static string flag.
 
-    // The bottom 6 bits in the hash are flags.
-    static const unsigned s_flagCount = 6;
+    // The bottom 7 bits in the hash are flags.
+    static const unsigned s_flagCount = 7;
     static const unsigned s_flagMask = (1u << s_flagCount) - 1;
     COMPILE_ASSERT(s_flagCount <= StringHasher::flagCount, StringHasher_reserves_enough_bits_for_StringImpl_flags);
 
+    static const unsigned s_hashFlagIsUnique = 1u << 6;
     static const unsigned s_hashFlag8BitBuffer = 1u << 5;
     static const unsigned s_hashFlagIsAtomic = 1u << 4;
     static const unsigned s_hashFlagDidReportCost = 1u << 3;
index a234ffd..65bb672 100644 (file)
@@ -47,17 +47,18 @@ StringImpl* StringImpl::empty()
     return &emptyString.get();
 }
 
-// Set the hash early, so that all empty unique StringImpls have a hash,
+// Set the hash early, so that all unique StringImpls have a hash,
 // and don't use the normal hashing algorithm - the unique nature of these
 // keys means that we don't need them to match any other string (in fact,
 // that's exactly the oposite of what we want!), and the normal hash would
 // lead to lots of conflicts.
-unsigned StringImpl::hashAndFlagsForEmptyUnique()
+unsigned StringImpl::hashAndFlagsForUnique(unsigned flags)
 {
-    static unsigned s_nextHashAndFlagsForEmptyUnique = BufferInternal | s_hashFlag8BitBuffer | s_hashFlagIsAtomic;
-    s_nextHashAndFlagsForEmptyUnique += 1 << s_flagCount;
-    s_nextHashAndFlagsForEmptyUnique |= 1 << 31;
-    return s_nextHashAndFlagsForEmptyUnique;
+    static unsigned s_nextHashAndFlagsForUnique = 0;
+    s_nextHashAndFlagsForUnique += 1 << s_flagCount;
+    s_nextHashAndFlagsForUnique |= 1 << 31;
+    unsigned flagsForUnique = (flags & s_flagMask) | s_hashFlagIsAtomic | s_hashFlagIsUnique;
+    return s_nextHashAndFlagsForUnique | flagsForUnique;
 }
 
 WTF_EXPORTDATA DEFINE_GLOBAL(AtomicString, nullAtom)