Revision: 18624
Author:   [email protected]
Date:     Wed Jan 15 16:25:55 2014 UTC
Log: Merged r18286, r18289, r18291, r18292, r18299, r18327 into 3.23 branch.

Fix patching the receiver (global object -> global proxy) after the interceptor.

Properly restore the receiver after the interceptor call.

Fix popping order on ARM.

Push receiver and holder separately, given that they can be the same.

Fixed global object leak caused by overwriting the global receiver (the global proxy) in the global object with the global object itself.

Move the receiver into r0 for PatchGlobalProxy. This fixes the ARM/android bug http://build.chromium.org/p/tryserver.chromium/builders/android_dbg_triggered_tests/builds/112686/steps/androidwebview_instrumentation_tests [email protected]

BUG=324812
LOG=N
[email protected]

Review URL: https://codereview.chromium.org/137993018
http://code.google.com/p/v8/source/detail?r=18624

Modified:
 /branches/3.23/include/v8.h
 /branches/3.23/src/api.cc
 /branches/3.23/src/arm/stub-cache-arm.cc
 /branches/3.23/src/bootstrapper.cc
 /branches/3.23/src/bootstrapper.h
 /branches/3.23/src/ia32/stub-cache-ia32.cc
 /branches/3.23/src/objects-inl.h
 /branches/3.23/src/objects.h
 /branches/3.23/src/runtime.cc
 /branches/3.23/src/runtime.h
 /branches/3.23/src/v8natives.js
 /branches/3.23/src/version.cc
 /branches/3.23/src/x64/stub-cache-x64.cc
 /branches/3.23/test/cctest/test-api.cc
 /branches/3.23/test/cctest/test-decls.cc
 /branches/3.23/test/cctest/test-object-observe.cc

