summaryrefslogtreecommitdiff
path: root/deps/v8/test/cctest/test-api.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/test/cctest/test-api.cc')
-rw-r--r--deps/v8/test/cctest/test-api.cc235
1 files changed, 224 insertions, 11 deletions
diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc
index aeb4cbe52..f2af81eb7 100644
--- a/deps/v8/test/cctest/test-api.cc
+++ b/deps/v8/test/cctest/test-api.cc
@@ -14452,34 +14452,34 @@ TEST(RegExp) {
v8::Handle<v8::RegExp> re = v8::RegExp::New(v8_str("foo"), v8::RegExp::kNone);
CHECK(re->IsRegExp());
CHECK(re->GetSource()->Equals(v8_str("foo")));
- CHECK_EQ(re->GetFlags(), v8::RegExp::kNone);
+ CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
re = v8::RegExp::New(v8_str("bar"),
static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
v8::RegExp::kGlobal));
CHECK(re->IsRegExp());
CHECK(re->GetSource()->Equals(v8_str("bar")));
- CHECK_EQ(static_cast<int>(re->GetFlags()),
- v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal);
+ CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
+ static_cast<int>(re->GetFlags()));
re = v8::RegExp::New(v8_str("baz"),
static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
v8::RegExp::kMultiline));
CHECK(re->IsRegExp());
CHECK(re->GetSource()->Equals(v8_str("baz")));
- CHECK_EQ(static_cast<int>(re->GetFlags()),
- v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline);
+ CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
+ static_cast<int>(re->GetFlags()));
re = CompileRun("/quux/").As<v8::RegExp>();
CHECK(re->IsRegExp());
CHECK(re->GetSource()->Equals(v8_str("quux")));
- CHECK_EQ(re->GetFlags(), v8::RegExp::kNone);
+ CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
re = CompileRun("/quux/gm").As<v8::RegExp>();
CHECK(re->IsRegExp());
CHECK(re->GetSource()->Equals(v8_str("quux")));
- CHECK_EQ(static_cast<int>(re->GetFlags()),
- v8::RegExp::kGlobal | v8::RegExp::kMultiline);
+ CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
+ static_cast<int>(re->GetFlags()));
// Override the RegExp constructor and check the API constructor
// still works.
@@ -14488,15 +14488,15 @@ TEST(RegExp) {
re = v8::RegExp::New(v8_str("foobar"), v8::RegExp::kNone);
CHECK(re->IsRegExp());
CHECK(re->GetSource()->Equals(v8_str("foobar")));
- CHECK_EQ(re->GetFlags(), v8::RegExp::kNone);
+ CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
re = v8::RegExp::New(v8_str("foobarbaz"),
static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
v8::RegExp::kMultiline));
CHECK(re->IsRegExp());
CHECK(re->GetSource()->Equals(v8_str("foobarbaz")));
- CHECK_EQ(static_cast<int>(re->GetFlags()),
- v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline);
+ CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
+ static_cast<int>(re->GetFlags()));
context->Global()->Set(v8_str("re"), re);
ExpectTrue("re.test('FoobarbaZ')");
@@ -14937,3 +14937,216 @@ THREADED_TEST(Regress1516) {
}
}
}
+
+
+static bool BlockProtoNamedSecurityTestCallback(Local<v8::Object> global,
+ Local<Value> name,
+ v8::AccessType type,
+ Local<Value> data) {
+ // Only block read access to __proto__.
+ if (type == v8::ACCESS_GET &&
+ name->IsString() &&
+ name->ToString()->Length() == 9 &&
+ name->ToString()->Utf8Length() == 9) {
+ char buffer[10];
+ CHECK_EQ(10, name->ToString()->WriteUtf8(buffer));
+ return strncmp(buffer, "__proto__", 9) != 0;
+ }
+
+ return true;
+}
+
+
+THREADED_TEST(Regress93759) {
+ HandleScope scope;
+
+ // Template for object with security check.
+ Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New();
+ // We don't do indexing, so any callback can be used for that.
+ no_proto_template->SetAccessCheckCallbacks(
+ BlockProtoNamedSecurityTestCallback,
+ IndexedSecurityTestCallback);
+
+ // Templates for objects with hidden prototypes and possibly security check.
+ Local<FunctionTemplate> hidden_proto_template = v8::FunctionTemplate::New();
+ hidden_proto_template->SetHiddenPrototype(true);
+
+ Local<FunctionTemplate> protected_hidden_proto_template =
+ v8::FunctionTemplate::New();
+ protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallbacks(
+ BlockProtoNamedSecurityTestCallback,
+ IndexedSecurityTestCallback);
+ protected_hidden_proto_template->SetHiddenPrototype(true);
+
+ // Context for "foreign" objects used in test.
+ Persistent<Context> context = v8::Context::New();
+ context->Enter();
+
+ // Plain object, no security check.
+ Local<Object> simple_object = Object::New();
+
+ // Object with explicit security check.
+ Local<Object> protected_object =
+ no_proto_template->NewInstance();
+
+ // JSGlobalProxy object, always have security check.
+ Local<Object> proxy_object =
+ context->Global();
+
+ // Global object, the prototype of proxy_object. No security checks.
+ Local<Object> global_object =
+ proxy_object->GetPrototype()->ToObject();
+
+ // Hidden prototype without security check.
+ Local<Object> hidden_prototype =
+ hidden_proto_template->GetFunction()->NewInstance();
+ Local<Object> object_with_hidden =
+ Object::New();
+ object_with_hidden->SetPrototype(hidden_prototype);
+
+ // Hidden prototype with security check on the hidden prototype.
+ Local<Object> protected_hidden_prototype =
+ protected_hidden_proto_template->GetFunction()->NewInstance();
+ Local<Object> object_with_protected_hidden =
+ Object::New();
+ object_with_protected_hidden->SetPrototype(protected_hidden_prototype);
+
+ context->Exit();
+
+ // Template for object for second context. Values to test are put on it as
+ // properties.
+ Local<ObjectTemplate> global_template = ObjectTemplate::New();
+ global_template->Set(v8_str("simple"), simple_object);
+ global_template->Set(v8_str("protected"), protected_object);
+ global_template->Set(v8_str("global"), global_object);
+ global_template->Set(v8_str("proxy"), proxy_object);
+ global_template->Set(v8_str("hidden"), object_with_hidden);
+ global_template->Set(v8_str("phidden"), object_with_protected_hidden);
+
+ LocalContext context2(NULL, global_template);
+
+ Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
+ CHECK(result1->Equals(simple_object->GetPrototype()));
+
+ Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
+ CHECK(result2->Equals(Undefined()));
+
+ Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
+ CHECK(result3->Equals(global_object->GetPrototype()));
+
+ Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
+ CHECK(result4->Equals(Undefined()));
+
+ Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
+ CHECK(result5->Equals(
+ object_with_hidden->GetPrototype()->ToObject()->GetPrototype()));
+
+ Local<Value> result6 = CompileRun("Object.getPrototypeOf(phidden)");
+ CHECK(result6->Equals(Undefined()));
+
+ context.Dispose();
+}
+
+
+static void TestReceiver(Local<Value> expected_result,
+ Local<Value> expected_receiver,
+ const char* code) {
+ Local<Value> result = CompileRun(code);
+ CHECK(result->IsObject());
+ CHECK(expected_receiver->Equals(result->ToObject()->Get(1)));
+ CHECK(expected_result->Equals(result->ToObject()->Get(0)));
+}
+
+
+THREADED_TEST(ForeignFunctionReceiver) {
+ HandleScope scope;
+
+ // Create two contexts with different "id" properties ('i' and 'o').
+ // Call a function both from its own context and from a the foreign
+ // context, and see what "this" is bound to (returning both "this"
+ // and "this.id" for comparison).
+
+ Persistent<Context> foreign_context = v8::Context::New();
+ foreign_context->Enter();
+ Local<Value> foreign_function =
+ CompileRun("function func() { return { 0: this.id, "
+ " 1: this, "
+ " toString: function() { "
+ " return this[0];"
+ " }"
+ " };"
+ "}"
+ "var id = 'i';"
+ "func;");
+ CHECK(foreign_function->IsFunction());
+ foreign_context->Exit();
+
+ LocalContext context;
+
+ Local<String> password = v8_str("Password");
+ // Don't get hit by security checks when accessing foreign_context's
+ // global receiver (aka. global proxy).
+ context->SetSecurityToken(password);
+ foreign_context->SetSecurityToken(password);
+
+ Local<String> i = v8_str("i");
+ Local<String> o = v8_str("o");
+ Local<String> id = v8_str("id");
+
+ CompileRun("function ownfunc() { return { 0: this.id, "
+ " 1: this, "
+ " toString: function() { "
+ " return this[0];"
+ " }"
+ " };"
+ "}"
+ "var id = 'o';"
+ "ownfunc");
+ context->Global()->Set(v8_str("func"), foreign_function);
+
+ // Sanity check the contexts.
+ CHECK(i->Equals(foreign_context->Global()->Get(id)));
+ CHECK(o->Equals(context->Global()->Get(id)));
+
+ // Checking local function's receiver.
+ // Calling function using its call/apply methods.
+ TestReceiver(o, context->Global(), "ownfunc.call()");
+ TestReceiver(o, context->Global(), "ownfunc.apply()");
+ // Making calls through built-in functions.
+ TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
+ CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/,ownfunc)[1]")));
+ CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]")));
+ CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]")));
+ // Calling with environment record as base.
+ TestReceiver(o, context->Global(), "ownfunc()");
+ // Calling with no base.
+ TestReceiver(o, context->Global(), "(1,ownfunc)()");
+
+ // Checking foreign function return value.
+ // Calling function using its call/apply methods.
+ TestReceiver(i, foreign_context->Global(), "func.call()");
+ TestReceiver(i, foreign_context->Global(), "func.apply()");
+ // Calling function using another context's call/apply methods.
+ TestReceiver(i, foreign_context->Global(),
+ "Function.prototype.call.call(func)");
+ TestReceiver(i, foreign_context->Global(),
+ "Function.prototype.call.apply(func)");
+ TestReceiver(i, foreign_context->Global(),
+ "Function.prototype.apply.call(func)");
+ TestReceiver(i, foreign_context->Global(),
+ "Function.prototype.apply.apply(func)");
+ // Making calls through built-in functions.
+ TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
+ // ToString(func()) is func()[0], i.e., the returned this.id.
+ CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/,func)[1]")));
+ CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[1]")));
+ CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[3]")));
+
+ // TODO(1547): Make the following also return "i".
+ // Calling with environment record as base.
+ TestReceiver(o, context->Global(), "func()");
+ // Calling with no base.
+ TestReceiver(o, context->Global(), "(1,func)()");
+
+ foreign_context.Dispose();
+}