Bug 1165053 - Part 2: Implement %TypedArray%[@@species] getter and ArrayBuffer[@@species] getter. r=evilpie
☠☠ backed out by 6be7ee58f77a ☠ ☠
authorTooru Fujisawa <arai_a@mac.com>
Sun, 20 Dec 2015 19:14:44 +0900
changeset 328408 6ec3a764a8a50ae594fc35f7f17aef550efbce34
parent 328407 f66243f0197ec2f2c55d8e0481234a7768d17198
child 328409 31ce940c509c21d24e9d59653ee5f4bad10f1cff
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersevilpie
bugs1165053
milestone48.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1165053 - Part 2: Implement %TypedArray%[@@species] getter and ArrayBuffer[@@species] getter. r=evilpie
js/src/builtin/TypedArray.js
js/src/builtin/Utilities.js
js/src/tests/ecma_6/Symbol/species.js
js/src/vm/ArrayBufferObject.cpp
js/src/vm/ArrayBufferObject.h
js/src/vm/TypedArrayObject.cpp
js/src/vm/TypedArrayObject.h
--- a/js/src/builtin/TypedArray.js
+++ b/js/src/builtin/TypedArray.js
@@ -1303,16 +1303,22 @@ function TypedArrayStaticOf(/*...items*/
     // Steps 6-7.
     for (var k = 0; k < len; k++)
         newObj[k] = items[k]
 
     // Step 8.
     return newObj;
 }
 
