OLD | NEW |
1 // Copyright 2017 the V8 project authors. All rights reserved. | 1 // Copyright 2017 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "include/v8.h" | 5 #include "include/v8.h" |
| 6 #include "src/api.h" |
| 7 #include "src/objects-inl.h" |
6 #include "test/unittests/test-utils.h" | 8 #include "test/unittests/test-utils.h" |
7 #include "testing/gtest/include/gtest/gtest.h" | 9 #include "testing/gtest/include/gtest/gtest.h" |
8 | 10 |
9 namespace v8 { | 11 namespace v8 { |
10 namespace { | 12 namespace { |
11 | 13 |
12 using ObjectTest = TestWithContext; | 14 using ObjectTest = TestWithContext; |
13 | 15 |
14 void accessor_name_getter_callback(Local<Name>, | 16 void accessor_name_getter_callback(Local<Name>, |
15 const PropertyCallbackInfo<Value>&) {} | 17 const PropertyCallbackInfo<Value>&) {} |
(...skipping 10 matching lines...) Expand all Loading... |
26 prop_desc.set_configurable(false); | 28 prop_desc.set_configurable(false); |
27 global->DefineProperty(context(), property_name, prop_desc).ToChecked(); | 29 global->DefineProperty(context(), property_name, prop_desc).ToChecked(); |
28 | 30 |
29 Maybe<bool> result = global->SetAccessor(context(), property_name, | 31 Maybe<bool> result = global->SetAccessor(context(), property_name, |
30 accessor_name_getter_callback); | 32 accessor_name_getter_callback); |
31 ASSERT_TRUE(result.IsJust()); | 33 ASSERT_TRUE(result.IsJust()); |
32 ASSERT_FALSE(result.FromJust()); | 34 ASSERT_FALSE(result.FromJust()); |
33 ASSERT_FALSE(try_catch.HasCaught()); | 35 ASSERT_FALSE(try_catch.HasCaught()); |
34 } | 36 } |
35 | 37 |
| 38 using LapContextTest = TestWithIsolate; |
| 39 |
| 40 TEST_F(LapContextTest, CurrentContextMustBeFunctionContext) { |
| 41 // The receiver object is created in |receiver_context|, but its prototype |
| 42 // object is created in |prototype_context|, and the property is accessed |
| 43 // from |caller_context|. |
| 44 Local<Context> receiver_context = Context::New(isolate()); |
| 45 Local<Context> prototype_context = Context::New(isolate()); |
| 46 Local<Context> caller_context = Context::New(isolate()); |
| 47 |
| 48 Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate()); |
| 49 Local<Signature> signature = Signature::New(isolate(), function_template); |
| 50 Local<String> property_key = |
| 51 String::NewFromUtf8(isolate(), "property", NewStringType::kNormal) |
| 52 .ToLocalChecked(); |
| 53 Local<FunctionTemplate> get_or_set = FunctionTemplate::New( |
| 54 isolate(), |
| 55 [](const FunctionCallbackInfo<Value>& info) { |
| 56 Local<Context> prototype_context = *reinterpret_cast<Local<Context>*>( |
| 57 info.Data().As<External>()->Value()); |
| 58 EXPECT_EQ(prototype_context, info.GetIsolate()->GetCurrentContext()); |
| 59 }, |
| 60 External::New(isolate(), &prototype_context), signature); |
| 61 function_template->PrototypeTemplate()->SetAccessorProperty( |
| 62 property_key, get_or_set, get_or_set); |
| 63 |
| 64 // |object| is created in |receiver_context|, and |prototype| is created |
| 65 // in |prototype_context|. And then, object.__proto__ = prototype. |
| 66 Local<Function> interface_for_receiver = |
| 67 function_template->GetFunction(receiver_context).ToLocalChecked(); |
| 68 Local<Function> interface_for_prototype = |
| 69 function_template->GetFunction(prototype_context).ToLocalChecked(); |
| 70 Local<String> prototype_key = |
| 71 String::NewFromUtf8(isolate(), "prototype", NewStringType::kNormal) |
| 72 .ToLocalChecked(); |
| 73 Local<Object> prototype = |
| 74 interface_for_prototype->Get(caller_context, prototype_key) |
| 75 .ToLocalChecked() |
| 76 .As<Object>(); |
| 77 Local<Object> object = |
| 78 interface_for_receiver->NewInstance(receiver_context).ToLocalChecked(); |
| 79 object->SetPrototype(caller_context, prototype).ToChecked(); |
| 80 EXPECT_EQ(receiver_context, object->CreationContext()); |
| 81 EXPECT_EQ(prototype_context, prototype->CreationContext()); |
| 82 |
| 83 object->Get(caller_context, property_key).ToLocalChecked(); |
| 84 object->Set(caller_context, property_key, Null(isolate())).ToChecked(); |
| 85 |
| 86 // Test with a compiled version. |
| 87 Local<String> object_key = |
| 88 String::NewFromUtf8(isolate(), "object", NewStringType::kNormal) |
| 89 .ToLocalChecked(); |
| 90 caller_context->Global()->Set(caller_context, object_key, object).ToChecked(); |
| 91 const char script[] = |
| 92 "function f() { object.property; object.property = 0; } " |
| 93 "f(); f(); " |
| 94 "%OptimizeFunctionOnNextCall(f); " |
| 95 "f();"; |
| 96 Context::Scope scope(caller_context); |
| 97 internal::FLAG_allow_natives_syntax = true; |
| 98 Script::Compile( |
| 99 caller_context, |
| 100 String::NewFromUtf8(isolate(), script, v8::NewStringType::kNormal) |
| 101 .ToLocalChecked()) |
| 102 .ToLocalChecked() |
| 103 ->Run(caller_context) |
| 104 .ToLocalChecked(); |
| 105 } |
| 106 |
36 } // namespace | 107 } // namespace |
37 } // namespace v8 | 108 } // namespace v8 |
OLD | NEW |