| Index: test/cctest/test-api.cc
|
| diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
|
| index 00585bfa45cd5649ad9b6b5d66998eb8531f1edf..71d1b273196f93e27810b23b9aa2ab4513fa1145 100644
|
| --- a/test/cctest/test-api.cc
|
| +++ b/test/cctest/test-api.cc
|
| @@ -141,10 +141,13 @@ static void ExpectUndefined(const char* code) {
|
|
|
|
|
| static int signature_callback_count;
|
| +static Local<Value> signature_expected_receiver;
|
| static void IncrementingSignatureCallback(
|
| const v8::FunctionCallbackInfo<v8::Value>& args) {
|
| ApiTestFuzzer::Fuzz();
|
| signature_callback_count++;
|
| + CHECK_EQ(signature_expected_receiver, args.Holder());
|
| + CHECK_EQ(signature_expected_receiver, args.This());
|
| v8::Handle<v8::Array> result = v8::Array::New(args.Length());
|
| for (int i = 0; i < args.Length(); i++)
|
| result->Set(v8::Integer::New(i), args[i]);
|
| @@ -163,6 +166,24 @@ static void SignatureCallback(
|
| }
|
|
|
|
|
| +// Tests that call v8::V8::Dispose() cannot be threaded.
|
| +TEST(InitializeAndDisposeOnce) {
|
| + CHECK(v8::V8::Initialize());
|
| + CHECK(v8::V8::Dispose());
|
| +}
|
| +
|
| +
|
| +// Tests that call v8::V8::Dispose() cannot be threaded.
|
| +TEST(InitializeAndDisposeMultiple) {
|
| + for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
|
| + for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
|
| + for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
|
| + // TODO(mstarzinger): This should fail gracefully instead of asserting.
|
| + // for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
|
| + for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
|
| +}
|
| +
|
| +
|
| THREADED_TEST(Handles) {
|
| v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| Local<Context> local_env;
|
| @@ -203,47 +224,98 @@ THREADED_TEST(IsolateOfContext) {
|
| }
|
|
|
|
|
| +static void TestSignature(const char* loop_js, Local<Value> receiver) {
|
| + i::ScopedVector<char> source(200);
|
| + i::OS::SNPrintF(source,
|
| + "for (var i = 0; i < 10; i++) {"
|
| + " %s"
|
| + "}",
|
| + loop_js);
|
| + signature_callback_count = 0;
|
| + signature_expected_receiver = receiver;
|
| + bool expected_to_throw = receiver.IsEmpty();
|
| + v8::TryCatch try_catch;
|
| + CompileRun(source.start());
|
| + CHECK_EQ(expected_to_throw, try_catch.HasCaught());
|
| + if (!expected_to_throw) {
|
| + CHECK_EQ(10, signature_callback_count);
|
| + } else {
|
| + CHECK_EQ(v8_str("TypeError: Illegal invocation"),
|
| + try_catch.Exception()->ToString());
|
| + }
|
| +}
|
| +
|
| +
|
| THREADED_TEST(ReceiverSignature) {
|
| LocalContext env;
|
| v8::HandleScope scope(env->GetIsolate());
|
| + // Setup templates.
|
| v8::Handle<v8::FunctionTemplate> fun = v8::FunctionTemplate::New();
|
| v8::Handle<v8::Signature> sig = v8::Signature::New(fun);
|
| - fun->PrototypeTemplate()->Set(
|
| - v8_str("m"),
|
| - v8::FunctionTemplate::New(IncrementingSignatureCallback,
|
| - v8::Handle<Value>(),
|
| - sig));
|
| - env->Global()->Set(v8_str("Fun"), fun->GetFunction());
|
| - signature_callback_count = 0;
|
| - CompileRun(
|
| - "var o = new Fun();"
|
| - "o.m();");
|
| - CHECK_EQ(1, signature_callback_count);
|
| + v8::Handle<v8::FunctionTemplate> callback_sig =
|
| + v8::FunctionTemplate::New(
|
| + IncrementingSignatureCallback, Local<Value>(), sig);
|
| + v8::Handle<v8::FunctionTemplate> callback =
|
| + v8::FunctionTemplate::New(IncrementingSignatureCallback);
|
| v8::Handle<v8::FunctionTemplate> sub_fun = v8::FunctionTemplate::New();
|
| sub_fun->Inherit(fun);
|
| - env->Global()->Set(v8_str("SubFun"), sub_fun->GetFunction());
|
| - CompileRun(
|
| - "var o = new SubFun();"
|
| - "o.m();");
|
| - CHECK_EQ(2, signature_callback_count);
|
| -
|
| - v8::TryCatch try_catch;
|
| - CompileRun(
|
| - "var o = { };"
|
| - "o.m = Fun.prototype.m;"
|
| - "o.m();");
|
| - CHECK_EQ(2, signature_callback_count);
|
| - CHECK(try_catch.HasCaught());
|
| - try_catch.Reset();
|
| v8::Handle<v8::FunctionTemplate> unrel_fun = v8::FunctionTemplate::New();
|
| - sub_fun->Inherit(fun);
|
| + // Install properties.
|
| + v8::Handle<v8::ObjectTemplate> fun_proto = fun->PrototypeTemplate();
|
| + fun_proto->Set(v8_str("prop_sig"), callback_sig);
|
| + fun_proto->Set(v8_str("prop"), callback);
|
| + fun_proto->SetAccessorProperty(
|
| + v8_str("accessor_sig"), callback_sig, callback_sig);
|
| + fun_proto->SetAccessorProperty(v8_str("accessor"), callback, callback);
|
| + // Instantiate templates.
|
| + Local<Value> fun_instance = fun->InstanceTemplate()->NewInstance();
|
| + Local<Value> sub_fun_instance = sub_fun->InstanceTemplate()->NewInstance();
|
| + // Setup global variables.
|
| + env->Global()->Set(v8_str("Fun"), fun->GetFunction());
|
| env->Global()->Set(v8_str("UnrelFun"), unrel_fun->GetFunction());
|
| + env->Global()->Set(v8_str("fun_instance"), fun_instance);
|
| + env->Global()->Set(v8_str("sub_fun_instance"), sub_fun_instance);
|
| CompileRun(
|
| - "var o = new UnrelFun();"
|
| - "o.m = Fun.prototype.m;"
|
| - "o.m();");
|
| - CHECK_EQ(2, signature_callback_count);
|
| - CHECK(try_catch.HasCaught());
|
| + "var accessor_sig_key = 'accessor_sig';"
|
| + "var accessor_key = 'accessor';"
|
| + "var prop_sig_key = 'prop_sig';"
|
| + "var prop_key = 'prop';"
|
| + ""
|
| + "function copy_props(obj) {"
|
| + " var keys = [accessor_sig_key, accessor_key, prop_sig_key, prop_key];"
|
| + " var source = Fun.prototype;"
|
| + " for (var i in keys) {"
|
| + " var key = keys[i];"
|
| + " var desc = Object.getOwnPropertyDescriptor(source, key);"
|
| + " Object.defineProperty(obj, key, desc);"
|
| + " }"
|
| + "}"
|
| + ""
|
| + "var obj = {};"
|
| + "copy_props(obj);"
|
| + "var unrel = new UnrelFun();"
|
| + "copy_props(unrel);");
|
| + // Test with and without ICs
|
| + const char* test_objects[] = {
|
| + "fun_instance", "sub_fun_instance", "obj", "unrel" };
|
| + unsigned bad_signature_start_offset = 2;
|
| + for (unsigned i = 0; i < ARRAY_SIZE(test_objects); i++) {
|
| + i::ScopedVector<char> source(200);
|
| + i::OS::SNPrintF(
|
| + source, "var test_object = %s; test_object", test_objects[i]);
|
| + Local<Value> test_object = CompileRun(source.start());
|
| + TestSignature("test_object.prop();", test_object);
|
| + TestSignature("test_object.accessor;", test_object);
|
| + TestSignature("test_object[accessor_key];", test_object);
|
| + TestSignature("test_object.accessor = 1;", test_object);
|
| + TestSignature("test_object[accessor_key] = 1;", test_object);
|
| + if (i >= bad_signature_start_offset) test_object = Local<Value>();
|
| + TestSignature("test_object.prop_sig();", test_object);
|
| + TestSignature("test_object.accessor_sig;", test_object);
|
| + TestSignature("test_object[accessor_sig_key];", test_object);
|
| + TestSignature("test_object.accessor_sig = 1;", test_object);
|
| + TestSignature("test_object[accessor_sig_key] = 1;", test_object);
|
| + }
|
| }
|
|
|
|
|
| @@ -1828,7 +1900,17 @@ void InterceptorGetter(Local<String> name,
|
| void InterceptorSetter(Local<String> name,
|
| Local<Value> value,
|
| const v8::PropertyCallbackInfo<v8::Value>& info) {
|
| - // Intercept accesses that set certain integer values.
|
| + // Intercept accesses that set certain integer values, for which the name does
|
| + // not start with 'accessor_'.
|
| + String::Utf8Value utf8(name);
|
| + char* name_str = *utf8;
|
| + char prefix[] = "accessor_";
|
| + int i;
|
| + for (i = 0; name_str[i] && prefix[i]; ++i) {
|
| + if (name_str[i] != prefix[i]) break;
|
| + }
|
| + if (!prefix[i]) return;
|
| +
|
| if (value->IsInt32() && value->Int32Value() < 10000) {
|
| Handle<Object> self = info.This();
|
| self->SetHiddenValue(name, value);
|
| @@ -3108,7 +3190,7 @@ THREADED_TEST(ResettingGlobalHandle) {
|
| v8::HandleScope scope(isolate);
|
| CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 6);
|
| }
|
| - global.Dispose(isolate);
|
| + global.Dispose();
|
| CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
|
| }
|
|
|
| @@ -3242,7 +3324,7 @@ static void WeakPointerCallback(v8::Isolate* isolate,
|
| WeakCallCounter* counter) {
|
| CHECK_EQ(1234, counter->id());
|
| counter->increment();
|
| - handle->Dispose(isolate);
|
| + handle->Dispose();
|
| }
|
|
|
|
|
| @@ -3315,8 +3397,8 @@ THREADED_TEST(ApiObjectGroups) {
|
| root.MakeWeak(&counter, &WeakPointerCallback);
|
| // But make children strong roots---all the objects (except for children)
|
| // should be collectable now.
|
| - g1c1.ClearWeak(iso);
|
| - g2c1.ClearWeak(iso);
|
| + g1c1.ClearWeak();
|
| + g2c1.ClearWeak();
|
|
|
| // Groups are deleted, rebuild groups.
|
| {
|
| @@ -3366,29 +3448,29 @@ THREADED_TEST(ApiObjectGroupsCycle) {
|
| g1s2.Reset(iso, Object::New());
|
| g1s1.MakeWeak(&counter, &WeakPointerCallback);
|
| g1s2.MakeWeak(&counter, &WeakPointerCallback);
|
| - CHECK(g1s1.IsWeak(iso));
|
| - CHECK(g1s2.IsWeak(iso));
|
| + CHECK(g1s1.IsWeak());
|
| + CHECK(g1s2.IsWeak());
|
|
|
| g2s1.Reset(iso, Object::New());
|
| g2s2.Reset(iso, Object::New());
|
| g2s1.MakeWeak(&counter, &WeakPointerCallback);
|
| g2s2.MakeWeak(&counter, &WeakPointerCallback);
|
| - CHECK(g2s1.IsWeak(iso));
|
| - CHECK(g2s2.IsWeak(iso));
|
| + CHECK(g2s1.IsWeak());
|
| + CHECK(g2s2.IsWeak());
|
|
|
| g3s1.Reset(iso, Object::New());
|
| g3s2.Reset(iso, Object::New());
|
| g3s1.MakeWeak(&counter, &WeakPointerCallback);
|
| g3s2.MakeWeak(&counter, &WeakPointerCallback);
|
| - CHECK(g3s1.IsWeak(iso));
|
| - CHECK(g3s2.IsWeak(iso));
|
| + CHECK(g3s1.IsWeak());
|
| + CHECK(g3s2.IsWeak());
|
|
|
| g4s1.Reset(iso, Object::New());
|
| g4s2.Reset(iso, Object::New());
|
| g4s1.MakeWeak(&counter, &WeakPointerCallback);
|
| g4s2.MakeWeak(&counter, &WeakPointerCallback);
|
| - CHECK(g4s1.IsWeak(iso));
|
| - CHECK(g4s2.IsWeak(iso));
|
| + CHECK(g4s1.IsWeak());
|
| + CHECK(g4s2.IsWeak());
|
| }
|
|
|
| Persistent<Value> root(iso, g1s1); // make a root.
|
| @@ -3490,19 +3572,19 @@ TEST(ApiObjectGroupsCycleForScavenger) {
|
|
|
| // Make a root.
|
| Persistent<Value> root(iso, g1s1);
|
| - root.MarkPartiallyDependent(iso);
|
| + root.MarkPartiallyDependent();
|
|
|
| // Connect groups. We're building the following cycle:
|
| // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
|
| // groups.
|
| {
|
| HandleScope handle_scope(iso);
|
| - g1s1.MarkPartiallyDependent(iso);
|
| - g1s2.MarkPartiallyDependent(iso);
|
| - g2s1.MarkPartiallyDependent(iso);
|
| - g2s2.MarkPartiallyDependent(iso);
|
| - g3s1.MarkPartiallyDependent(iso);
|
| - g3s2.MarkPartiallyDependent(iso);
|
| + g1s1.MarkPartiallyDependent();
|
| + g1s2.MarkPartiallyDependent();
|
| + g2s1.MarkPartiallyDependent();
|
| + g2s2.MarkPartiallyDependent();
|
| + g3s1.MarkPartiallyDependent();
|
| + g3s2.MarkPartiallyDependent();
|
| iso->SetObjectGroupId(g1s1, UniqueId(1));
|
| iso->SetObjectGroupId(g1s2, UniqueId(1));
|
| Local<Object>::New(iso, g1s1.As<Object>())->Set(
|
| @@ -3526,18 +3608,17 @@ TEST(ApiObjectGroupsCycleForScavenger) {
|
|
|
| // Weaken the root.
|
| root.MakeWeak(&counter, &WeakPointerCallback);
|
| - root.MarkPartiallyDependent(iso);
|
| + root.MarkPartiallyDependent();
|
|
|
| - v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
| // Groups are deleted, rebuild groups.
|
| {
|
| HandleScope handle_scope(iso);
|
| - g1s1.MarkPartiallyDependent(isolate);
|
| - g1s2.MarkPartiallyDependent(isolate);
|
| - g2s1.MarkPartiallyDependent(isolate);
|
| - g2s2.MarkPartiallyDependent(isolate);
|
| - g3s1.MarkPartiallyDependent(isolate);
|
| - g3s2.MarkPartiallyDependent(isolate);
|
| + g1s1.MarkPartiallyDependent();
|
| + g1s2.MarkPartiallyDependent();
|
| + g2s1.MarkPartiallyDependent();
|
| + g2s2.MarkPartiallyDependent();
|
| + g3s1.MarkPartiallyDependent();
|
| + g3s2.MarkPartiallyDependent();
|
| iso->SetObjectGroupId(g1s1, UniqueId(1));
|
| iso->SetObjectGroupId(g1s2, UniqueId(1));
|
| Local<Object>::New(iso, g1s1.As<Object>())->Set(
|
| @@ -4895,7 +4976,7 @@ THREADED_TEST(Equality) {
|
| v8::Handle<v8::Object> obj = v8::Object::New();
|
| v8::Persistent<v8::Object> alias(isolate, obj);
|
| CHECK(v8::Local<v8::Object>::New(isolate, alias)->StrictEquals(obj));
|
| - alias.Dispose(isolate);
|
| + alias.Dispose();
|
| }
|
|
|
|
|
| @@ -5210,7 +5291,7 @@ THREADED_TEST(SimplePropertyWrite) {
|
| CHECK(xValue.IsEmpty());
|
| script->Run();
|
| CHECK_EQ(v8_num(4), Local<Value>::New(v8::Isolate::GetCurrent(), xValue));
|
| - xValue.Dispose(context->GetIsolate());
|
| + xValue.Dispose();
|
| xValue.Clear();
|
| }
|
| }
|
| @@ -5227,7 +5308,7 @@ THREADED_TEST(SetterOnly) {
|
| CHECK(xValue.IsEmpty());
|
| script->Run();
|
| CHECK_EQ(v8_num(4), Local<Value>::New(v8::Isolate::GetCurrent(), xValue));
|
| - xValue.Dispose(context->GetIsolate());
|
| + xValue.Dispose();
|
| xValue.Clear();
|
| }
|
| }
|
| @@ -6602,7 +6683,7 @@ class Snorkel {
|
| class Whammy {
|
| public:
|
| explicit Whammy(v8::Isolate* isolate) : cursor_(0), isolate_(isolate) { }
|
| - ~Whammy() { script_.Dispose(isolate_); }
|
| + ~Whammy() { script_.Dispose(); }
|
| v8::Handle<Script> getScript() {
|
| if (script_.IsEmpty()) script_.Reset(isolate_, v8_compile("({}).blammo"));
|
| return Local<Script>::New(isolate_, script_);
|
| @@ -6620,7 +6701,7 @@ static void HandleWeakReference(v8::Isolate* isolate,
|
| v8::Persistent<v8::Value>* obj,
|
| Snorkel* snorkel) {
|
| delete snorkel;
|
| - obj->ClearWeak(isolate);
|
| + obj->ClearWeak();
|
| }
|
|
|
| void WhammyPropertyGetter(Local<String> name,
|
| @@ -6676,7 +6757,7 @@ THREADED_TEST(WeakReference) {
|
| static void DisposeAndSetFlag(v8::Isolate* isolate,
|
| v8::Persistent<v8::Object>* obj,
|
| bool* data) {
|
| - obj->Dispose(isolate);
|
| + obj->Dispose();
|
| *(data) = true;
|
| }
|
|
|
| @@ -6699,10 +6780,10 @@ THREADED_TEST(IndependentWeakHandle) {
|
| bool object_b_disposed = false;
|
| object_a.MakeWeak(&object_a_disposed, &DisposeAndSetFlag);
|
| object_b.MakeWeak(&object_b_disposed, &DisposeAndSetFlag);
|
| - CHECK(!object_b.IsIndependent(iso));
|
| - object_a.MarkIndependent(iso);
|
| - object_b.MarkIndependent(iso);
|
| - CHECK(object_b.IsIndependent(iso));
|
| + CHECK(!object_b.IsIndependent());
|
| + object_a.MarkIndependent();
|
| + object_b.MarkIndependent();
|
| + CHECK(object_b.IsIndependent());
|
| HEAP->PerformScavenge();
|
| CHECK(object_a_disposed);
|
| CHECK(object_b_disposed);
|
| @@ -6722,7 +6803,7 @@ static void InvokeMarkSweep() {
|
| static void ForceScavenge(v8::Isolate* isolate,
|
| v8::Persistent<v8::Object>* obj,
|
| bool* data) {
|
| - obj->Dispose(isolate);
|
| + obj->Dispose();
|
| *(data) = true;
|
| InvokeScavenge();
|
| }
|
| @@ -6731,7 +6812,7 @@ static void ForceScavenge(v8::Isolate* isolate,
|
| static void ForceMarkSweep(v8::Isolate* isolate,
|
| v8::Persistent<v8::Object>* obj,
|
| bool* data) {
|
| - obj->Dispose(isolate);
|
| + obj->Dispose();
|
| *(data) = true;
|
| InvokeMarkSweep();
|
| }
|
| @@ -6760,7 +6841,7 @@ THREADED_TEST(GCFromWeakCallbacks) {
|
| }
|
| bool disposed = false;
|
| object.MakeWeak(&disposed, gc_forcing_callback[inner_gc]);
|
| - object.MarkIndependent(isolate);
|
| + object.MarkIndependent();
|
| invoke_gc[outer_gc]();
|
| CHECK(disposed);
|
| }
|
| @@ -6771,7 +6852,7 @@ THREADED_TEST(GCFromWeakCallbacks) {
|
| static void RevivingCallback(v8::Isolate* isolate,
|
| v8::Persistent<v8::Object>* obj,
|
| bool* data) {
|
| - obj->ClearWeak(isolate);
|
| + obj->ClearWeak();
|
| *(data) = true;
|
| }
|
|
|
| @@ -6793,7 +6874,7 @@ THREADED_TEST(IndependentHandleRevival) {
|
| }
|
| bool revived = false;
|
| object.MakeWeak(&revived, &RevivingCallback);
|
| - object.MarkIndependent(isolate);
|
| + object.MarkIndependent();
|
| HEAP->PerformScavenge();
|
| CHECK(revived);
|
| HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
|
| @@ -12598,7 +12679,7 @@ void NewPersistentHandleCallback(v8::Isolate* isolate,
|
| void*) {
|
| v8::HandleScope scope(isolate);
|
| bad_handle.Reset(isolate, some_object);
|
| - handle->Dispose(isolate);
|
| + handle->Dispose();
|
| }
|
|
|
|
|
| @@ -12618,7 +12699,7 @@ THREADED_TEST(NewPersistentHandleFromWeakCallback) {
|
| // in reverse allocation order, so if second allocated handle is deleted,
|
| // weak callback of the first handle would be able to 'reallocate' it.
|
| handle1.MakeWeak<v8::Value, void>(NULL, NewPersistentHandleCallback);
|
| - handle2.Dispose(isolate);
|
| + handle2.Dispose();
|
| HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| }
|
|
|
| @@ -12628,9 +12709,9 @@ v8::Persistent<v8::Object> to_be_disposed;
|
| void DisposeAndForceGcCallback(v8::Isolate* isolate,
|
| v8::Persistent<v8::Value>* handle,
|
| void*) {
|
| - to_be_disposed.Dispose(isolate);
|
| + to_be_disposed.Dispose();
|
| HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| - handle->Dispose(isolate);
|
| + handle->Dispose();
|
| }
|
|
|
|
|
| @@ -12652,7 +12733,7 @@ THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
|
| void DisposingCallback(v8::Isolate* isolate,
|
| v8::Persistent<v8::Value>* handle,
|
| void*) {
|
| - handle->Dispose(isolate);
|
| + handle->Dispose();
|
| }
|
|
|
| void HandleCreatingCallback(v8::Isolate* isolate,
|
| @@ -12660,7 +12741,7 @@ void HandleCreatingCallback(v8::Isolate* isolate,
|
| void*) {
|
| v8::HandleScope scope(isolate);
|
| v8::Persistent<v8::Object>(isolate, v8::Object::New());
|
| - handle->Dispose(isolate);
|
| + handle->Dispose();
|
| }
|
|
|
|
|
| @@ -14997,10 +15078,19 @@ THREADED_TEST(Regress16276) {
|
| CHECK_EQ(42, CompileRun("f(this).foo")->Int32Value());
|
| }
|
|
|
| +static void CheckElementValue(i::Isolate* isolate,
|
| + int expected,
|
| + i::Handle<i::Object> obj,
|
| + int offset) {
|
| + i::Object* element = obj->GetElement(isolate, offset)->ToObjectChecked();
|
| + CHECK_EQ(expected, i::Smi::cast(element)->value());
|
| +}
|
| +
|
|
|
| THREADED_TEST(PixelArray) {
|
| LocalContext context;
|
| - i::Factory* factory = i::Isolate::Current()->factory();
|
| + i::Isolate* isolate = i::Isolate::Current();
|
| + i::Factory* factory = isolate->factory();
|
| v8::HandleScope scope(context->GetIsolate());
|
| const int kElementCount = 260;
|
| uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
|
| @@ -15026,7 +15116,7 @@ THREADED_TEST(PixelArray) {
|
| // Set the elements to be the pixels.
|
| // jsobj->set_elements(*pixels);
|
| obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
|
| - CHECK_EQ(1, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
|
| + CheckElementValue(isolate, 1, jsobj, 1);
|
| obj->Set(v8_str("field"), v8::Int32::New(1503));
|
| context->Global()->Set(v8_str("pixels"), obj);
|
| v8::Handle<v8::Value> result = CompileRun("pixels.field");
|
| @@ -15083,40 +15173,33 @@ THREADED_TEST(PixelArray) {
|
| i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
|
| ASSERT(!no_failure.is_null());
|
| i::USE(no_failure);
|
| - CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
|
| + CheckElementValue(isolate, 2, jsobj, 1);
|
| *value.location() = i::Smi::FromInt(256);
|
| no_failure =
|
| i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
|
| ASSERT(!no_failure.is_null());
|
| i::USE(no_failure);
|
| - CHECK_EQ(255,
|
| - i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
|
| + CheckElementValue(isolate, 255, jsobj, 1);
|
| *value.location() = i::Smi::FromInt(-1);
|
| no_failure =
|
| i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
|
| ASSERT(!no_failure.is_null());
|
| i::USE(no_failure);
|
| - CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
|
| + CheckElementValue(isolate, 0, jsobj, 1);
|
|
|
| result = CompileRun("for (var i = 0; i < 8; i++) {"
|
| " pixels[i] = (i * 65) - 109;"
|
| "}"
|
| "pixels[1] + pixels[6];");
|
| CHECK_EQ(255, result->Int32Value());
|
| - CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(0)->ToObjectChecked())->value());
|
| - CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
|
| - CHECK_EQ(21,
|
| - i::Smi::cast(jsobj->GetElement(2)->ToObjectChecked())->value());
|
| - CHECK_EQ(86,
|
| - i::Smi::cast(jsobj->GetElement(3)->ToObjectChecked())->value());
|
| - CHECK_EQ(151,
|
| - i::Smi::cast(jsobj->GetElement(4)->ToObjectChecked())->value());
|
| - CHECK_EQ(216,
|
| - i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
|
| - CHECK_EQ(255,
|
| - i::Smi::cast(jsobj->GetElement(6)->ToObjectChecked())->value());
|
| - CHECK_EQ(255,
|
| - i::Smi::cast(jsobj->GetElement(7)->ToObjectChecked())->value());
|
| + CheckElementValue(isolate, 0, jsobj, 0);
|
| + CheckElementValue(isolate, 0, jsobj, 1);
|
| + CheckElementValue(isolate, 21, jsobj, 2);
|
| + CheckElementValue(isolate, 86, jsobj, 3);
|
| + CheckElementValue(isolate, 151, jsobj, 4);
|
| + CheckElementValue(isolate, 216, jsobj, 5);
|
| + CheckElementValue(isolate, 255, jsobj, 6);
|
| + CheckElementValue(isolate, 255, jsobj, 7);
|
| result = CompileRun("var sum = 0;"
|
| "for (var i = 0; i < 8; i++) {"
|
| " sum += pixels[i];"
|
| @@ -15129,50 +15212,49 @@ THREADED_TEST(PixelArray) {
|
| "}"
|
| "pixels[1] + pixels[6];");
|
| CHECK_EQ(8, result->Int32Value());
|
| - CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(0)->ToObjectChecked())->value());
|
| - CHECK_EQ(1, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
|
| - CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(2)->ToObjectChecked())->value());
|
| - CHECK_EQ(3, i::Smi::cast(jsobj->GetElement(3)->ToObjectChecked())->value());
|
| - CHECK_EQ(4, i::Smi::cast(jsobj->GetElement(4)->ToObjectChecked())->value());
|
| - CHECK_EQ(6, i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
|
| - CHECK_EQ(7, i::Smi::cast(jsobj->GetElement(6)->ToObjectChecked())->value());
|
| - CHECK_EQ(8, i::Smi::cast(jsobj->GetElement(7)->ToObjectChecked())->value());
|
| + CheckElementValue(isolate, 0, jsobj, 0);
|
| + CheckElementValue(isolate, 1, jsobj, 1);
|
| + CheckElementValue(isolate, 2, jsobj, 2);
|
| + CheckElementValue(isolate, 3, jsobj, 3);
|
| + CheckElementValue(isolate, 4, jsobj, 4);
|
| + CheckElementValue(isolate, 6, jsobj, 5);
|
| + CheckElementValue(isolate, 7, jsobj, 6);
|
| + CheckElementValue(isolate, 8, jsobj, 7);
|
|
|
| result = CompileRun("for (var i = 0; i < 8; i++) {"
|
| " pixels[7] = undefined;"
|
| "}"
|
| "pixels[7];");
|
| CHECK_EQ(0, result->Int32Value());
|
| - CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(7)->ToObjectChecked())->value());
|
| + CheckElementValue(isolate, 0, jsobj, 7);
|
|
|
| result = CompileRun("for (var i = 0; i < 8; i++) {"
|
| " pixels[6] = '2.3';"
|
| "}"
|
| "pixels[6];");
|
| CHECK_EQ(2, result->Int32Value());
|
| - CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(6)->ToObjectChecked())->value());
|
| + CheckElementValue(isolate, 2, jsobj, 6);
|
|
|
| result = CompileRun("for (var i = 0; i < 8; i++) {"
|
| " pixels[5] = NaN;"
|
| "}"
|
| "pixels[5];");
|
| CHECK_EQ(0, result->Int32Value());
|
| - CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
|
| + CheckElementValue(isolate, 0, jsobj, 5);
|
|
|
| result = CompileRun("for (var i = 0; i < 8; i++) {"
|
| " pixels[8] = Infinity;"
|
| "}"
|
| "pixels[8];");
|
| CHECK_EQ(255, result->Int32Value());
|
| - CHECK_EQ(255,
|
| - i::Smi::cast(jsobj->GetElement(8)->ToObjectChecked())->value());
|
| + CheckElementValue(isolate, 255, jsobj, 8);
|
|
|
| result = CompileRun("for (var i = 0; i < 8; i++) {"
|
| " pixels[9] = -Infinity;"
|
| "}"
|
| "pixels[9];");
|
| CHECK_EQ(0, result->Int32Value());
|
| - CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(9)->ToObjectChecked())->value());
|
| + CheckElementValue(isolate, 0, jsobj, 9);
|
|
|
| result = CompileRun("pixels[3] = 33;"
|
| "delete pixels[3];"
|
| @@ -15489,6 +15571,7 @@ static void ObjectWithExternalArrayTestHelper(
|
| v8::ExternalArrayType array_type,
|
| int64_t low, int64_t high) {
|
| i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
|
| + i::Isolate* isolate = jsobj->GetIsolate();
|
| obj->Set(v8_str("field"), v8::Int32::New(1503));
|
| context->Global()->Set(v8_str("ext_array"), obj);
|
| v8::Handle<v8::Value> result = CompileRun("ext_array.field");
|
| @@ -15630,12 +15713,11 @@ static void ObjectWithExternalArrayTestHelper(
|
| CHECK_EQ(0, result->Int32Value());
|
| if (array_type == v8::kExternalDoubleArray ||
|
| array_type == v8::kExternalFloatArray) {
|
| - CHECK_EQ(
|
| - static_cast<int>(i::OS::nan_value()),
|
| - static_cast<int>(jsobj->GetElement(7)->ToObjectChecked()->Number()));
|
| + CHECK_EQ(static_cast<int>(i::OS::nan_value()),
|
| + static_cast<int>(
|
| + jsobj->GetElement(isolate, 7)->ToObjectChecked()->Number()));
|
| } else {
|
| - CHECK_EQ(0, static_cast<int>(
|
| - jsobj->GetElement(7)->ToObjectChecked()->Number()));
|
| + CheckElementValue(isolate, 0, jsobj, 7);
|
| }
|
|
|
| result = CompileRun("for (var i = 0; i < 8; i++) {"
|
| @@ -15643,8 +15725,9 @@ static void ObjectWithExternalArrayTestHelper(
|
| "}"
|
| "ext_array[6];");
|
| CHECK_EQ(2, result->Int32Value());
|
| - CHECK_EQ(
|
| - 2, static_cast<int>(jsobj->GetElement(6)->ToObjectChecked()->Number()));
|
| + CHECK_EQ(2,
|
| + static_cast<int>(
|
| + jsobj->GetElement(isolate, 6)->ToObjectChecked()->Number()));
|
|
|
| if (array_type != v8::kExternalFloatArray &&
|
| array_type != v8::kExternalDoubleArray) {
|
| @@ -15658,8 +15741,7 @@ static void ObjectWithExternalArrayTestHelper(
|
| "}"
|
| "ext_array[5];");
|
| CHECK_EQ(0, result->Int32Value());
|
| - CHECK_EQ(0,
|
| - i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
|
| + CheckElementValue(isolate, 0, jsobj, 5);
|
|
|
| result = CompileRun("for (var i = 0; i < 8; i++) {"
|
| " ext_array[i] = 5;"
|
| @@ -15671,8 +15753,7 @@ static void ObjectWithExternalArrayTestHelper(
|
| int expected_value =
|
| (array_type == v8::kExternalPixelArray) ? 255 : 0;
|
| CHECK_EQ(expected_value, result->Int32Value());
|
| - CHECK_EQ(expected_value,
|
| - i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
|
| + CheckElementValue(isolate, expected_value, jsobj, 5);
|
|
|
| result = CompileRun("for (var i = 0; i < 8; i++) {"
|
| " ext_array[i] = 5;"
|
| @@ -15682,8 +15763,7 @@ static void ObjectWithExternalArrayTestHelper(
|
| "}"
|
| "ext_array[5];");
|
| CHECK_EQ(0, result->Int32Value());
|
| - CHECK_EQ(0,
|
| - i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
|
| + CheckElementValue(isolate, 0, jsobj, 5);
|
|
|
| // Check truncation behavior of integral arrays.
|
| const char* unsigned_data =
|
| @@ -15789,7 +15869,8 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
|
| int64_t low,
|
| int64_t high) {
|
| LocalContext context;
|
| - i::Factory* factory = i::Isolate::Current()->factory();
|
| + i::Isolate* isolate = i::Isolate::Current();
|
| + i::Factory* factory = isolate->factory();
|
| v8::HandleScope scope(context->GetIsolate());
|
| const int kElementCount = 40;
|
| int element_size = ExternalArrayElementSize(array_type);
|
| @@ -15817,8 +15898,9 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
|
| obj->SetIndexedPropertiesToExternalArrayData(array_data,
|
| array_type,
|
| kElementCount);
|
| - CHECK_EQ(
|
| - 1, static_cast<int>(jsobj->GetElement(1)->ToObjectChecked()->Number()));
|
| + CHECK_EQ(1,
|
| + static_cast<int>(
|
| + jsobj->GetElement(isolate, 1)->ToObjectChecked()->Number()));
|
|
|
| ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
|
| context.local(), obj, kElementCount, array_type, low, high);
|
| @@ -18590,15 +18672,15 @@ TEST(PersistentHandleVisitor) {
|
| v8::Isolate* isolate = context->GetIsolate();
|
| v8::HandleScope scope(isolate);
|
| v8::Persistent<v8::Object> object(isolate, v8::Object::New());
|
| - CHECK_EQ(0, object.WrapperClassId(isolate));
|
| - object.SetWrapperClassId(isolate, 42);
|
| - CHECK_EQ(42, object.WrapperClassId(isolate));
|
| + CHECK_EQ(0, object.WrapperClassId());
|
| + object.SetWrapperClassId(42);
|
| + CHECK_EQ(42, object.WrapperClassId());
|
|
|
| Visitor42 visitor(&object);
|
| v8::V8::VisitHandlesWithClassIds(&visitor);
|
| CHECK_EQ(1, visitor.counter_);
|
|
|
| - object.Dispose(isolate);
|
| + object.Dispose();
|
| }
|
|
|
|
|
| @@ -18607,10 +18689,10 @@ TEST(WrapperClassId) {
|
| v8::Isolate* isolate = context->GetIsolate();
|
| v8::HandleScope scope(isolate);
|
| v8::Persistent<v8::Object> object(isolate, v8::Object::New());
|
| - CHECK_EQ(0, object.WrapperClassId(isolate));
|
| - object.SetWrapperClassId(isolate, 65535);
|
| - CHECK_EQ(65535, object.WrapperClassId(isolate));
|
| - object.Dispose(isolate);
|
| + CHECK_EQ(0, object.WrapperClassId());
|
| + object.SetWrapperClassId(65535);
|
| + CHECK_EQ(65535, object.WrapperClassId());
|
| + object.Dispose();
|
| }
|
|
|
|
|
| @@ -18619,23 +18701,23 @@ TEST(PersistentHandleInNewSpaceVisitor) {
|
| v8::Isolate* isolate = context->GetIsolate();
|
| v8::HandleScope scope(isolate);
|
| v8::Persistent<v8::Object> object1(isolate, v8::Object::New());
|
| - CHECK_EQ(0, object1.WrapperClassId(isolate));
|
| - object1.SetWrapperClassId(isolate, 42);
|
| - CHECK_EQ(42, object1.WrapperClassId(isolate));
|
| + CHECK_EQ(0, object1.WrapperClassId());
|
| + object1.SetWrapperClassId(42);
|
| + CHECK_EQ(42, object1.WrapperClassId());
|
|
|
| HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
|
|
| v8::Persistent<v8::Object> object2(isolate, v8::Object::New());
|
| - CHECK_EQ(0, object2.WrapperClassId(isolate));
|
| - object2.SetWrapperClassId(isolate, 42);
|
| - CHECK_EQ(42, object2.WrapperClassId(isolate));
|
| + CHECK_EQ(0, object2.WrapperClassId());
|
| + object2.SetWrapperClassId(42);
|
| + CHECK_EQ(42, object2.WrapperClassId());
|
|
|
| Visitor42 visitor(&object2);
|
| v8::V8::VisitHandlesForPartialDependence(isolate, &visitor);
|
| CHECK_EQ(1, visitor.counter_);
|
|
|
| - object1.Dispose(isolate);
|
| - object2.Dispose(isolate);
|
| + object1.Dispose();
|
| + object2.Dispose();
|
| }
|
|
|
|
|
| @@ -20320,4 +20402,123 @@ THREADED_TEST(Regress256330) {
|
| ExpectBoolean("%GetOptimizationStatus(f) != 2", true);
|
| }
|
|
|
| +
|
| +THREADED_TEST(CrankshaftInterceptorSetter) {
|
| + i::FLAG_allow_natives_syntax = true;
|
| + v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| + Handle<FunctionTemplate> templ = FunctionTemplate::New();
|
| + AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
|
| + LocalContext env;
|
| + env->Global()->Set(v8_str("Obj"), templ->GetFunction());
|
| + CompileRun("var obj = new Obj;"
|
| + // Initialize fields to avoid transitions later.
|
| + "obj.age = 0;"
|
| + "obj.accessor_age = 42;"
|
| + "function setter(i) { this.accessor_age = i; };"
|
| + "function getter() { return this.accessor_age; };"
|
| + "function setAge(i) { obj.age = i; };"
|
| + "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
|
| + "setAge(1);"
|
| + "setAge(2);"
|
| + "setAge(3);"
|
| + "%OptimizeFunctionOnNextCall(setAge);"
|
| + "setAge(4);");
|
| + // All stores went through the interceptor.
|
| + ExpectInt32("obj.interceptor_age", 4);
|
| + ExpectInt32("obj.accessor_age", 42);
|
| +}
|
| +
|
| +
|
| +THREADED_TEST(CrankshaftInterceptorGetter) {
|
| + i::FLAG_allow_natives_syntax = true;
|
| + v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| + Handle<FunctionTemplate> templ = FunctionTemplate::New();
|
| + AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
|
| + LocalContext env;
|
| + env->Global()->Set(v8_str("Obj"), templ->GetFunction());
|
| + CompileRun("var obj = new Obj;"
|
| + // Initialize fields to avoid transitions later.
|
| + "obj.age = 1;"
|
| + "obj.accessor_age = 42;"
|
| + "function getter() { return this.accessor_age; };"
|
| + "function getAge() { return obj.interceptor_age; };"
|
| + "Object.defineProperty(obj, 'interceptor_age', { get:getter });"
|
| + "getAge();"
|
| + "getAge();"
|
| + "getAge();"
|
| + "%OptimizeFunctionOnNextCall(getAge);");
|
| + // Access through interceptor.
|
| + ExpectInt32("getAge()", 1);
|
| +}
|
| +
|
| +
|
| +THREADED_TEST(CrankshaftInterceptorFieldRead) {
|
| + i::FLAG_allow_natives_syntax = true;
|
| + v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| + Handle<FunctionTemplate> templ = FunctionTemplate::New();
|
| + AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
|
| + LocalContext env;
|
| + env->Global()->Set(v8_str("Obj"), templ->GetFunction());
|
| + CompileRun("var obj = new Obj;"
|
| + "obj.__proto__.interceptor_age = 42;"
|
| + "obj.age = 100;"
|
| + "function getAge() { return obj.interceptor_age; };");
|
| + ExpectInt32("getAge();", 100);
|
| + ExpectInt32("getAge();", 100);
|
| + ExpectInt32("getAge();", 100);
|
| + CompileRun("%OptimizeFunctionOnNextCall(getAge);");
|
| + // Access through interceptor.
|
| + ExpectInt32("getAge();", 100);
|
| +}
|
| +
|
| +
|
| +THREADED_TEST(CrankshaftInterceptorFieldWrite) {
|
| + i::FLAG_allow_natives_syntax = true;
|
| + v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| + Handle<FunctionTemplate> templ = FunctionTemplate::New();
|
| + AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
|
| + LocalContext env;
|
| + env->Global()->Set(v8_str("Obj"), templ->GetFunction());
|
| + CompileRun("var obj = new Obj;"
|
| + "obj.age = 100000;"
|
| + "function setAge(i) { obj.age = i };"
|
| + "setAge(100);"
|
| + "setAge(101);"
|
| + "setAge(102);"
|
| + "%OptimizeFunctionOnNextCall(setAge);"
|
| + "setAge(103);");
|
| + ExpectInt32("obj.age", 100000);
|
| + ExpectInt32("obj.interceptor_age", 103);
|
| +}
|
| +
|
| +
|
| #endif // V8_OS_POSIX
|
| +
|
| +
|
| +static Local<Value> function_new_expected_env;
|
| +static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
|
| + CHECK_EQ(function_new_expected_env, info.Data());
|
| + info.GetReturnValue().Set(17);
|
| +}
|
| +
|
| +
|
| +THREADED_TEST(FunctionNew) {
|
| + LocalContext env;
|
| + v8::Isolate* isolate = env->GetIsolate();
|
| + v8::HandleScope scope(isolate);
|
| + Local<Object> data = v8::Object::New();
|
| + function_new_expected_env = data;
|
| + Local<Function> func = Function::New(isolate, FunctionNewCallback, data);
|
| + env->Global()->Set(v8_str("func"), func);
|
| + Local<Value> result = CompileRun("func();");
|
| + CHECK_EQ(v8::Integer::New(17, isolate), result);
|
| + // Verify function not cached
|
| + int serial_number =
|
| + i::Smi::cast(v8::Utils::OpenHandle(*func)
|
| + ->shared()->get_api_func_data()->serial_number())->value();
|
| + i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
|
| + i::Object* elm = i_isolate->native_context()->function_cache()
|
| + ->GetElementNoExceptionThrown(i_isolate, serial_number);
|
| + CHECK(elm->IsNull());
|
| +}
|
| +
|
|
|