+// ES 2016 draft Mar 25, 2016 22.2.2.4.
+function TypedArraySpecies() {
+    // Step 1.
+    return this;
+}
+
 // ES 2016 draft Mar 25, 2016 24.1.4.3.
 function ArrayBufferSlice(start, end) {
     // Step 1.
     var O = this;
 
     // Steps 2-3,
     // This function is not generic.
     if (!IsObject(O) || !IsArrayBuffer(O)) {
@@ -1392,8 +1398,14 @@ function IsDetachedBufferThis() {
   return IsDetachedBuffer(this);
 }
 
 function ArrayBufferStaticSlice(buf, start, end) {
     if (arguments.length < 1)
         ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'ArrayBuffer.slice');
     return callFunction(ArrayBufferSlice, buf, start, end);
 }
+
+// ES 2016 draft Mar 25, 2016 24.1.3.3.
+function ArrayBufferSpecies() {
+    // Step 1.
+    return this;
+}
--- a/js/src/builtin/Utilities.js
+++ b/js/src/builtin/Utilities.js
@@ -162,44 +162,44 @@ function GetBuiltinConstructor(builtinNa
     assert(ctor, `No builtin with name "${builtinName}" found`);
     return ctor;
 }
 
 function GetBuiltinPrototype(builtinName) {
     return (_builtinCtorsCache[builtinName] || GetBuiltinConstructor(builtinName)).prototype;
 }
 
-// ES6 draft 20150317 7.3.20.
+// ES 2016 draft Mar 25, 2016 7.3.20.
 function SpeciesConstructor(obj, defaultConstructor) {
     // Step 1.
     assert(IsObject(obj), "not passed an object");
 
-    // Steps 2-3.
+    // Step 2.
     var ctor = obj.constructor;
 
-    // Step 4.
+    // Step 3.
     if (ctor === undefined)
         return defaultConstructor;
 
-    // Step 5.
+    // Step 4.
     if (!IsObject(ctor))
         ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT, "object's 'constructor' property");
 
-    // Steps 6-7.
+    // Steps 5.
     var s = ctor[std_species];
 
-    // Step 8.
+    // Step 6.
     if (s === undefined || s === null)
         return defaultConstructor;
 
-    // Step 9.
+    // Step 7.
     if (IsConstructor(s))
         return s;
 
-    // Step 10.
+    // Step 8.
     ThrowTypeError(JSMSG_NOT_CONSTRUCTOR, "@@species property of object's constructor");
 }
 
 function GetTypeError(msg) {
     try {
         FUN_APPLY(ThrowTypeError, undefined, arguments);
     } catch (e) {
         return e;
--- a/js/src/tests/ecma_6/Symbol/species.js
+++ b/js/src/tests/ecma_6/Symbol/species.js
@@ -1,18 +1,26 @@
 var BUGNUMBER = 1131043;
 var summary = "Implement @@species getter for builtin types";
 
 print(BUGNUMBER + ": " + summary);
 
-for (var C of [Map, Set]) {
+var TypedArray = Object.getPrototypeOf(Int8Array);
+
+for (var C of [Map, Set,
+               Int8Array, Uint8Array, Uint8ClampedArray,
+               Int16Array, Uint16Array, Int32Array, Uint32Array,
+               Float32Array, Float64Array,
+               ArrayBuffer]) {
   assertEq(C[Symbol.species], C);
 }
 
-for (C of [Map, Set]) {
+for (C of [Map, Set,
+           TypedArray,
+           ArrayBuffer]) {
   var desc = Object.getOwnPropertyDescriptor(C, Symbol.species);
   assertDeepEq(Object.keys(desc).sort(), ["configurable", "enumerable", "get", "set"]);
   assertEq(desc.set, undefined);
   assertEq(desc.enumerable, false);
   assertEq(desc.configurable, true);
   assertEq(desc.get.apply(null), null);
   assertEq(desc.get.apply(undefined), undefined);
   assertEq(desc.get.apply(42), 42);
--- a/js/src/vm/ArrayBufferObject.cpp
+++ b/js/src/vm/ArrayBufferObject.cpp
@@ -128,16 +128,21 @@ const JSFunctionSpec ArrayBufferObject::
 };
 
 const JSFunctionSpec ArrayBufferObject::jsstaticfuncs[] = {
     JS_FN("isView", ArrayBufferObject::fun_isView, 1, 0),
     JS_SELF_HOSTED_FN("slice", "ArrayBufferStaticSlice", 3,0),
     JS_FS_END
 };
 
+const JSPropertySpec ArrayBufferObject::jsstaticprops[] = {
+    JS_SELF_HOSTED_SYM_GET(species, "ArrayBufferSpecies", 0),
+    JS_PS_END
+};
+
 bool
 js::IsArrayBuffer(HandleValue v)
 {
     return v.isObject() && v.toObject().is<ArrayBufferObject>();
 }
 
 bool
 js::IsArrayBuffer(HandleObject obj)
@@ -1438,14 +1443,17 @@ js::InitArrayBufferClass(JSContext* cx, 
 
     if (!NativeDefineProperty(cx, arrayBufferProto, byteLengthId, UndefinedHandleValue,
                               JS_DATA_TO_FUNC_PTR(GetterOp, getter), nullptr, attrs))
         return nullptr;
 
     if (!JS_DefineFunctions(cx, ctor, ArrayBufferObject::jsstaticfuncs))
         return nullptr;
 
+    if (!JS_DefineProperties(cx, ctor, ArrayBufferObject::jsstaticprops))
+        return nullptr;
+
     if (!JS_DefineFunctions(cx, arrayBufferProto, ArrayBufferObject::jsfuncs))
         return nullptr;
 
     return arrayBufferProto;
 }
 
--- a/js/src/vm/ArrayBufferObject.h
+++ b/js/src/vm/ArrayBufferObject.h
@@ -193,26 +193,29 @@ class ArrayBufferObject : public ArrayBu
         explicit operator bool() const { return data_ != nullptr; }
     };
 
     static const Class class_;
 
     static const Class protoClass;
     static const JSFunctionSpec jsfuncs[];
     static const JSFunctionSpec jsstaticfuncs[];
+    static const JSPropertySpec jsstaticprops[];
 
     static bool byteLengthGetter(JSContext* cx, unsigned argc, Value* vp);
 
     static bool fun_slice(JSContext* cx, unsigned argc, Value* vp);
 
     static bool fun_isView(JSContext* cx, unsigned argc, Value* vp);
 #ifdef NIGHTLY_BUILD
     static bool fun_transfer(JSContext* cx, unsigned argc, Value* vp);
 #endif
 
+    static bool fun_species(JSContext* cx, unsigned argc, Value* vp);
+
     static bool class_constructor(JSContext* cx, unsigned argc, Value* vp);
 
     static ArrayBufferObject* create(JSContext* cx, uint32_t nbytes,
                                      BufferContents contents,
                                      OwnsState ownsState = OwnsData,
                                      HandleObject proto = nullptr,
                                      NewObjectKind newKind = GenericObject);
     static ArrayBufferObject* create(JSContext* cx, uint32_t nbytes,
--- a/js/src/vm/TypedArrayObject.cpp
+++ b/js/src/vm/TypedArrayObject.cpp
@@ -856,16 +856,22 @@ TypedArrayObject::protoFunctions[] = {
 
 /* static */ const JSFunctionSpec
 TypedArrayObject::staticFunctions[] = {
     JS_SELF_HOSTED_FN("from", "TypedArrayStaticFrom", 3, 0),
     JS_SELF_HOSTED_FN("of", "TypedArrayStaticOf", 0, 0),
     JS_FS_END
 };
 
+/* static */ const JSPropertySpec
+TypedArrayObject::staticProperties[] = {
+    JS_SELF_HOSTED_SYM_GET(species, "TypedArraySpecies", 0),
+    JS_PS_END
+};
+
 /* static */ const Class
 TypedArrayObject::sharedTypedArrayPrototypeClass = {
     // Actually ({}).toString.call(%TypedArray%.prototype) should throw,
     // because %TypedArray%.prototype lacks the the typed array internal
     // slots.  (It's not clear this is desirable -- particularly applied to
     // the actual typed array prototypes, see below -- but it's what ES6
     // draft 20140824 requires.)  But this is about as much as we can do
     // until we implement @@toStringTag.
@@ -882,17 +888,17 @@ TypedArrayObject::sharedTypedArrayProtot
     nullptr,                /* call */
     nullptr,                /* hasInstance */
     nullptr,                /* construct */
     nullptr,                /* trace */
     {
         GenericCreateConstructor<TypedArrayConstructor, 3, gc::AllocKind::FUNCTION>,
         GenericCreatePrototype,
         TypedArrayObject::staticFunctions,
-        nullptr,
+        TypedArrayObject::staticProperties,
         TypedArrayObject::protoFunctions,
         TypedArrayObject::protoAccessors,
         nullptr,
         ClassSpec::DontDefineConstructor
     }
 };
 
 template<typename T>
--- a/js/src/vm/TypedArrayObject.h
+++ b/js/src/vm/TypedArrayObject.h
@@ -251,16 +251,17 @@ class TypedArrayObject : public NativeOb
     {
         CallArgs args = CallArgsFromVp(argc, vp);
         return CallNonGenericMethod<is, GetterImpl<ValueGetter>>(cx, args);
     }
 
     static const JSFunctionSpec protoFunctions[];
     static const JSPropertySpec protoAccessors[];
     static const JSFunctionSpec staticFunctions[];
+    static const JSPropertySpec staticProperties[];
 
     /* Accessors and functions */
 
     static bool is(HandleValue v);
 
     static bool set(JSContext* cx, unsigned argc, Value* vp);
 };