Neutering API for v8::ArrayBuffer
R=svenpanne@chromium.org Review URL: https://codereview.chromium.org/16562005 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15006 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
17cfe68015
commit
cbb11dbe6c
@ -2431,6 +2431,14 @@ class V8EXPORT ArrayBuffer : public Object {
|
||||
*/
|
||||
bool IsExternal() const;
|
||||
|
||||
/**
|
||||
* Neuters this ArrayBuffer and all its views (typed arrays).
|
||||
* Neutering sets the byte length of the buffer and all typed arrays to zero,
|
||||
* preventing JavaScript from ever accessing underlying backing store.
|
||||
* ArrayBuffer should have been externalized.
|
||||
*/
|
||||
void Neuter();
|
||||
|
||||
/**
|
||||
* Pass the ownership of this ArrayBuffer's backing store to
|
||||
* a given ArrayBufferContents.
|
||||
|
19
src/api.cc
19
src/api.cc
@ -6112,6 +6112,25 @@ void v8::ArrayBuffer::Externalize(ArrayBufferContents* contents) {
|
||||
}
|
||||
|
||||
|
||||
void v8::ArrayBuffer::Neuter() {
|
||||
i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
|
||||
i::Isolate* isolate = obj->GetIsolate();
|
||||
ApiCheck(obj->is_external(),
|
||||
"v8::ArrayBuffer::Neuter",
|
||||
"Only externalized ArrayBuffers can be neutered");
|
||||
LOG_API(obj->GetIsolate(), "v8::ArrayBuffer::Neuter()");
|
||||
ENTER_V8(isolate);
|
||||
|
||||
for (i::Handle<i::Object> array_obj(obj->weak_first_array(), isolate);
|
||||
*array_obj != i::Smi::FromInt(0);) {
|
||||
i::Handle<i::JSTypedArray> typed_array(i::JSTypedArray::cast(*array_obj));
|
||||
typed_array->Neuter();
|
||||
array_obj = i::handle(typed_array->weak_next(), isolate);
|
||||
}
|
||||
obj->Neuter();
|
||||
}
|
||||
|
||||
|
||||
size_t v8::ArrayBuffer::ByteLength() const {
|
||||
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
|
||||
if (IsDeadCheck(isolate, "v8::ArrayBuffer::ByteLength()")) return 0;
|
||||
|
@ -15777,4 +15777,19 @@ void JSDate::SetLocalFields(int64_t local_time_ms, DateCache* date_cache) {
|
||||
set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
|
||||
}
|
||||
|
||||
|
||||
void JSArrayBuffer::Neuter() {
|
||||
ASSERT(is_external());
|
||||
set_backing_store(NULL);
|
||||
set_byte_length(Smi::FromInt(0));
|
||||
}
|
||||
|
||||
|
||||
void JSTypedArray::Neuter() {
|
||||
set_byte_offset(Smi::FromInt(0));
|
||||
set_byte_length(Smi::FromInt(0));
|
||||
set_length(Smi::FromInt(0));
|
||||
set_elements(GetHeap()->EmptyExternalArrayForMap(map()));
|
||||
}
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
@ -8813,6 +8813,9 @@ class JSArrayBuffer: public JSObject {
|
||||
// Casting.
|
||||
static inline JSArrayBuffer* cast(Object* obj);
|
||||
|
||||
// Neutering. Only neuters the buffer, not associated typed arrays.
|
||||
void Neuter();
|
||||
|
||||
// Dispatched behavior.
|
||||
DECLARE_PRINTER(JSArrayBuffer)
|
||||
DECLARE_VERIFIER(JSArrayBuffer)
|
||||
@ -8852,6 +8855,9 @@ class JSTypedArray: public JSObject {
|
||||
// [weak_next]: linked list of typed arrays over the same array buffer.
|
||||
DECL_ACCESSORS(weak_next, Object)
|
||||
|
||||
// Neutering. Only neuters this typed array.
|
||||
void Neuter();
|
||||
|
||||
// Casting.
|
||||
static inline JSTypedArray* cast(Object* obj);
|
||||
|
||||
|
@ -2657,6 +2657,122 @@ THREADED_TEST(ArrayBuffer_External) {
|
||||
}
|
||||
|
||||
|
||||
static void CheckIsNeutered(v8::Handle<v8::TypedArray> ta) {
|
||||
CHECK_EQ(0, static_cast<int>(ta->ByteLength()));
|
||||
CHECK_EQ(0, static_cast<int>(ta->Length()));
|
||||
CHECK_EQ(0, static_cast<int>(ta->ByteOffset()));
|
||||
}
|
||||
|
||||
template <typename TypedArray, int kElementSize>
|
||||
static Handle<TypedArray> CreateAndCheck(Handle<v8::ArrayBuffer> ab,
|
||||
int byteOffset,
|
||||
int length) {
|
||||
v8::Handle<TypedArray> ta = TypedArray::New(ab, byteOffset, length);
|
||||
CHECK_EQ(byteOffset, static_cast<int>(ta->ByteOffset()));
|
||||
CHECK_EQ(length, static_cast<int>(ta->Length()));
|
||||
CHECK_EQ(length * kElementSize, static_cast<int>(ta->ByteLength()));
|
||||
return ta;
|
||||
}
|
||||
|
||||
|
||||
THREADED_TEST(ArrayBuffer_NeuteringApi) {
|
||||
LocalContext env;
|
||||
v8::Isolate* isolate = env->GetIsolate();
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
|
||||
v8::Handle<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(1024);
|
||||
|
||||
v8::Handle<v8::Uint8Array> u8a =
|
||||
CreateAndCheck<v8::Uint8Array, 1>(buffer, 1, 1023);
|
||||
v8::Handle<v8::Uint8ClampedArray> u8c =
|
||||
CreateAndCheck<v8::Uint8ClampedArray, 1>(buffer, 1, 1023);
|
||||
v8::Handle<v8::Int8Array> i8a =
|
||||
CreateAndCheck<v8::Int8Array, 1>(buffer, 1, 1023);
|
||||
|
||||
v8::Handle<v8::Uint16Array> u16a =
|
||||
CreateAndCheck<v8::Uint16Array, 2>(buffer, 2, 511);
|
||||
v8::Handle<v8::Int16Array> i16a =
|
||||
CreateAndCheck<v8::Int16Array, 2>(buffer, 2, 511);
|
||||
|
||||
v8::Handle<v8::Uint32Array> u32a =
|
||||
CreateAndCheck<v8::Uint32Array, 4>(buffer, 4, 255);
|
||||
v8::Handle<v8::Int32Array> i32a =
|
||||
CreateAndCheck<v8::Int32Array, 4>(buffer, 4, 255);
|
||||
|
||||
v8::Handle<v8::Float32Array> f32a =
|
||||
CreateAndCheck<v8::Float32Array, 4>(buffer, 4, 255);
|
||||
v8::Handle<v8::Float64Array> f64a =
|
||||
CreateAndCheck<v8::Float64Array, 8>(buffer, 8, 127);
|
||||
|
||||
v8::ArrayBufferContents contents;
|
||||
buffer->Externalize(&contents);
|
||||
buffer->Neuter();
|
||||
CHECK_EQ(0, static_cast<int>(buffer->ByteLength()));
|
||||
CheckIsNeutered(u8a);
|
||||
CheckIsNeutered(u8c);
|
||||
CheckIsNeutered(i8a);
|
||||
CheckIsNeutered(u16a);
|
||||
CheckIsNeutered(i16a);
|
||||
CheckIsNeutered(u32a);
|
||||
CheckIsNeutered(i32a);
|
||||
CheckIsNeutered(f32a);
|
||||
CheckIsNeutered(f64a);
|
||||
}
|
||||
|
||||
THREADED_TEST(ArrayBuffer_NeuteringScript) {
|
||||
LocalContext env;
|
||||
v8::Isolate* isolate = env->GetIsolate();
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
|
||||
CompileRun(
|
||||
"var ab = new ArrayBuffer(1024);"
|
||||
"var u8a = new Uint8Array(ab, 1, 1023);"
|
||||
"var u8c = new Uint8ClampedArray(ab, 1, 1023);"
|
||||
"var i8a = new Int8Array(ab, 1, 1023);"
|
||||
"var u16a = new Uint16Array(ab, 2, 511);"
|
||||
"var i16a = new Int16Array(ab, 2, 511);"
|
||||
"var u32a = new Uint32Array(ab, 4, 255);"
|
||||
"var i32a = new Int32Array(ab, 4, 255);"
|
||||
"var f32a = new Float32Array(ab, 4, 255);"
|
||||
"var f64a = new Float64Array(ab, 8, 127);");
|
||||
|
||||
v8::Handle<v8::ArrayBuffer> ab(v8::ArrayBuffer::Cast(*CompileRun("ab")));
|
||||
|
||||
v8::Handle<v8::Uint8Array> u8a(v8::Uint8Array::Cast(*CompileRun("u8a")));
|
||||
v8::Handle<v8::Uint8ClampedArray> u8c(
|
||||
v8::Uint8ClampedArray::Cast(*CompileRun("u8c")));
|
||||
v8::Handle<v8::Int8Array> i8a(v8::Int8Array::Cast(*CompileRun("i8a")));
|
||||
|
||||
v8::Handle<v8::Uint16Array> u16a(
|
||||
v8::Uint16Array::Cast(*CompileRun("u16a")));
|
||||
v8::Handle<v8::Int16Array> i16a(
|
||||
v8::Int16Array::Cast(*CompileRun("i16a")));
|
||||
v8::Handle<v8::Uint32Array> u32a(
|
||||
v8::Uint32Array::Cast(*CompileRun("u32a")));
|
||||
v8::Handle<v8::Int32Array> i32a(
|
||||
v8::Int32Array::Cast(*CompileRun("i32a")));
|
||||
v8::Handle<v8::Float32Array> f32a(
|
||||
v8::Float32Array::Cast(*CompileRun("f32a")));
|
||||
v8::Handle<v8::Float64Array> f64a(
|
||||
v8::Float64Array::Cast(*CompileRun("f64a")));
|
||||
|
||||
v8::ArrayBufferContents contents;
|
||||
ab->Externalize(&contents);
|
||||
ab->Neuter();
|
||||
CHECK_EQ(0, static_cast<int>(ab->ByteLength()));
|
||||
CheckIsNeutered(u8a);
|
||||
CheckIsNeutered(u8c);
|
||||
CheckIsNeutered(i8a);
|
||||
CheckIsNeutered(u16a);
|
||||
CheckIsNeutered(i16a);
|
||||
CheckIsNeutered(u32a);
|
||||
CheckIsNeutered(i32a);
|
||||
CheckIsNeutered(f32a);
|
||||
CheckIsNeutered(f64a);
|
||||
}
|
||||
|
||||
|
||||
|
||||
THREADED_TEST(HiddenProperties) {
|
||||
LocalContext env;
|
||||
v8::HandleScope scope(env->GetIsolate());
|
||||
|
Loading…
Reference in New Issue
Block a user