[strong] Add tests for loading from super, loading with access checks
authorconradw <conradw@chromium.org>
Thu, 2 Jul 2015 15:23:40 +0000 (08:23 -0700)
committerCommit bot <commit-bot@chromium.org>
Thu, 2 Jul 2015 15:23:48 +0000 (15:23 +0000)
BUG=v8:3956
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#29448}

test/cctest/test-api.cc
test/mjsunit/strong/load-builtins.js
test/mjsunit/strong/load-super.js [new file with mode: 0644]

index 5c844cb..49ee969 100644 (file)
@@ -21349,6 +21349,164 @@ TEST(SealHandleScopeNested) {
 }
 
 
+static bool access_was_called = false;
+
+
+static bool AccessAlwaysAllowedWithFlag(Local<v8::Object> global,
+                                        Local<Value> name, v8::AccessType type,
+                                        Local<Value> data) {
+  access_was_called = true;
+  return true;
+}
+
+
+static bool AccessAlwaysBlockedWithFlag(Local<v8::Object> global,
+                                        Local<Value> name, v8::AccessType type,
+                                        Local<Value> data) {
+  access_was_called = true;
+  return false;
+}
+
+
+TEST(StrongModeAccessCheckAllowed) {
+  i::FLAG_strong_mode = true;
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope handle_scope(isolate);
+  v8::Handle<Value> value;
+  access_was_called = false;
+
+  v8::Handle<v8::ObjectTemplate> obj_template =
+      v8::ObjectTemplate::New(isolate);
+
+  obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
+  obj_template->SetAccessCheckCallbacks(AccessAlwaysAllowedWithFlag, NULL);
+
+  // Create an environment
+  v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
+  context0->Enter();
+  v8::Handle<v8::Object> global0 = context0->Global();
+  global0->Set(v8_str("object"), obj_template->NewInstance());
+  {
+    v8::TryCatch try_catch(isolate);
+    value = CompileRun("'use strong'; object.x");
+    CHECK(!try_catch.HasCaught());
+    CHECK(!access_was_called);
+    CHECK_EQ(42, value->Int32Value());
+  }
+  {
+    v8::TryCatch try_catch(isolate);
+    value = CompileRun("'use strong'; object.foo");
+    CHECK(try_catch.HasCaught());
+    CHECK(!access_was_called);
+  }
+  {
+    v8::TryCatch try_catch(isolate);
+    value = CompileRun("'use strong'; object[10]");
+    CHECK(try_catch.HasCaught());
+    CHECK(!access_was_called);
+  }
+
+  // Create an environment
+  v8::Local<Context> context1 = Context::New(isolate);
+  context1->Enter();
+  v8::Handle<v8::Object> global1 = context1->Global();
+  global1->Set(v8_str("object"), obj_template->NewInstance());
+  {
+    v8::TryCatch try_catch(isolate);
+    value = CompileRun("'use strong'; object.x");
+    CHECK(!try_catch.HasCaught());
+    CHECK(access_was_called);
+    CHECK_EQ(42, value->Int32Value());
+  }
+  access_was_called = false;
+  {
+    v8::TryCatch try_catch(isolate);
+    value = CompileRun("'use strong'; object.foo");
+    CHECK(try_catch.HasCaught());
+    CHECK(access_was_called);
+  }
+  access_was_called = false;
+  {
+    v8::TryCatch try_catch(isolate);
+    value = CompileRun("'use strong'; object[10]");
+    CHECK(try_catch.HasCaught());
+    CHECK(access_was_called);
+  }
+
+  context1->Exit();
+  context0->Exit();
+}
+
+
+TEST(StrongModeAccessCheckBlocked) {
+  i::FLAG_strong_mode = true;
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope handle_scope(isolate);
+  v8::Handle<Value> value;
+  access_was_called = false;
+
+  v8::Handle<v8::ObjectTemplate> obj_template =
+      v8::ObjectTemplate::New(isolate);
+
+  obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
+  obj_template->SetAccessCheckCallbacks(AccessAlwaysBlockedWithFlag, NULL);
+
+  // Create an environment
+  v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
+  context0->Enter();
+  v8::Handle<v8::Object> global0 = context0->Global();
+  global0->Set(v8_str("object"), obj_template->NewInstance());
+  {
+    v8::TryCatch try_catch(isolate);
+    value = CompileRun("'use strong'; object.x");
+    CHECK(!try_catch.HasCaught());
+    CHECK(!access_was_called);
+    CHECK_EQ(42, value->Int32Value());
+  }
+  {
+    v8::TryCatch try_catch(isolate);
+    value = CompileRun("'use strong'; object.foo");
+    CHECK(try_catch.HasCaught());
+    CHECK(!access_was_called);
+  }
+  {
+    v8::TryCatch try_catch(isolate);
+    value = CompileRun("'use strong'; object[10]");
+    CHECK(try_catch.HasCaught());
+    CHECK(!access_was_called);
+  }
+
+  // Create an environment
+  v8::Local<Context> context1 = Context::New(isolate);
+  context1->Enter();
+  v8::Handle<v8::Object> global1 = context1->Global();
+  global1->Set(v8_str("object"), obj_template->NewInstance());
+  {
+    v8::TryCatch try_catch(isolate);
+    value = CompileRun("'use strong'; object.x");
+    CHECK(try_catch.HasCaught());
+    CHECK(access_was_called);
+  }
+  access_was_called = false;
+  {
+    v8::TryCatch try_catch(isolate);
+    value = CompileRun("'use strong'; object.foo");
+    CHECK(try_catch.HasCaught());
+    CHECK(access_was_called);
+  }
+  access_was_called = false;
+  {
+    v8::TryCatch try_catch(isolate);
+    value = CompileRun("'use strong'; object[10]");
+    CHECK(try_catch.HasCaught());
+    CHECK(access_was_called);
+  }
+
+  context1->Exit();
+  context0->Exit();
+}
+
+
 TEST(StrongModeArityCallFromApi) {
   i::FLAG_strong_mode = true;
   LocalContext env;
index 4266cc4..6638ff3 100644 (file)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --strong-mode --allow-natives-syntax
+// Flags: --strong-mode
 
 function getGlobal() {
   return this;
diff --git a/test/mjsunit/strong/load-super.js b/test/mjsunit/strong/load-super.js
new file mode 100644 (file)
index 0000000..4aa91c2
--- /dev/null
@@ -0,0 +1,102 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --strong-mode
+
+"use strong";
+
+function testSuper(object) {
+  assertEquals(0, object.validLoad());
+  assertThrows(function(){ return object.propertyLoad() }, TypeError);
+  assertThrows(function(){ return object.elementLoad()  }, TypeError);
+  assertThrows(function(){ return object.accessorLoad() }, TypeError);
+}
+
+class A {
+  constructor() {}
+  foo() {
+    return 0;
+  }
+  get bar() {
+    return 0;
+  }
+  set baz(_) {
+    return;
+  }
+}
+
+class B extends A {
+  constructor() {
+    super();
+  }
+  validLoad() {
+    return super.foo() + super.bar;
+  }
+  propertyLoad() {
+    return super.x;
+  }
+  elementLoad() {
+    return super[1];
+  }
+  accessorLoad() {
+    return super.baz;
+  }
+}
+
+class C extends A {
+  constructor() {
+    super();
+    this[1] = 0;
+    this.x = 0;
+  }
+  get baz() {
+    return 0;
+  }
+  validLoad() {
+    return super.foo() + super.bar;
+  }
+  propertyLoad() {
+    return super.x;
+  }
+  elementLoad() {
+    return super[1];
+  }
+  accessorLoad() {
+    return super.baz;
+  }
+}
+
+let b = new B();
+let c = new C();
+testSuper(b);
+testSuper(c);
+
+let d = {
+  "0": 0,
+  foo: 0,
+  bar: (function(){return 0}),
+  get baz(){return 0},
+  set qux(_){return}
+}
+
+let e = {
+  __proto__: d,
+  "1": 0,
+  x: 0,
+  get baz(){return 0},
+  validLoad() {
+    return super[0] + super.foo + super.bar() + super.baz;
+  },
+  propertyLoad() {
+    return super.x;
+  },
+  elementLoad() {
+    return super[1];
+  },
+  accessorLoad() {
+    return super.qux;
+  }
+}
+
+testSuper(e);