diff options
Diffstat (limited to 'deps/v8/test/cctest/test-api.cc')
-rw-r--r-- | deps/v8/test/cctest/test-api.cc | 235 |
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(); +} |