From 56b53dd5dc307c93f58e66ef57251911fa8ef382 Mon Sep 17 00:00:00 2001 From: "antonm@chromium.org" Date: Fri, 1 Apr 2011 12:17:20 +0000 Subject: [PATCH] Introduce v8::Object::CreationContext method. That allows to find out a global context in which the object was created. Review URL: http://codereview.chromium.org/6759054 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7476 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- include/v8.h | 5 +++ src/api.cc | 27 ++++++++++++++ test/cctest/test-api.cc | 99 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+) diff --git a/include/v8.h b/include/v8.h index 62d1085..a990fc2 100644 --- a/include/v8.h +++ b/include/v8.h @@ -1653,6 +1653,11 @@ class Object : public Value { V8EXPORT Local Clone(); /** + * Returns the context in which the object was created. + */ + V8EXPORT Local CreationContext(); + + /** * Set the backing store of the indexed properties to be managed by the * embedding layer. Access to the indexed properties will follow the rules * spelled out in CanvasPixelArray. diff --git a/src/api.cc b/src/api.cc index 6c04687..b0d287d 100644 --- a/src/api.cc +++ b/src/api.cc @@ -2879,6 +2879,33 @@ Local v8::Object::Clone() { } +static i::Context* GetCreationContext(i::JSObject* object) { + i::Object* constructor = object->map()->constructor(); + i::JSFunction* function; + if (!constructor->IsJSFunction()) { + // API functions have null as a constructor, + // but any JSFunction knows its context immediately. + ASSERT(object->IsJSFunction() && + i::JSFunction::cast(object)->shared()->IsApiFunction()); + function = i::JSFunction::cast(object); + } else { + function = i::JSFunction::cast(constructor); + } + return function->context()->global_context(); +} + + +Local v8::Object::CreationContext() { + i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); + ON_BAILOUT(isolate, + "v8::Object::CreationContext()", return Local()); + ENTER_V8(isolate); + i::Handle self = Utils::OpenHandle(this); + i::Context* context = GetCreationContext(*self); + return Utils::ToLocal(i::Handle(context)); +} + + int v8::Object::GetIdentityHash() { i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); ON_BAILOUT(isolate, "v8::Object::GetIdentityHash()", return 0); diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc index 33d505e..d5748ce 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -13629,3 +13629,102 @@ TEST(DefinePropertyPostDetach) { context->DetachGlobal(); define_property->Call(proxy, 0, NULL); } + + +static void InstallContextId(v8::Handle context, int id) { + Context::Scope scope(context); + CompileRun("Object.prototype").As()-> + Set(v8_str("context_id"), v8::Integer::New(id)); +} + + +static void CheckContextId(v8::Handle object, int expected) { + CHECK_EQ(expected, object->Get(v8_str("context_id"))->Int32Value()); +} + + +THREADED_TEST(CreationContext) { + HandleScope handle_scope; + Persistent context1 = Context::New(); + InstallContextId(context1, 1); + Persistent context2 = Context::New(); + InstallContextId(context2, 2); + Persistent context3 = Context::New(); + InstallContextId(context3, 3); + + Local tmpl = v8::FunctionTemplate::New(); + + Local object1; + Local func1; + { + Context::Scope scope(context1); + object1 = Object::New(); + func1 = tmpl->GetFunction(); + } + + Local object2; + Local func2; + { + Context::Scope scope(context2); + object2 = Object::New(); + func2 = tmpl->GetFunction(); + } + + Local instance1; + Local instance2; + + { + Context::Scope scope(context3); + instance1 = func1->NewInstance(); + instance2 = func2->NewInstance(); + } + + CHECK(object1->CreationContext() == context1); + CheckContextId(object1, 1); + CHECK(func1->CreationContext() == context1); + CheckContextId(func1, 1); + CHECK(instance1->CreationContext() == context1); + CheckContextId(instance1, 1); + CHECK(object2->CreationContext() == context2); + CheckContextId(object2, 2); + CHECK(func2->CreationContext() == context2); + CheckContextId(func2, 2); + CHECK(instance2->CreationContext() == context2); + CheckContextId(instance2, 2); + + { + Context::Scope scope(context1); + CHECK(object1->CreationContext() == context1); + CheckContextId(object1, 1); + CHECK(func1->CreationContext() == context1); + CheckContextId(func1, 1); + CHECK(instance1->CreationContext() == context1); + CheckContextId(instance1, 1); + CHECK(object2->CreationContext() == context2); + CheckContextId(object2, 2); + CHECK(func2->CreationContext() == context2); + CheckContextId(func2, 2); + CHECK(instance2->CreationContext() == context2); + CheckContextId(instance2, 2); + } + + { + Context::Scope scope(context2); + CHECK(object1->CreationContext() == context1); + CheckContextId(object1, 1); + CHECK(func1->CreationContext() == context1); + CheckContextId(func1, 1); + CHECK(instance1->CreationContext() == context1); + CheckContextId(instance1, 1); + CHECK(object2->CreationContext() == context2); + CheckContextId(object2, 2); + CHECK(func2->CreationContext() == context2); + CheckContextId(func2, 2); + CHECK(instance2->CreationContext() == context2); + CheckContextId(instance2, 2); + } + + context1.Dispose(); + context2.Dispose(); + context3.Dispose(); +} -- 2.7.4