Commit a1059015 authored by littledan's avatar littledan Committed by Commit bot

Add %TypedArray% to proto chain

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}
parent bc847230
......@@ -11,25 +11,21 @@
// -------------------------------------------------------------------
// 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
]);
})
......@@ -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);
......
......@@ -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);
......
......@@ -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
......
......@@ -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);
}
......
......@@ -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);
......
......@@ -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
}
}
......
......@@ -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);
......
......@@ -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
}
}
......
......@@ -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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment