Commit 3235ccbb authored by bmeurer's avatar bmeurer Committed by Commit bot

[es6] Correctify and unify ArrayBuffer and SharedArrayBuffer constructors.

The ArrayBuffer and SharedArrayBuffer constructors should raise an
exception when called with no arguments or undefined length.  Also
unified the ArrayBuffer and SharedArrayBuffer implementations as C++
builtins, and removed some (now) obsolete runtime entries.

R=yangguo@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#32590}
parent 9290dd82
......@@ -204,6 +204,8 @@ class Genesis BASE_EMBEDDED {
HARMONY_SHIPPING(DECLARE_FEATURE_INITIALIZATION)
#undef DECLARE_FEATURE_INITIALIZATION
Handle<JSFunction> InstallArrayBuffer(Handle<JSObject> target,
const char* name);
Handle<JSFunction> InstallInternalArray(Handle<JSObject> target,
const char* name,
ElementsKind elements_kind);
......@@ -1248,11 +1250,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
{ // -- A r r a y B u f f e r
Handle<JSFunction> array_buffer_fun =
InstallFunction(
global, "ArrayBuffer", JS_ARRAY_BUFFER_TYPE,
JSArrayBuffer::kSizeWithInternalFields,
isolate->initial_object_prototype(),
Builtins::kIllegal);
InstallArrayBuffer(global, "ArrayBuffer");
native_context()->set_array_buffer_fun(*array_buffer_fun);
}
......@@ -2067,13 +2065,9 @@ void Genesis::InitializeGlobal_harmony_reflect() {
void Genesis::InitializeGlobal_harmony_sharedarraybuffer() {
if (!FLAG_harmony_sharedarraybuffer) return;
Handle<JSGlobalObject> global(
JSGlobalObject::cast(native_context()->global_object()));
Handle<JSFunction> shared_array_buffer_fun = InstallFunction(
global, "SharedArrayBuffer", JS_ARRAY_BUFFER_TYPE,
JSArrayBuffer::kSizeWithInternalFields,
isolate()->initial_object_prototype(), Builtins::kIllegal);
Handle<JSGlobalObject> global(native_context()->global_object());
Handle<JSFunction> shared_array_buffer_fun =
InstallArrayBuffer(global, "SharedArrayBuffer");
native_context()->set_shared_array_buffer_fun(*shared_array_buffer_fun);
}
......@@ -2127,6 +2121,39 @@ void Genesis::InitializeGlobal_harmony_proxies() {
}
Handle<JSFunction> Genesis::InstallArrayBuffer(Handle<JSObject> target,
const char* name) {
// Setup the {prototype} with the given {name} for @@toStringTag.
Handle<JSObject> prototype =
factory()->NewJSObject(isolate()->object_function(), TENURED);
JSObject::AddProperty(prototype, factory()->to_string_tag_symbol(),
factory()->NewStringFromAsciiChecked(name),
static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY));
// Allocate the constructor with the given {prototype}.
Handle<JSFunction> array_buffer_fun =
InstallFunction(target, name, JS_ARRAY_BUFFER_TYPE,
JSArrayBuffer::kSizeWithInternalFields, prototype,
Builtins::kArrayBufferConstructor);
array_buffer_fun->shared()->set_construct_stub(
*isolate()->builtins()->ArrayBufferConstructor_ConstructStub());
array_buffer_fun->shared()->set_internal_formal_parameter_count(1);
array_buffer_fun->shared()->set_length(1);
// Install the "constructor" property on the {prototype}.
JSObject::AddProperty(prototype, factory()->constructor_string(),
array_buffer_fun, DONT_ENUM);
Handle<JSFunction> array_buffer_is_view_fun = InstallFunction(
array_buffer_fun, "isView", JS_OBJECT_TYPE, JSObject::kHeaderSize,
MaybeHandle<JSObject>(), Builtins::kArrayBufferIsView);
array_buffer_is_view_fun->shared()->set_internal_formal_parameter_count(1);
array_buffer_is_view_fun->shared()->set_length(1);
return array_buffer_fun;
}
Handle<JSFunction> Genesis::InstallInternalArray(Handle<JSObject> target,
const char* name,
ElementsKind elements_kind) {
......
......@@ -1755,6 +1755,66 @@ BUILTIN(SymbolConstructor_ConstructStub) {
}
// ES6 section 24.1.2.1 ArrayBuffer( length ) for the [[Call]] case.
BUILTIN(ArrayBufferConstructor) {
HandleScope scope(isolate);
Handle<JSFunction> target = args.target();
DCHECK(*target == target->native_context()->array_buffer_fun() ||
*target == target->native_context()->shared_array_buffer_fun());
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kConstructorNotFunction,
handle(target->shared()->name(), isolate)));
}
// ES6 section 24.1.2.1 ArrayBuffer( length ) for the [[Construct]] case.
BUILTIN(ArrayBufferConstructor_ConstructStub) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
Handle<JSFunction> target = args.target();
Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
Handle<Object> length = args.at<Object>(1);
DCHECK(*target == target->native_context()->array_buffer_fun() ||
*target == target->native_context()->shared_array_buffer_fun());
// The ConstructStub is executed in the context of the caller, so we need
// to enter the callee context first before raising an exception.
isolate->set_context(args.target()->context());
Handle<Object> number_length;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, number_length,
Object::ToNumber(length));
size_t byte_length;
if (!TryNumberToSize(isolate, *number_length, &byte_length)) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength));
}
Handle<Map> initial_map;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, initial_map,
JSFunction::GetDerivedMap(isolate, target, new_target));
Handle<JSArrayBuffer> result = Handle<JSArrayBuffer>::cast(
isolate->factory()->NewJSObjectFromMap(initial_map));
SharedFlag shared_flag =
(*target == target->native_context()->array_buffer_fun())
? SharedFlag::kNotShared
: SharedFlag::kShared;
if (!JSArrayBuffer::SetupAllocatingData(result, isolate, byte_length, true,
shared_flag)) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewRangeError(MessageTemplate::kArrayBufferAllocationFailed));
}
return *result;
}
// ES6 section 24.1.3.1 ArrayBuffer.isView ( arg )
BUILTIN(ArrayBufferIsView) {
SealHandleScope shs(isolate);
DCHECK_EQ(2, args.length());
Object* arg = args[1];
return isolate->heap()->ToBoolean(arg->IsJSArrayBufferView());
}
namespace {
// ES6 section 9.5.15 ProxyCreate (target, handler)
......
......@@ -51,46 +51,50 @@ inline bool operator&(BuiltinExtraArguments lhs, BuiltinExtraArguments rhs) {
// Define list of builtins implemented in C++.
#define BUILTIN_LIST_C(V) \
V(Illegal, kNone) \
\
V(EmptyFunction, kNone) \
\
V(ArrayConcat, kNone) \
V(ArrayIsArray, kNone) \
V(ArrayPop, kNone) \
V(ArrayPush, kNone) \
V(ArrayShift, kNone) \
V(ArraySlice, kNone) \
V(ArraySplice, kNone) \
V(ArrayUnshift, kNone) \
\
V(DateToPrimitive, kNone) \
\
V(ProxyConstructor, kNone) \
V(ProxyConstructor_ConstructStub, kTarget) \
\
V(ReflectDefineProperty, kNone) \
V(ReflectDeleteProperty, kNone) \
V(ReflectGet, kNone) \
V(ReflectGetOwnPropertyDescriptor, kNone) \
V(ReflectGetPrototypeOf, kNone) \
V(ReflectHas, kNone) \
V(ReflectIsExtensible, kNone) \
V(ReflectOwnKeys, kNone) \
V(ReflectPreventExtensions, kNone) \
V(ReflectSet, kNone) \
V(ReflectSetPrototypeOf, kNone) \
\
V(SymbolConstructor, kNone) \
V(SymbolConstructor_ConstructStub, kTarget) \
\
V(HandleApiCall, kTarget) \
V(HandleApiCallConstruct, kTarget) \
V(HandleApiCallAsFunction, kNone) \
V(HandleApiCallAsConstructor, kNone) \
\
V(RestrictedFunctionPropertiesThrower, kNone) \
#define BUILTIN_LIST_C(V) \
V(Illegal, kNone) \
\
V(EmptyFunction, kNone) \
\
V(ArrayConcat, kNone) \
V(ArrayIsArray, kNone) \
V(ArrayPop, kNone) \
V(ArrayPush, kNone) \
V(ArrayShift, kNone) \
V(ArraySlice, kNone) \
V(ArraySplice, kNone) \
V(ArrayUnshift, kNone) \
\
V(ArrayBufferConstructor, kTarget) \
V(ArrayBufferConstructor_ConstructStub, kTargetAndNewTarget) \
V(ArrayBufferIsView, kNone) \
\
V(DateToPrimitive, kNone) \
\
V(ProxyConstructor, kNone) \
V(ProxyConstructor_ConstructStub, kTarget) \
\
V(ReflectDefineProperty, kNone) \
V(ReflectDeleteProperty, kNone) \
V(ReflectGet, kNone) \
V(ReflectGetOwnPropertyDescriptor, kNone) \
V(ReflectGetPrototypeOf, kNone) \
V(ReflectHas, kNone) \
V(ReflectIsExtensible, kNone) \
V(ReflectOwnKeys, kNone) \
V(ReflectPreventExtensions, kNone) \
V(ReflectSet, kNone) \
V(ReflectSetPrototypeOf, kNone) \
\
V(SymbolConstructor, kNone) \
V(SymbolConstructor_ConstructStub, kTarget) \
\
V(HandleApiCall, kTarget) \
V(HandleApiCallConstruct, kTarget) \
V(HandleApiCallAsFunction, kNone) \
V(HandleApiCallAsConstructor, kNone) \
\
V(RestrictedFunctionPropertiesThrower, kNone) \
V(RestrictedStrictArgumentsPropertiesThrower, kNone)
// Define list of builtins implemented in assembly.
......
......@@ -12,31 +12,18 @@
// Imports
var GlobalArrayBuffer = global.ArrayBuffer;
var GlobalObject = global.Object;
var MakeTypeError;
var MaxSimple;
var MinSimple;
var ToPositiveInteger;
var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
utils.Import(function(from) {
MakeTypeError = from.MakeTypeError;
MaxSimple = from.MaxSimple;
MinSimple = from.MinSimple;
ToPositiveInteger = from.ToPositiveInteger;
});
// -------------------------------------------------------------------
function ArrayBufferConstructor(length) { // length = 1
if (!IS_UNDEFINED(new.target)) {
var byteLength = ToPositiveInteger(length, kInvalidArrayBufferLength);
%ArrayBufferInitialize(this, byteLength, kNotShared);
} else {
throw MakeTypeError(kConstructorNotFunction, "ArrayBuffer");
}
}
function ArrayBufferGetByteLen() {
if (!IS_ARRAYBUFFER(this)) {
throw MakeTypeError(kIncompatibleMethodReceiver,
......@@ -82,29 +69,9 @@ function ArrayBufferSlice(start, end) {
return result;
}
function ArrayBufferIsViewJS(obj) {
return %ArrayBufferIsView(obj);
}
// Set up the ArrayBuffer constructor function.
%SetCode(GlobalArrayBuffer, ArrayBufferConstructor);
%FunctionSetPrototype(GlobalArrayBuffer, new GlobalObject());
// Set up the constructor property on the ArrayBuffer prototype object.
%AddNamedProperty(
GlobalArrayBuffer.prototype, "constructor", GlobalArrayBuffer, DONT_ENUM);
%AddNamedProperty(GlobalArrayBuffer.prototype,
toStringTagSymbol, "ArrayBuffer", DONT_ENUM | READ_ONLY);
utils.InstallGetter(GlobalArrayBuffer.prototype, "byteLength",
ArrayBufferGetByteLen);
utils.InstallFunctions(GlobalArrayBuffer, DONT_ENUM, [
"isView", ArrayBufferIsViewJS
]);
utils.InstallFunctions(GlobalArrayBuffer.prototype, DONT_ENUM, [
"slice", ArrayBufferSlice
]);
......
......@@ -9,27 +9,14 @@
%CheckIsBootstrapping();
var GlobalSharedArrayBuffer = global.SharedArrayBuffer;
var GlobalObject = global.Object;
var MakeTypeError;
var ToPositiveInteger;
var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
utils.Import(function(from) {
MakeTypeError = from.MakeTypeError;
ToPositiveInteger = from.ToPositiveInteger;
})
// -------------------------------------------------------------------
function SharedArrayBufferConstructor(length) { // length = 1
if (!IS_UNDEFINED(new.target)) {
var byteLength = ToPositiveInteger(length, kInvalidArrayBufferLength);
%ArrayBufferInitialize(this, byteLength, kShared);
} else {
throw MakeTypeError(kConstructorNotFunction, "SharedArrayBuffer");
}
}
function SharedArrayBufferGetByteLen() {
if (!IS_SHAREDARRAYBUFFER(this)) {
throw MakeTypeError(kIncompatibleMethodReceiver,
......@@ -38,27 +25,7 @@ function SharedArrayBufferGetByteLen() {
return %_ArrayBufferGetByteLength(this);
}
function SharedArrayBufferIsViewJS(obj) {
return %ArrayBufferIsView(obj);
}
// Set up the SharedArrayBuffer constructor function.
%SetCode(GlobalSharedArrayBuffer, SharedArrayBufferConstructor);
%FunctionSetPrototype(GlobalSharedArrayBuffer, new GlobalObject());
// Set up the constructor property on the SharedArrayBuffer prototype object.
%AddNamedProperty(GlobalSharedArrayBuffer.prototype, "constructor",
GlobalSharedArrayBuffer, DONT_ENUM);
%AddNamedProperty(GlobalSharedArrayBuffer.prototype,
toStringTagSymbol, "SharedArrayBuffer", DONT_ENUM | READ_ONLY);
utils.InstallGetter(GlobalSharedArrayBuffer.prototype, "byteLength",
SharedArrayBufferGetByteLen);
utils.InstallFunctions(GlobalSharedArrayBuffer, DONT_ENUM, [
"isView", SharedArrayBufferIsViewJS
]);
})
......@@ -13,32 +13,6 @@
namespace v8 {
namespace internal {
RUNTIME_FUNCTION(Runtime_ArrayBufferInitialize) {
HandleScope scope(isolate);
DCHECK(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, holder, 0);
CONVERT_NUMBER_ARG_HANDLE_CHECKED(byteLength, 1);
CONVERT_BOOLEAN_ARG_CHECKED(is_shared, 2);
if (!holder->byte_length()->IsUndefined()) {
// ArrayBuffer is already initialized; probably a fuzz test.
return *holder;
}
size_t allocated_length = 0;
if (!TryNumberToSize(isolate, *byteLength, &allocated_length)) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength));
}
if (!JSArrayBuffer::SetupAllocatingData(
holder, isolate, allocated_length, true,
is_shared ? SharedFlag::kShared : SharedFlag::kNotShared)) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewRangeError(MessageTemplate::kArrayBufferAllocationFailed));
}
return *holder;
}
RUNTIME_FUNCTION(Runtime_ArrayBufferGetByteLength) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 1);
......@@ -70,14 +44,6 @@ RUNTIME_FUNCTION(Runtime_ArrayBufferSliceImpl) {
}
RUNTIME_FUNCTION(Runtime_ArrayBufferIsView) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_CHECKED(Object, object, 0);
return isolate->heap()->ToBoolean(object->IsJSArrayBufferView());
}
RUNTIME_FUNCTION(Runtime_ArrayBufferNeuter) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
......
......@@ -988,10 +988,8 @@ namespace internal {
#define FOR_EACH_INTRINSIC_TYPEDARRAY(F) \
F(ArrayBufferInitialize, 3, 1) \
F(ArrayBufferGetByteLength, 1, 1) \
F(ArrayBufferSliceImpl, 3, 1) \
F(ArrayBufferIsView, 1, 1) \
F(ArrayBufferNeuter, 1, 1) \
F(TypedArrayInitialize, 6, 1) \
F(TypedArrayInitializeFromArrayLike, 4, 1) \
......
......@@ -8,4 +8,4 @@
var MEM = new Uint8ClampedArray(heap);
function foo( ) { MEM[0] ^= 1; }
return {foo: foo};
})(this, {}, new ArrayBuffer( ) ).foo();
})(this, {}, new ArrayBuffer(0) ).foo();
......@@ -436,7 +436,7 @@ function TestMapSetSubclassing(container, is_map) {
assertEquals(4.2, o.d);
assertEquals(153, o.o.foo);
var o1 = new A("bar");
var o1 = new A(8);
assertTrue(%HaveSameMap(o, o1));
......
......@@ -39,7 +39,7 @@ function TestArrayBufferCreation() {
TestByteLength(256, 256);
TestByteLength(2.567, 2);
TestByteLength("abc", 0);
TestByteLength("0", 0);
TestByteLength(0, 0);
......@@ -52,7 +52,7 @@ function TestArrayBufferCreation() {
}, RangeError);
*/
var ab = new ArrayBuffer();
var ab = new ArrayBuffer(0);
assertSame(0, ab.byteLength);
assertEquals("[object ArrayBuffer]",
Object.prototype.toString.call(ab));
......@@ -729,11 +729,11 @@ function TestEnumerable(func, obj) {
if (obj)
assertArrayEquals([], props(obj));
}
TestEnumerable(ArrayBuffer, new ArrayBuffer());
TestEnumerable(ArrayBuffer, new ArrayBuffer(0));
for(i = 0; i < typedArrayConstructors.length; i++) {
TestEnumerable(typedArrayConstructors[i]);
}
TestEnumerable(DataView, new DataView(new ArrayBuffer()));
TestEnumerable(DataView, new DataView(new ArrayBuffer(0)));
// Test arbitrary properties on ArrayBuffer
function TestArbitrary(m) {
......@@ -754,8 +754,8 @@ TestArbitrary(new DataView(new ArrayBuffer(256)));
// Test direct constructor call
assertThrows(function() { ArrayBuffer(); }, TypeError);
assertThrows(function() { DataView(new ArrayBuffer()); }, TypeError);
assertThrows(function() { ArrayBuffer(0); }, TypeError);
assertThrows(function() { DataView(new ArrayBuffer(0)); }, TypeError);
function TestNonConfigurableProperties(constructor) {
var arr = new constructor([100])
......
......@@ -77,7 +77,6 @@ for (var f of errorFunctions) {
// Builtin constructors.
var functions = [
Array,
ArrayBuffer,
Boolean,
// DataView,
Date,
......@@ -112,5 +111,8 @@ for (var f of functions) {
var p = new Promise(function() {});
assertPrototypeOf(p, Promise.prototype);
var dv = new DataView(new ArrayBuffer());
var ab = new ArrayBuffer(0);
assertPrototypeOf(ab, ArrayBuffer.prototype);
var dv = new DataView(ab);
assertPrototypeOf(dv, DataView.prototype);
......@@ -100,7 +100,6 @@ for (var f of errorFunctions) {
// Builtin constructors.
var functions = [
Array,
ArrayBuffer,
Boolean,
// DataView,
Date,
......@@ -135,5 +134,8 @@ for (var f of functions) {
var p = new Promise(function() {});
assertPrototypeOf(p, Promise.prototype);
var dv = new DataView(new ArrayBuffer());
var ab = new ArrayBuffer(0);
assertPrototypeOf(ab, ArrayBuffer.prototype);
var dv = new DataView(ab);
assertPrototypeOf(dv, DataView.prototype);
......@@ -40,7 +40,7 @@ function TestArrayBufferCreation() {
TestByteLength(256, 256);
TestByteLength(2.567, 2);
TestByteLength("abc", 0);
TestByteLength("0", 0);
TestByteLength(0, 0);
......@@ -53,7 +53,7 @@ function TestArrayBufferCreation() {
}, RangeError);
*/
var sab = new SharedArrayBuffer();
var sab = new SharedArrayBuffer(0);
assertSame(0, sab.byteLength);
assertEquals("[object SharedArrayBuffer]",
Object.prototype.toString.call(sab));
......@@ -548,7 +548,7 @@ function TestEnumerable(func, obj) {
if (obj)
assertArrayEquals([], props(obj));
}
TestEnumerable(ArrayBuffer, new SharedArrayBuffer());
TestEnumerable(ArrayBuffer, new SharedArrayBuffer(0));
for(i = 0; i < typedArrayConstructors.length; i++) {
TestEnumerable(typedArrayConstructors[i]);
}
......
......@@ -4,6 +4,6 @@
if (this.Worker) {
var worker = new Worker("onmessage = function(){}");
var buf = new ArrayBuffer();
var buf = new ArrayBuffer(0);
worker.postMessage(buf, [buf]);
}
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