[ES6] Support subclassing the String builtin object
authorkeith_miller@apple.com <keith_miller@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 13 Jan 2016 23:45:14 +0000 (23:45 +0000)
committerkeith_miller@apple.com <keith_miller@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 13 Jan 2016 23:45:14 +0000 (23:45 +0000)
https://bugs.webkit.org/show_bug.cgi?id=153068

Reviewed by Michael Saboff.

This patch adds subclassing of strings. Also, this patch fixes a bug where we could have
the wrong indexing type for builtins constructed without storage.

* runtime/PrototypeMap.cpp:
(JSC::PrototypeMap::emptyStructureForPrototypeFromBaseStructure):
* runtime/StringConstructor.cpp:
(JSC::constructWithStringConstructor):
* tests/stress/class-subclassing-string.js: Added.
(test):

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

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/runtime/PrototypeMap.cpp
Source/JavaScriptCore/runtime/StringConstructor.cpp
Source/JavaScriptCore/tests/stress/class-subclassing-string.js [new file with mode: 0644]

index 56ddc3df493531b500f7ba488234a3fc59be9ab2..dc1df0cac4882327a4c946d6fc80ac93b3860676 100644 (file)
@@ -1,3 +1,20 @@
+2016-01-13  Keith Miller  <keith_miller@apple.com>
+
+        [ES6] Support subclassing the String builtin object
+        https://bugs.webkit.org/show_bug.cgi?id=153068
+
+        Reviewed by Michael Saboff.
+
+        This patch adds subclassing of strings. Also, this patch fixes a bug where we could have
+        the wrong indexing type for builtins constructed without storage.
+
+        * runtime/PrototypeMap.cpp:
+        (JSC::PrototypeMap::emptyStructureForPrototypeFromBaseStructure):
+        * runtime/StringConstructor.cpp:
+        (JSC::constructWithStringConstructor):
+        * tests/stress/class-subclassing-string.js: Added.
+        (test):
+
 2016-01-13  Mark Lam  <mark.lam@apple.com>
 
         The StringFromCharCode DFG intrinsic should support untyped operands.
 2016-01-13  Mark Lam  <mark.lam@apple.com>
 
         The StringFromCharCode DFG intrinsic should support untyped operands.
index e63f642182095d300c521e2475e075ebff47c9d0..d9a150db06952595aaa814678bf9e280f9d1b7c3 100644 (file)
@@ -72,7 +72,7 @@ Structure* PrototypeMap::emptyStructureForPrototypeFromBaseStructure(JSObject* p
 {
     // We currently do not have inline capacity static analysis for subclasses and all internal function constructors have a default inline capacity of 0.
     IndexingType indexingType = baseStructure->indexingType();
 {
     // We currently do not have inline capacity static analysis for subclasses and all internal function constructors have a default inline capacity of 0.
     IndexingType indexingType = baseStructure->indexingType();
-    if (prototype->structure()->anyObjectInChainMayInterceptIndexedAccesses())
+    if (prototype->structure()->anyObjectInChainMayInterceptIndexedAccesses() && hasIndexedProperties(indexingType))
         indexingType = (indexingType & ~IndexingShapeMask) | SlowPutArrayStorageShape;
 
     return createEmptyStructure(prototype, baseStructure->typeInfo(), baseStructure->classInfo(), indexingType, 0);
         indexingType = (indexingType & ~IndexingShapeMask) | SlowPutArrayStorageShape;
 
     return createEmptyStructure(prototype, baseStructure->typeInfo(), baseStructure->classInfo(), indexingType, 0);
index 2acf0735c53fc40ed476cd01ef1c1440821e6ca0..835d2464938193704fa3ec78b2bbc6fe97db9f0d 100644 (file)
@@ -126,9 +126,9 @@ static EncodedJSValue JSC_HOST_CALL constructWithStringConstructor(ExecState* ex
     VM& vm = exec->vm();
 
     if (!exec->argumentCount())
     VM& vm = exec->vm();
 
     if (!exec->argumentCount())
-        return JSValue::encode(StringObject::create(vm, globalObject->stringObjectStructure()));
+        return JSValue::encode(StringObject::create(vm, InternalFunction::createSubclassStructure(exec, exec->newTarget(), globalObject->stringObjectStructure())));
 
 
-    return JSValue::encode(StringObject::create(vm, globalObject->stringObjectStructure(), exec->uncheckedArgument(0).toString(exec)));
+    return JSValue::encode(StringObject::create(vm, InternalFunction::createSubclassStructure(exec, exec->newTarget(), globalObject->stringObjectStructure()), exec->uncheckedArgument(0).toString(exec)));
 }
 
 ConstructType StringConstructor::getConstructData(JSCell*, ConstructData& constructData)
 }
 
 ConstructType StringConstructor::getConstructData(JSCell*, ConstructData& constructData)
diff --git a/Source/JavaScriptCore/tests/stress/class-subclassing-string.js b/Source/JavaScriptCore/tests/stress/class-subclassing-string.js
new file mode 100644 (file)
index 0000000..bd9b377
--- /dev/null
@@ -0,0 +1,38 @@
+A = class extends String { }
+B = class extends A { get 4() { return 1; } }
+C = class extends B { }
+
+A.prototype[3] = 1;
+
+function test() {
+    let a = new A("foo");
+    let b = new B("baz");
+    let c = new C("bar");
+
+    // String objects have a non-writable length property
+    a.length = 1;
+    b.length = 1;
+    c.length = 1;
+
+    if (a.length !== 3 || b.length !== 3 || c.length !== 3)
+        throw "not string objects";
+
+    if (!(a instanceof A && a instanceof String))
+        throw "a has incorrect prototype chain";
+
+    if (!(b instanceof B && b instanceof A && b instanceof String))
+        throw "b has incorrect prototype chain";
+
+    if (!(c instanceof C && c instanceof B && c instanceof A && c instanceof String))
+        throw "c has incorrect prototype chain";
+
+    if (a[4] !== undefined || b[4] !== 1 || c[4] !== 1)
+        throw "bad indexing type with accessors on chain";
+
+    if (a[3] !== 1 || b[3] !== 1 || c[3] !== 1)
+        throw "bad indexing type with values on chain";
+}
+noInline(test);
+
+for (i = 0; i < 10000; i++)
+    test();