Add %TypedArray% to proto chain
authorlittledan <littledan@chromium.org>
Tue, 16 Jun 2015 23:39:01 +0000 (16:39 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 16 Jun 2015 23:39:10 +0000 (23:39 +0000)
According to the ES6 spec, the main methods and getters shouldn't
be properties of the individual TypedArray objects and prototypes
but instead on %TypedArray% and %TypedArray%.prototype. This
difference is observable through introspection. This patch moves
some methods and getters to the proper place, with the exception
of %TypedArray%.prototype.subarray and harmony methods. These will
be moved in follow-on patches.

BUG=v8:4085
LOG=Y
R=adamk

Review URL: https://codereview.chromium.org/1186733002

Cr-Commit-Position: refs/heads/master@{#29057}

src/harmony-typedarray.js
src/runtime/runtime-function.cc
src/runtime/runtime-object.cc
src/typedarray.js
test/mjsunit/es6/built-in-accessor-names.js
test/mjsunit/get-prototype-of.js
test/mjsunit/harmony/sharedarraybuffer.js
test/mjsunit/harmony/typedarrays-of.js
test/mjsunit/harmony/typedarrays.js
test/mjsunit/regress/regress-typedarray-length.js

index b9cc798..b2550a9 100644 (file)
 // -------------------------------------------------------------------
 // Imports
 
-macro TYPED_ARRAYS(FUNCTION)
-// arrayIds below should be synchronized with Runtime_TypedArrayInitialize.
-FUNCTION(Uint8Array)
-FUNCTION(Int8Array)
-FUNCTION(Uint16Array)
-FUNCTION(Int16Array)
-FUNCTION(Uint32Array)
-FUNCTION(Int32Array)
-FUNCTION(Float32Array)
-FUNCTION(Float64Array)
-FUNCTION(Uint8ClampedArray)
-endmacro
 
 macro DECLARE_GLOBALS(NAME)
 var GlobalNAME = global.NAME;
 endmacro
 
-TYPED_ARRAYS(DECLARE_GLOBALS)
 DECLARE_GLOBALS(Array)
+DECLARE_GLOBALS(Uint8Array)
+DECLARE_GLOBALS(Int8Array)
+DECLARE_GLOBALS(Uint16Array)
+DECLARE_GLOBALS(Int16Array)
+DECLARE_GLOBALS(Uint32Array)
+DECLARE_GLOBALS(Int32Array)
+DECLARE_GLOBALS(Float32Array)
+DECLARE_GLOBALS(Float64Array)
+DECLARE_GLOBALS(Uint8ClampedArray)
 
 var ArrayFrom;
 var ArrayToString;
@@ -51,6 +47,8 @@ var InnerArrayToLocaleString;
 var IsNaN;
 var MathMax;
 var MathMin;
+var TypedArray = GlobalUint8Array.__proto__;
+var TypedArrayPrototype = GlobalUint8Array.prototype.__proto__;
 
 utils.Import(function(from) {
   ArrayFrom = from.ArrayFrom;
@@ -376,38 +374,33 @@ function TypedArrayFrom(source, mapfn, thisArg) {
 }
 %FunctionSetLength(TypedArrayFrom, 1);
 
-// TODO(littledan): Fix the TypedArray proto chain (bug v8:4085).
-macro EXTEND_TYPED_ARRAY(NAME)
   // Set up non-enumerable functions on the object.
-  utils.InstallFunctions(GlobalNAME, DONT_ENUM | DONT_DELETE | READ_ONLY, [
-    "from", TypedArrayFrom,
-    "of", TypedArrayOf
-  ]);
-
-  // Set up non-enumerable functions on the prototype object.
-  utils.InstallFunctions(GlobalNAME.prototype, DONT_ENUM, [
-    "copyWithin", TypedArrayCopyWithin,
-    "every", TypedArrayEvery,
-    "fill", TypedArrayFill,
-    "filter", TypedArrayFilter,
-    "find", TypedArrayFind,
-    "findIndex", TypedArrayFindIndex,
-    "indexOf", TypedArrayIndexOf,
-    "join", TypedArrayJoin,
-    "lastIndexOf", TypedArrayLastIndexOf,
-    "forEach", TypedArrayForEach,
-    "map", TypedArrayMap,
-    "reduce", TypedArrayReduce,
-    "reduceRight", TypedArrayReduceRight,
-    "reverse", TypedArrayReverse,
-    "slice", TypedArraySlice,
-    "some", TypedArraySome,
-    "sort", TypedArraySort,
-    "toString", TypedArrayToString,
-    "toLocaleString", TypedArrayToLocaleString
-  ]);
-endmacro
-
-TYPED_ARRAYS(EXTEND_TYPED_ARRAY)
+utils.InstallFunctions(TypedArray, DONT_ENUM | DONT_DELETE | READ_ONLY, [
+  "from", TypedArrayFrom,
+  "of", TypedArrayOf
+]);
+
+// Set up non-enumerable functions on the prototype object.
+utils.InstallFunctions(TypedArrayPrototype, DONT_ENUM, [
+  "copyWithin", TypedArrayCopyWithin,
+  "every", TypedArrayEvery,
+  "fill", TypedArrayFill,
+  "filter", TypedArrayFilter,
+  "find", TypedArrayFind,
+  "findIndex", TypedArrayFindIndex,
+  "indexOf", TypedArrayIndexOf,
+  "join", TypedArrayJoin,
+  "lastIndexOf", TypedArrayLastIndexOf,
+  "forEach", TypedArrayForEach,
+  "map", TypedArrayMap,
+  "reduce", TypedArrayReduce,
+  "reduceRight", TypedArrayReduceRight,
+  "reverse", TypedArrayReverse,
+  "slice", TypedArraySlice,
+  "some", TypedArraySome,
+  "sort", TypedArraySort,
+  "toString", TypedArrayToString,
+  "toLocaleString", TypedArrayToLocaleString
+]);
 
 })
index 6283f1e..63008d5 100644 (file)
@@ -171,6 +171,7 @@ RUNTIME_FUNCTION(Runtime_FunctionSetLength) {
 }
 
 
+// Set the "prototype" property of a constructor Function.
 RUNTIME_FUNCTION(Runtime_FunctionSetPrototype) {
   HandleScope scope(isolate);
   DCHECK(args.length() == 2);
index b3b917b..ba67597 100644 (file)
@@ -148,6 +148,7 @@ RUNTIME_FUNCTION(Runtime_GetPrototype) {
 }
 
 
+// Set the [[Prototype]] internal slot of an object.
 RUNTIME_FUNCTION(Runtime_InternalSetPrototype) {
   HandleScope scope(isolate);
   DCHECK(args.length() == 2);
index ce52cdf..056a0d7 100644 (file)
@@ -47,6 +47,44 @@ var InternalArray = utils.InternalArray;
 
 // --------------- Typed Arrays ---------------------
 
+function TypedArray() {
+  if (!%_IsConstructCall()) {
+    throw MakeTypeError(kConstructorNotFunction, "TypedArray")
+  }
+  // TODO(littledan): When the TypedArrays code is refactored to provide
+  // a common constructor entrypoint for v8:4182, call that here.
+}
+
+function TypedArray_GetBuffer() {
+  if (!%_IsTypedArray(this)) {
+    throw MakeTypeError(kIncompatibleMethodReceiver, "TypedArray.buffer", this);
+  }
+  return %TypedArrayGetBuffer(this);
+}
+
+function TypedArray_GetByteLength() {
+  if (!%_IsTypedArray(this)) {
+    throw MakeTypeError(kIncompatibleMethodReceiver, "TypedArray.byteLength",
+                        this);
+  }
+  return %_ArrayBufferViewGetByteLength(this);
+}
+
+function TypedArray_GetByteOffset() {
+  if (!%_IsTypedArray(this)) {
+    throw MakeTypeError(kIncompatibleMethodReceiver, "TypedArray.byteOffset",
+                        this);
+  }
+  return %_ArrayBufferViewGetByteOffset(this);
+}
+
+function TypedArray_GetLength() {
+  if (!%_IsTypedArray(this)) {
+    throw MakeTypeError(kIncompatibleMethodReceiver, "TypedArray.length", this);
+  }
+  return %_TypedArrayGetLength(this);
+}
+
 macro TYPED_ARRAY_CONSTRUCTOR(ARRAY_ID, NAME, ELEMENT_SIZE)
 function NAMEConstructByArrayBuffer(obj, buffer, byteOffset, length) {
   if (!IS_UNDEFINED(byteOffset)) {
@@ -172,34 +210,6 @@ function NAMEConstructor(arg1, arg2, arg3) {
   }
 }
 
-function NAME_GetBuffer() {
-  if (!(%_ClassOf(this) === 'NAME')) {
-    throw MakeTypeError(kIncompatibleMethodReceiver, "NAME.buffer", this);
-  }
-  return %TypedArrayGetBuffer(this);
-}
-
-function NAME_GetByteLength() {
-  if (!(%_ClassOf(this) === 'NAME')) {
-    throw MakeTypeError(kIncompatibleMethodReceiver, "NAME.byteLength", this);
-  }
-  return %_ArrayBufferViewGetByteLength(this);
-}
-
-function NAME_GetByteOffset() {
-  if (!(%_ClassOf(this) === 'NAME')) {
-    throw MakeTypeError(kIncompatibleMethodReceiver, "NAME.byteOffset", this);
-  }
-  return %_ArrayBufferViewGetByteOffset(this);
-}
-
-function NAME_GetLength() {
-  if (!(%_ClassOf(this) === 'NAME')) {
-    throw MakeTypeError(kIncompatibleMethodReceiver, "NAME.length", this);
-  }
-  return %_TypedArrayGetLength(this);
-}
-
 function NAMESubArray(begin, end) {
   if (!(%_ClassOf(this) === 'NAME')) {
     throw MakeTypeError(kIncompatibleMethodReceiver, "NAME.subarray", this);
@@ -347,29 +357,33 @@ function TypedArrayGetToStringTag() {
 
 // -------------------------------------------------------------------
 
+utils.InstallGetter(TypedArray.prototype, "buffer", TypedArray_GetBuffer);
+utils.InstallGetter(TypedArray.prototype, "byteOffset",
+                    TypedArray_GetByteOffset, DONT_ENUM);
+utils.InstallGetter(TypedArray.prototype, "byteLength",
+                    TypedArray_GetByteLength, DONT_ENUM);
+utils.InstallGetter(TypedArray.prototype, "length", TypedArray_GetLength,
+                    DONT_ENUM);
+utils.InstallGetter(TypedArray.prototype, symbolToStringTag,
+                    TypedArrayGetToStringTag, DONT_ENUM);
+utils.InstallFunctions(TypedArray.prototype, DONT_ENUM, [
+  "set", TypedArraySet
+]);
+
 macro SETUP_TYPED_ARRAY(ARRAY_ID, NAME, ELEMENT_SIZE)
   %SetCode(GlobalNAME, NAMEConstructor);
-  %FunctionSetPrototype(GlobalNAME, new GlobalObject());
+  %InternalSetPrototype(GlobalNAME, TypedArray);
+  %FunctionSetPrototype(GlobalNAME, new TypedArray());
+  %AddNamedProperty(GlobalNAME.prototype,
+                    "BYTES_PER_ELEMENT", ELEMENT_SIZE,
+                    READ_ONLY | DONT_ENUM | DONT_DELETE);
 
   %AddNamedProperty(GlobalNAME, "BYTES_PER_ELEMENT", ELEMENT_SIZE,
                     READ_ONLY | DONT_ENUM | DONT_DELETE);
   %AddNamedProperty(GlobalNAME.prototype,
                     "constructor", global.NAME, DONT_ENUM);
-  %AddNamedProperty(GlobalNAME.prototype,
-                    "BYTES_PER_ELEMENT", ELEMENT_SIZE,
-                    READ_ONLY | DONT_ENUM | DONT_DELETE);
-  utils.InstallGetter(GlobalNAME.prototype, "buffer", NAME_GetBuffer);
-  utils.InstallGetter(GlobalNAME.prototype, "byteOffset", NAME_GetByteOffset,
-                      DONT_ENUM | DONT_DELETE);
-  utils.InstallGetter(GlobalNAME.prototype, "byteLength", NAME_GetByteLength,
-                      DONT_ENUM | DONT_DELETE);
-  utils.InstallGetter(GlobalNAME.prototype, "length", NAME_GetLength,
-                      DONT_ENUM | DONT_DELETE);
-  utils.InstallGetter(GlobalNAME.prototype, symbolToStringTag,
-                      TypedArrayGetToStringTag);
   utils.InstallFunctions(GlobalNAME.prototype, DONT_ENUM, [
-    "subarray", NAMESubArray,
-    "set", TypedArraySet
+    "subarray", NAMESubArray
   ]);
 endmacro
 
index d902ae6..4cfebdc 100644 (file)
@@ -6,14 +6,22 @@
 
 'use strict';
 
-function assertGetterName(expected, object, name) {
-  var descr = Object.getOwnPropertyDescriptor(object, name);
+function getPropertyDescriptor(object, field, expectedDepth) {
+  for (var depth = 0; depth < expectedDepth; depth++) {
+    assertFalse(Object.hasOwnProperty(object, field));
+    object = object.__proto__;
+  }
+  return Object.getOwnPropertyDescriptor(object, field);
+}
+
+function assertGetterName(expected, object, name, expectedDepth) {
+  var descr = getPropertyDescriptor(object, name, expectedDepth);
   assertSame(expected, descr.get.name);
 }
 
 
-function assertSetterName(expected, object, name) {
-  var descr = Object.getOwnPropertyDescriptor(object, name);
+function assertSetterName(expected, object, name, indirect) {
+  var descr = getPropertyDescriptor(object, name);
   assertSame(expected, descr.set.name);
 }
 
@@ -36,11 +44,11 @@ let typedArrays = [
 ];
 
 for (let f of typedArrays) {
-  assertGetterName('get buffer', f.prototype, 'buffer');
-  assertGetterName('get byteOffset', f.prototype, 'byteOffset');
-  assertGetterName('get byteLength', f.prototype, 'byteLength');
-  assertGetterName('get length', f.prototype, 'length');
-  assertGetterName('get [Symbol.toStringTag]', f.prototype, Symbol.toStringTag);
+  assertGetterName('get buffer', f.prototype, 'buffer', 1);
+  assertGetterName('get byteOffset', f.prototype, 'byteOffset', 1);
+  assertGetterName('get byteLength', f.prototype, 'byteLength', 1);
+  assertGetterName('get length', f.prototype, 'length', 1);
+  assertGetterName('get [Symbol.toStringTag]', f.prototype, Symbol.toStringTag, 1);
 }
 
 
index 47edcb0..95bd157 100644 (file)
@@ -82,12 +82,7 @@ var functions = [
   // DataView,
   Date,
   Error,
-  Float32Array,
-  Float64Array,
   Function,
-  Int16Array,
-  Int32Array,
-  Int8Array,
   Map,
   Number,
   Object,
@@ -96,10 +91,6 @@ var functions = [
   Set,
   String,
   // Symbol, not constructible
-  Uint16Array,
-  Uint32Array,
-  Uint8Array,
-  Uint8ClampedArray,
   WeakMap,
   WeakSet,
 ];
@@ -109,6 +100,23 @@ for (var f of functions) {
   assertPrototypeOf(new f(), f.prototype);
 }
 
+var typedArrayConstructors = [
+  Float32Array,
+  Float64Array,
+  Int16Array,
+  Int32Array,
+  Int8Array,
+  Uint16Array,
+  Uint32Array,
+  Uint8Array,
+  Uint8ClampedArray,
+];
+
+for (var t of typedArrayConstructors) {
+  assertPrototypeOf(t, Uint8Array.__proto__);
+  assertPrototypeOf(new t(), t.prototype);
+}
+
 var p = new Promise(function() {});
 assertPrototypeOf(p, Promise.prototype);
 
index bac4268..cdbf102 100644 (file)
@@ -87,6 +87,14 @@ function MakeSharedTypedArray(constr, numElements) {
   return new constr(sab);
 }
 
+function getPropertyDescriptor(object, field, expectedDepth) {
+  for (var depth = 0; depth < expectedDepth; depth++) {
+    assertFalse(Object.hasOwnProperty(object, field));
+    object = object.__proto__;
+  }
+  return Object.getOwnPropertyDescriptor(object, field);
+}
+
 function TestTypedArray(constr, elementSize, typicalElement) {
   assertSame(elementSize, constr.BYTES_PER_ELEMENT);
 
@@ -203,8 +211,7 @@ function TestTypedArray(constr, elementSize, typicalElement) {
   var a = new constr(sab, 64*elementSize, 128);
   assertEquals("[object " + constr.name + "]",
       Object.prototype.toString.call(a));
-  var desc = Object.getOwnPropertyDescriptor(
-      constr.prototype, Symbol.toStringTag);
+  var desc = getPropertyDescriptor(constr.prototype, Symbol.toStringTag, 1);
   assertTrue(desc.configurable);
   assertFalse(desc.enumerable);
   assertFalse(!!desc.writable);
@@ -310,17 +317,13 @@ var typedArrayConstructors = [
 
 function TestPropertyTypeChecks(constructor) {
   function CheckProperty(name) {
-    var d = Object.getOwnPropertyDescriptor(constructor.prototype, name);
+    var d = getPropertyDescriptor(constructor.prototype, name, 1);
     var o = {};
     assertThrows(function() {d.get.call(o);}, TypeError);
     for (var i = 0; i < typedArrayConstructors.length; i++) {
       var ctor = typedArrayConstructors[i];
       var a = MakeSharedTypedArray(ctor, 10);
-      if (ctor === constructor) {
-        d.get.call(a); // shouldn't throw
-      } else {
-        assertThrows(function() {d.get.call(a);}, TypeError);
-      }
+      d.get.call(a); // shouldn't throw on any type
     }
   }
 
index 9df1d30..66f5e2a 100644 (file)
@@ -15,8 +15,16 @@ var typedArrayConstructors = [
   Int32Array,
   Uint8ClampedArray,
   Float32Array,
-  Float64Array];
+  Float64Array
+];
 
+function getPropertyDescriptor(object, field, expectedDepth) {
+  for (var depth = 0; depth < expectedDepth; depth++) {
+    assertFalse(Object.hasOwnProperty(object, field));
+    object = object.__proto__;
+  }
+  return Object.getOwnPropertyDescriptor(object, field);
+}
 
 function TestTypedArrayOf(constructor) {
   // %TypedArray%.of basics.
@@ -111,7 +119,7 @@ function TestTypedArrayOf(constructor) {
   assertEquals("pass", status);
 
   // Check superficial features of %TypedArray%.of.
-  var desc = Object.getOwnPropertyDescriptor(constructor, "of");
+  var desc = getPropertyDescriptor(constructor, "of", 1);
 
   assertEquals(desc.configurable, false);
   assertEquals(desc.enumerable, false);
index ef7955c..9b2cde6 100644 (file)
@@ -121,6 +121,14 @@ TestArrayBufferSlice();
 
 // Typed arrays
 
+function getPropertyDescriptor(object, field, expectedDepth) {
+  for (var depth = 0; depth < expectedDepth; depth++) {
+    assertFalse(Object.hasOwnProperty(object, field));
+    object = object.__proto__;
+  }
+  return Object.getOwnPropertyDescriptor(object, field);
+}
+
 function TestTypedArray(constr, elementSize, typicalElement) {
   assertSame(elementSize, constr.BYTES_PER_ELEMENT);
 
@@ -269,8 +277,7 @@ function TestTypedArray(constr, elementSize, typicalElement) {
   var a = new constr(ab, 64*elementSize, 128);
   assertEquals("[object " + constr.name + "]",
       Object.prototype.toString.call(a));
-  var desc = Object.getOwnPropertyDescriptor(
-      constr.prototype, Symbol.toStringTag);
+  var desc = getPropertyDescriptor(constr.prototype, Symbol.toStringTag, 1);
   assertTrue(desc.configurable);
   assertFalse(desc.enumerable);
   assertFalse(!!desc.writable);
@@ -417,17 +424,13 @@ var typedArrayConstructors = [
 
 function TestPropertyTypeChecks(constructor) {
   function CheckProperty(name) {
-    var d = Object.getOwnPropertyDescriptor(constructor.prototype, name);
+    var d = getPropertyDescriptor(constructor.prototype, name, 1);
     var o = {};
     assertThrows(function() {d.get.call(o);}, TypeError);
     for (var i = 0; i < typedArrayConstructors.length; i++) {
       var ctor = typedArrayConstructors[i];
       var a = new ctor(10);
-      if (ctor === constructor) {
-        d.get.call(a); // shouldn't throw
-      } else {
-        assertThrows(function() {d.get.call(a);}, TypeError);
-      }
+      d.get.call(a); // shouldn't throw, even from a different type
     }
   }
 
index cae5573..62acb7d 100644 (file)
@@ -71,14 +71,6 @@ assertEquals(undefined, get(a));
   assertEquals(undefined, get(a));
 })();
 
-// Ensure we cannot delete length, byteOffset, byteLength.
-assertTrue(Int32Array.prototype.hasOwnProperty("length"));
-assertTrue(Int32Array.prototype.hasOwnProperty("byteOffset"));
-assertTrue(Int32Array.prototype.hasOwnProperty("byteLength"));
-assertFalse(delete Int32Array.prototype.length);
-assertFalse(delete Int32Array.prototype.byteOffset);
-assertFalse(delete Int32Array.prototype.byteLength);
-
 a = new Int32Array(100);
 
 get = function(a) {
@@ -110,3 +102,13 @@ assertEquals(0, get(a));
 assertEquals(0, get(a));
 %OptimizeFunctionOnNextCall(get);
 assertEquals(0, get(a));
+
+// Ensure we can delete length, byteOffset, byteLength.
+for (var name of ['length', 'byteOffset', 'byteLength', 'buffer']) {
+  var property = Object.getOwnPropertyDescriptor(
+                     Int32Array.prototype.__proto__, name);
+  assertEquals("object", typeof property);
+  assertEquals(true, property.configurable);
+  assertEquals(false, property.enumerable);
+  assertEquals("function", typeof property.get);
+}