=======================================
--- /branches/3.23/include/v8.h Fri Nov 29 11:43:20 2013 UTC
+++ /branches/3.23/include/v8.h Wed Jan 15 16:25:55 2014 UTC
@@ -5150,20 +5150,16 @@
 class V8_EXPORT Context {
  public:
   /**
-   * Returns the global proxy object or global object itself for
-   * detached contexts.
+   * Returns the global proxy object.
    *
-   * Global proxy object is a thin wrapper whose prototype points to
-   * actual context's global object with the properties like Object, etc.
-   * This is done that way for security reasons (for more details see
+   * Global proxy object is a thin wrapper whose prototype points to actual
+ * context's global object with the properties like Object, etc. This is done
+   * that way for security reasons (for more details see
    * https://wiki.mozilla.org/Gecko:SplitWindow).
    *
* Please note that changes to global proxy object prototype most probably
-   * would break VM---v8 expects only global object as a prototype of
-   * global proxy object.
-   *
- * If DetachGlobal() has been invoked, Global() would return actual global
-   * object until global is reattached with ReattachGlobal().
+ * would break VM---v8 expects only global object as a prototype of global
+   * proxy object.
    */
   Local<Object> Global();

@@ -5173,18 +5169,6 @@
    */
   void DetachGlobal();

-  /**
-   * Reattaches a global object to a context.  This can be used to
-   * restore the connection between a global object and a context
-   * after DetachGlobal has been called.
-   *
-   * \param global_object The global object to reattach to the
-   *   context.  For this to work, the global object must be the global
-   *   object that was associated with this context before a call to
-   *   DetachGlobal.
-   */
-  void ReattachGlobal(Handle<Object> global_object);
-
   /**
    * Creates a new context and returns a handle to the newly allocated
    * context.
=======================================
--- /branches/3.23/src/api.cc   Tue Dec  3 08:00:39 2013 UTC
+++ /branches/3.23/src/api.cc   Wed Jan 15 16:25:55 2014 UTC
@@ -5410,6 +5410,12 @@
   i::Handle<i::Context> context = Utils::OpenHandle(this);
   i::Isolate* isolate = context->GetIsolate();
   i::Handle<i::Object> global(context->global_proxy(), isolate);
+  // TODO(dcarney): This should always return the global proxy
+ // but can't presently as calls to GetProtoype will return the wrong result.
+  if (i::Handle<i::JSGlobalProxy>::cast(
+          global)->IsDetachedFrom(context->global_object())) {
+     global = i::Handle<i::Object>(context->global_object(), isolate);
+  }
   return Utils::ToLocal(i::Handle<i::JSObject>::cast(global));
 }

@@ -5420,16 +5426,6 @@
   ENTER_V8(isolate);
   isolate->bootstrapper()->DetachGlobal(context);
 }
-
-
-void Context::ReattachGlobal(Handle<Object> global_object) {
-  i::Handle<i::Context> context = Utils::OpenHandle(this);
-  i::Isolate* isolate = context->GetIsolate();
-  ENTER_V8(isolate);
-  i::Handle<i::JSGlobalProxy> global_proxy =
-      i::Handle<i::JSGlobalProxy>::cast(Utils::OpenHandle(*global_object));
-  isolate->bootstrapper()->ReattachGlobal(context, global_proxy);
-}


 void Context::AllowCodeGenerationFromStrings(bool allow) {
=======================================
--- /branches/3.23/src/arm/stub-cache-arm.cc    Tue Dec  3 08:00:39 2013 UTC
+++ /branches/3.23/src/arm/stub-cache-arm.cc    Wed Jan 15 16:25:55 2014 UTC
@@ -1021,7 +1021,7 @@
     // holder haven't changed and thus we can use cached constant function.
     if (*interceptor_holder != lookup->holder()) {
       stub_compiler_->CheckPrototypes(
-          IC::CurrentTypeOf(interceptor_holder, masm->isolate()), receiver,
+          IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder,
           handle(lookup->holder()), scratch1, scratch2, scratch3,
           name, depth2, miss);
     } else {
@@ -1038,7 +1038,8 @@
           masm, optimization, arguments_.immediate(), false);
     } else {
       Handle<JSFunction> function = optimization.constant_function();
-      stub_compiler_->GenerateJumpFunctionIgnoreReceiver(function);
+      __ Move(r0, receiver);
+      stub_compiler_->GenerateJumpFunction(object, function);
     }

     // Deferred code for fast API call case---clean preallocated space.
@@ -1091,12 +1092,14 @@
                            Label* interceptor_succeeded) {
     {
       FrameScope scope(masm, StackFrame::INTERNAL);
+      __ Push(receiver);
       __ Push(holder, name_);
       CompileCallLoadPropertyWithInterceptor(
           masm, receiver, holder, name_, holder_obj,
           IC::kLoadPropertyWithInterceptorOnly);
-      __ pop(name_);  // Restore the name.
-      __ pop(receiver);  // Restore the holder.
+      __ pop(name_);
+      __ pop(holder);
+      __ pop(receiver);
     }
// If interceptor returns no-result sentinel, call the constant function.
     __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex);
=======================================
--- /branches/3.23/src/bootstrapper.cc  Thu Nov 28 13:42:41 2013 UTC
+++ /branches/3.23/src/bootstrapper.cc  Wed Jan 15 16:25:55 2014 UTC
@@ -339,17 +339,6 @@
Handle<JSGlobalProxy> global_proxy(JSGlobalProxy::cast(env->global_proxy()));
   global_proxy->set_native_context(*factory->null_value());
   SetObjectPrototype(global_proxy, factory->null_value());
-  env->set_global_proxy(env->global_object());
-  env->global_object()->set_global_receiver(env->global_object());
-}
-
-
-void Bootstrapper::ReattachGlobal(Handle<Context> env,
-                                  Handle<JSGlobalProxy> global_proxy) {
-  env->global_object()->set_global_receiver(*global_proxy);
-  env->set_global_proxy(*global_proxy);
-  SetObjectPrototype(global_proxy, Handle<JSObject>(env->global_object()));
-  global_proxy->set_native_context(*env);
 }


=======================================
--- /branches/3.23/src/bootstrapper.h   Thu Sep 12 09:02:59 2013 UTC
+++ /branches/3.23/src/bootstrapper.h   Wed Jan 15 16:25:55 2014 UTC
@@ -105,9 +105,6 @@
   // Detach the environment from its outer global object.
   void DetachGlobal(Handle<Context> env);

-  // Reattach an outer global object to an environment.
- void ReattachGlobal(Handle<Context> env, Handle<JSGlobalProxy> global_proxy);
-
   // Traverses the pointers for memory management.
   void Iterate(ObjectVisitor* v);

=======================================
--- /branches/3.23/src/ia32/stub-cache-ia32.cc  Tue Dec  3 08:00:39 2013 UTC
+++ /branches/3.23/src/ia32/stub-cache-ia32.cc  Wed Jan 15 16:25:55 2014 UTC
@@ -740,7 +740,7 @@
     // holder haven't changed and thus we can use cached constant function.
     if (*interceptor_holder != lookup->holder()) {
       stub_compiler_->CheckPrototypes(
-          IC::CurrentTypeOf(interceptor_holder, masm->isolate()), receiver,
+          IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder,
           handle(lookup->holder()), scratch1, scratch2, scratch3,
           name, depth2, miss);
     } else {
@@ -756,7 +756,7 @@
       GenerateFastApiCall(masm, optimization, arguments_.immediate());
     } else {
       Handle<JSFunction> fun = optimization.constant_function();
-      stub_compiler_->GenerateJumpFunctionIgnoreReceiver(fun);
+      stub_compiler_->GenerateJumpFunction(object, fun);
     }

     // Deferred code for fast API call case---clean preallocated space.
@@ -808,15 +808,17 @@
                            Label* interceptor_succeeded) {
     {
       FrameScope scope(masm, StackFrame::INTERNAL);
-      __ push(holder);  // Save the holder.
-      __ push(name_);  // Save the name.
+      __ push(receiver);
+      __ push(holder);
+      __ push(name_);

       CompileCallLoadPropertyWithInterceptor(
           masm, receiver, holder, name_, holder_obj,
           IC::kLoadPropertyWithInterceptorOnly);

-      __ pop(name_);  // Restore the name.
-      __ pop(receiver);  // Restore the holder.
+      __ pop(name_);
+      __ pop(holder);
+      __ pop(receiver);
       // Leave the internal frame.
     }

=======================================
--- /branches/3.23/src/objects-inl.h    Fri Jan 10 13:13:22 2014 UTC
+++ /branches/3.23/src/objects-inl.h    Wed Jan 15 16:25:55 2014 UTC
@@ -5907,16 +5907,13 @@
 }


-// TODO(504): this may be useful in other places too where JSGlobalProxy
-// is used.
-Object* JSObject::BypassGlobalProxy() {
-  if (IsJSGlobalProxy()) {
-    Object* proto = GetPrototype();
-    if (proto->IsNull()) return GetHeap()->undefined_value();
-    ASSERT(proto->IsJSGlobalObject());
-    return proto;
-  }
-  return this;
+bool JSGlobalObject::IsDetached() {
+  return JSGlobalProxy::cast(global_receiver())->IsDetachedFrom(this);
+}
+
+
+bool JSGlobalProxy::IsDetachedFrom(GlobalObject* global) {
+  return GetPrototype() != global;
 }


=======================================
--- /branches/3.23/src/objects.h        Mon Jan 13 11:34:55 2014 UTC
+++ /branches/3.23/src/objects.h        Wed Jan 15 16:25:55 2014 UTC
@@ -878,6 +878,7 @@
 class ElementsAccessor;
 class Failure;
 class FixedArrayBase;
+class GlobalObject;
 class ObjectVisitor;
 class StringStream;
 class Type;
@@ -7424,6 +7425,8 @@
   // Casting.
   static inline JSGlobalProxy* cast(Object* obj);

+  inline bool IsDetachedFrom(GlobalObject* global);
+
   // Dispatched behavior.
   DECLARE_PRINTER(JSGlobalProxy)
   DECLARE_VERIFIER(JSGlobalProxy)
@@ -7493,6 +7496,8 @@
static Handle<PropertyCell> EnsurePropertyCell(Handle<JSGlobalObject> global,
                                                  Handle<Name> name);

+  inline bool IsDetached();
+
   // Dispatched behavior.
   DECLARE_PRINTER(JSGlobalObject)
   DECLARE_VERIFIER(JSGlobalObject)
=======================================
--- /branches/3.23/src/runtime.cc       Thu Nov 28 13:42:41 2013 UTC
+++ /branches/3.23/src/runtime.cc       Wed Jan 15 16:25:55 2014 UTC
@@ -9644,6 +9644,16 @@
   if (!global->IsJSGlobalObject()) return isolate->heap()->null_value();
   return JSGlobalObject::cast(global)->global_receiver();
 }
+
+
+RUNTIME_FUNCTION(MaybeObject*, Runtime_IsAttachedGlobal) {
+  SealHandleScope shs(isolate);
+  ASSERT(args.length() == 1);
+  Object* global = args[0];
+  if (!global->IsJSGlobalObject()) return isolate->heap()->false_value();
+  return isolate->heap()->ToBoolean(
+      !JSGlobalObject::cast(global)->IsDetached());
+}


 RUNTIME_FUNCTION(MaybeObject*, Runtime_ParseJson) {
=======================================
--- /branches/3.23/src/runtime.h        Thu Nov 28 13:42:41 2013 UTC
+++ /branches/3.23/src/runtime.h        Wed Jan 15 16:25:55 2014 UTC
@@ -278,6 +278,7 @@
   \
   /* Eval */ \
   F(GlobalReceiver, 1, 1) \
+  F(IsAttachedGlobal, 1, 1) \
   F(ResolvePossiblyDirectEval, 5, 2) \
   \
   F(SetProperty, -1 /* 4 or 5 */, 1) \
=======================================
--- /branches/3.23/src/v8natives.js     Thu Nov 28 13:42:41 2013 UTC
+++ /branches/3.23/src/v8natives.js     Wed Jan 15 16:25:55 2014 UTC
@@ -170,18 +170,17 @@
 function GlobalEval(x) {
   if (!IS_STRING(x)) return x;

-  var global_receiver = %GlobalReceiver(global);
-  var global_is_detached = (global === global_receiver);
-
   // For consistency with JSC we require the global object passed to
   // eval to be the global object from which 'eval' originated. This
   // is not mandated by the spec.
   // We only throw if the global has been detached, since we need the
   // receiver as this-value for the call.
-  if (global_is_detached) {
+  if (!%IsAttachedGlobal(global)) {
     throw new $EvalError('The "this" value passed to eval must ' +
'be the global object from which eval originated');
   }
+
+  var global_receiver = %GlobalReceiver(global);

   var f = %CompileString(x, false);
   if (!IS_FUNCTION(f)) return f;
=======================================
--- /branches/3.23/src/version.cc       Mon Jan 13 11:34:55 2014 UTC
+++ /branches/3.23/src/version.cc       Wed Jan 15 16:25:55 2014 UTC
@@ -35,7 +35,7 @@
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     23
 #define BUILD_NUMBER      17
-#define PATCH_LEVEL       6
+#define PATCH_LEVEL       7
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
 #define IS_CANDIDATE_VERSION 0
=======================================
--- /branches/3.23/src/x64/stub-cache-x64.cc    Tue Dec  3 08:00:39 2013 UTC
+++ /branches/3.23/src/x64/stub-cache-x64.cc    Wed Jan 15 16:25:55 2014 UTC
@@ -733,7 +733,7 @@
     // holder haven't changed and thus we can use cached constant function.
     if (*interceptor_holder != lookup->holder()) {
       stub_compiler_->CheckPrototypes(
-          IC::CurrentTypeOf(interceptor_holder, masm->isolate()), receiver,
+          IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder,
           handle(lookup->holder()), scratch1, scratch2, scratch3,
           name, depth2, miss);
     } else {
@@ -749,7 +749,7 @@
       GenerateFastApiCall(masm, optimization, arguments_.immediate());
     } else {
       Handle<JSFunction> fun = optimization.constant_function();
-      stub_compiler_->GenerateJumpFunctionIgnoreReceiver(fun);
+      stub_compiler_->GenerateJumpFunction(object, fun);
     }

     // Deferred code for fast API call case---clean preallocated space.
@@ -801,15 +801,17 @@
                            Label* interceptor_succeeded) {
     {
       FrameScope scope(masm, StackFrame::INTERNAL);
-      __ push(holder);  // Save the holder.
-      __ push(name_);  // Save the name.
+      __ push(receiver);
+      __ push(holder);
+      __ push(name_);

       CompileCallLoadPropertyWithInterceptor(
           masm, receiver, holder, name_, holder_obj,
           IC::kLoadPropertyWithInterceptorOnly);

-      __ pop(name_);  // Restore the name.
-      __ pop(receiver);  // Restore the holder.
+      __ pop(name_);
+      __ pop(holder);
+      __ pop(receiver);
       // Leave the internal frame.
     }

=======================================
--- /branches/3.23/test/cctest/test-api.cc      Thu Nov 28 13:42:41 2013 UTC
+++ /branches/3.23/test/cctest/test-api.cc      Wed Jan 15 16:25:55 2014 UTC
@@ -8502,8 +8502,6 @@
   // Detach env2's global, and reuse the global object of env2
   env2->Exit();
   env2->DetachGlobal();
-  // env2 has a new global object.
-  CHECK(!env2->Global()->Equals(global2));

   v8::Handle<Context> env3 = Context::New(env1->GetIsolate(),
                                           0,
@@ -8538,7 +8536,7 @@
 }


-TEST(DetachAndReattachGlobal) {
+TEST(DetachGlobal) {
   LocalContext env1;
   v8::HandleScope scope(env1->GetIsolate());

@@ -8603,16 +8601,58 @@
   // so access should be blocked.
   result = CompileRun("other.p");
   CHECK(result->IsUndefined());
+}

-  // Detach the global for env3 and reattach it to env2.
-  env3->DetachGlobal();
-  env2->ReattachGlobal(global2);
+
+TEST(DetachedAccesses) {
+  LocalContext env1;
+  v8::HandleScope scope(env1->GetIsolate());
+
+  // Create second environment.
+  v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
+
+  Local<Value> foo = v8_str("foo");
+
+  // Set same security token for env1 and env2.
+  env1->SetSecurityToken(foo);
+  env2->SetSecurityToken(foo);
+
+  {
+    v8::Context::Scope scope(env2);
+    CompileRun(
+        "var x = 'x';"
+        "function get_x() { return this.x; }"
+        "function get_x_w() { return get_x(); }"
+        "");
+    env1->Global()->Set(v8_str("get_x"), CompileRun("get_x"));
+    env1->Global()->Set(v8_str("get_x_w"), CompileRun("get_x_w"));
+  }
+
+  Local<Object> env2_global = env2->Global();
+  env2_global->TurnOnAccessCheck();
+  env2->DetachGlobal();
+
+  Local<Value> result;
+  result = CompileRun("get_x()");
+  CHECK(result->IsUndefined());
+  result = CompileRun("get_x_w()");
+  CHECK(result->IsUndefined());
+
+  // Reattach env2's proxy
+  env2 = Context::New(env1->GetIsolate(),
+                      0,
+                      v8::Handle<v8::ObjectTemplate>(),
+                      env2_global);
+  env2->SetSecurityToken(foo);
+  {
+    v8::Context::Scope scope(env2);
+    CompileRun("var x = 'x2';");
+  }

-  // Check that we have access to other.p again in env1.  |other| is now
-  // the global object for env2 which has the same security token as env1.
-  result = CompileRun("other.p");
-  CHECK(result->IsInt32());
-  CHECK_EQ(42, result->Int32Value());
+  result = CompileRun("get_x()");
+  CHECK(result->IsUndefined());
+  result = CompileRun("get_x_w()");
+  CHECK_EQ(v8_str("x2"), result);
 }


@@ -14230,8 +14270,10 @@
   }

   // Detach the global and turn on access check.
+  Local<Object> hidden_global = Local<Object>::Cast(
+      context->Global()->GetPrototype());
   context->DetachGlobal();
-  context->Global()->TurnOnAccessCheck();
+  hidden_global->TurnOnAccessCheck();

   // Failing access check to property get results in undefined.
   CHECK(f1->Call(global, 0, NULL)->IsUndefined());
@@ -14315,8 +14357,10 @@

// Detach the global and turn on access check now blocking access to property
   // a and function h.
+  Local<Object> hidden_global = Local<Object>::Cast(
+      context->Global()->GetPrototype());
   context->DetachGlobal();
-  context->Global()->TurnOnAccessCheck();
+  hidden_global->TurnOnAccessCheck();

   // Failing access check to property get results in undefined.
   CHECK(f1->Call(global, 0, NULL)->IsUndefined());
@@ -14332,11 +14376,11 @@
// Now compile the source again. And get the newly compiled functions, except
   // for h for which access is blocked.
   CompileRun(source);
-  f1 = Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
-  f2 = Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
-  g1 = Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
-  g2 = Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
-  CHECK(context->Global()->Get(v8_str("h"))->IsUndefined());
+  f1 = Local<Function>::Cast(hidden_global->Get(v8_str("f1")));
+  f2 = Local<Function>::Cast(hidden_global->Get(v8_str("f2")));
+  g1 = Local<Function>::Cast(hidden_global->Get(v8_str("g1")));
+  g2 = Local<Function>::Cast(hidden_global->Get(v8_str("g2")));
+  CHECK(hidden_global->Get(v8_str("h"))->IsUndefined());

   // Failing access check to property get results in undefined.
   CHECK(f1->Call(global, 0, NULL)->IsUndefined());
@@ -15202,23 +15246,6 @@
   CHECK(!obj->Get(foo_string)->IsUndefined());
 }

-
-// Regression test for http://crbug.com/16276.
-THREADED_TEST(Regress16276) {
-  LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
-  // Force the IC in f to be a dictionary load IC.
-  CompileRun("function f(obj) { return obj.x; }\n"
-             "var obj = { x: { foo: 42 }, y: 87 };\n"
-             "var x = obj.x;\n"
-             "delete obj.y;\n"
-             "for (var i = 0; i < 5; i++) f(obj);");
-  // Detach the global object to make 'this' refer directly to the
-  // global object (not the proxy), and make sure that the dictionary
-  // load IC doesn't mess up loading directly from the global object.
-  context->DetachGlobal();
-  CHECK_EQ(42, CompileRun("f(this).foo")->Int32Value());
-}

 static void CheckElementValue(i::Isolate* isolate,
                               int expected,
=======================================
--- /branches/3.23/test/cctest/test-decls.cc    Mon Nov 25 12:01:13 2013 UTC
+++ /branches/3.23/test/cctest/test-decls.cc    Wed Jan 15 16:25:55 2014 UTC
@@ -648,9 +648,9 @@
   virtual void PostInitializeContext(Handle<Context> context) {
     Local<Object> global_object = context->Global();
Local<Object> hidden_proto = hidden_proto_->GetFunction()->NewInstance();
-    context->DetachGlobal();
-    context->Global()->SetPrototype(hidden_proto);
-    context->ReattachGlobal(global_object);
+    Local<Object> inner_global =
+        Local<Object>::Cast(global_object->GetPrototype());
+    inner_global->SetPrototype(hidden_proto);
   }

   // Use the hidden prototype as the holder for the interceptors.
=======================================
--- /branches/3.23/test/cctest/test-object-observe.cc Thu Nov 28 13:42:41 2013 UTC +++ /branches/3.23/test/cctest/test-object-observe.cc Wed Jan 15 16:25:55 2014 UTC
@@ -242,7 +242,6 @@
   LocalContext context(isolate.GetIsolate());
   HandleScope scope(isolate.GetIsolate());
   Handle<Object> global_proxy = context->Global();
-  Handle<Object> inner_global = global_proxy->GetPrototype().As<Object>();
   CompileRun(
       "var records = [];"
       "var global = this;"
@@ -255,33 +254,26 @@
   context->DetachGlobal();
   CompileRun("global.bar = 'goodbye';");
   CHECK_EQ(1, CompileRun("records.length")->Int32Value());
-
-  // Mutating the global object directly still has an effect...
-  CompileRun("this.bar = 'goodbye';");
-  CHECK_EQ(2, CompileRun("records.length")->Int32Value());
-  CHECK(inner_global->StrictEquals(CompileRun("records[1].object")));
-
-  // Reattached, back to global proxy.
-  context->ReattachGlobal(global_proxy);
-  CompileRun("global.baz = 'again';");
-  CHECK_EQ(3, CompileRun("records.length")->Int32Value());
-  CHECK(global_proxy->StrictEquals(CompileRun("records[2].object")));
+  CompileRun("this.baz = 'goodbye';");
+  CHECK_EQ(1, CompileRun("records.length")->Int32Value());

   // Attached to a different context, should not leak mutations
   // to the old context.
   context->DetachGlobal();
   {
     LocalContext context2(isolate.GetIsolate());
-    context2->DetachGlobal();
-    context2->ReattachGlobal(global_proxy);
     CompileRun(
         "var records2 = [];"
+        "var global = this;"
         "Object.observe(this, function(r) { [].push.apply(records2, r) });"
-        "this.bat = 'context2';");
+        "this.v1 = 'context2';");
+    context2->DetachGlobal();
+    CompileRun(
+        "global.v2 = 'context2';"
+        "this.v3 = 'context2';");
     CHECK_EQ(1, CompileRun("records2.length")->Int32Value());
-    CHECK(global_proxy->StrictEquals(CompileRun("records2[0].object")));
   }
-  CHECK_EQ(3, CompileRun("records.length")->Int32Value());
+  CHECK_EQ(1, CompileRun("records.length")->Int32Value());

   // Attaching by passing to Context::New
   {
@@ -295,7 +287,7 @@
     CHECK_EQ(1, CompileRun("records3.length")->Int32Value());
     CHECK(global_proxy->StrictEquals(CompileRun("records3[0].object")));
   }
-  CHECK_EQ(3, CompileRun("records.length")->Int32Value());
+  CHECK_EQ(1, CompileRun("records.length")->Int32Value());
 }


--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to