Line data Source code
1 : // Copyright 2015 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "test/cctest/cctest.h"
6 :
7 : #include "include/v8.h"
8 : #include "src/api.h"
9 : #include "src/objects-inl.h"
10 :
11 : namespace i = v8::internal;
12 :
13 : // The goal is to avoid the callback.
14 0 : static void UnreachableCallback(
15 : const v8::FunctionCallbackInfo<v8::Value>& info) {
16 0 : UNREACHABLE();
17 : }
18 :
19 23724 : TEST(CachedAccessor) {
20 : // Crankshaft support for fast accessors is not implemented; crankshafted
21 : // code uses the slow accessor which breaks this test's expectations.
22 6 : v8::internal::FLAG_always_opt = false;
23 6 : LocalContext env;
24 6 : v8::Isolate* isolate = env->GetIsolate();
25 12 : v8::HandleScope scope(isolate);
26 :
27 : // Create 'foo' class, with a hidden property.
28 6 : v8::Local<v8::ObjectTemplate> foo = v8::ObjectTemplate::New(isolate);
29 :
30 : v8::Local<v8::Private> priv =
31 6 : v8::Private::ForApi(isolate, v8_str("Foo#draft"));
32 :
33 : foo->SetAccessorProperty(v8_str("draft"), v8::FunctionTemplate::NewWithCache(
34 : isolate, UnreachableCallback,
35 12 : priv, v8::Local<v8::Value>()));
36 :
37 : // Create 'obj', instance of 'foo'.
38 6 : v8::Local<v8::Object> obj = foo->NewInstance(env.local()).ToLocalChecked();
39 :
40 : // Install the private property on the instance.
41 12 : CHECK(obj->SetPrivate(isolate->GetCurrentContext(), priv,
42 : v8::Undefined(isolate))
43 : .FromJust());
44 :
45 30 : CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust());
46 :
47 : // Access cached accessor.
48 6 : ExpectUndefined("obj.draft");
49 :
50 : // Set hidden property.
51 18 : CHECK(obj->SetPrivate(isolate->GetCurrentContext(), priv,
52 : v8_str("Shhh, I'm private!"))
53 : .FromJust());
54 :
55 6 : ExpectString("obj.draft", "Shhh, I'm private!");
56 :
57 : // Stress the accessor to use the IC.
58 : ExpectString(
59 : "var result = '';"
60 : "for (var i = 0; i < 10; ++i) { "
61 : " result = obj.draft; "
62 : "} "
63 : "result; ",
64 12 : "Shhh, I'm private!");
65 6 : }
66 :
67 23724 : TEST(CachedAccessorCrankshaft) {
68 6 : i::FLAG_allow_natives_syntax = true;
69 : // v8::internal::FLAG_always_opt = false;
70 6 : LocalContext env;
71 6 : v8::Isolate* isolate = env->GetIsolate();
72 12 : v8::HandleScope scope(isolate);
73 :
74 : // Create 'foo' class, with a hidden property.
75 6 : v8::Local<v8::ObjectTemplate> foo = v8::ObjectTemplate::New(isolate);
76 : v8::Local<v8::Private> priv =
77 6 : v8::Private::ForApi(isolate, v8_str("Foo#draft"));
78 :
79 : // Install the private property on the template.
80 : // foo->SetPrivate(priv, v8::Undefined(isolate));
81 :
82 : foo->SetAccessorProperty(v8_str("draft"), v8::FunctionTemplate::NewWithCache(
83 : isolate, UnreachableCallback,
84 12 : priv, v8::Local<v8::Value>()));
85 :
86 : // Create 'obj', instance of 'foo'.
87 6 : v8::Local<v8::Object> obj = foo->NewInstance(env.local()).ToLocalChecked();
88 :
89 : // Install the private property on the instance.
90 12 : CHECK(obj->SetPrivate(isolate->GetCurrentContext(), priv,
91 : v8::Undefined(isolate))
92 : .FromJust());
93 :
94 30 : CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust());
95 :
96 : // Access surrogate accessor.
97 6 : ExpectUndefined("obj.draft");
98 :
99 : // Set hidden property.
100 18 : CHECK(obj->SetPrivate(env.local(), priv, v8::Integer::New(isolate, 123))
101 : .FromJust());
102 :
103 : // Test ICs.
104 : CompileRun(
105 : "function f() {"
106 : " var x;"
107 : " for (var i = 0; i < 100; i++) {"
108 : " x = obj.draft;"
109 : " }"
110 : " return x;"
111 : "}");
112 :
113 6 : ExpectInt32("f()", 123);
114 :
115 : // Reset hidden property.
116 18 : CHECK(obj->SetPrivate(env.local(), priv, v8::Integer::New(isolate, 456))
117 : .FromJust());
118 :
119 : // Test Crankshaft.
120 : CompileRun("%OptimizeFunctionOnNextCall(f);");
121 :
122 6 : ExpectInt32("f()", 456);
123 :
124 18 : CHECK(obj->SetPrivate(env.local(), priv, v8::Integer::New(isolate, 456))
125 : .FromJust());
126 : // Test non-global ICs.
127 : CompileRun(
128 : "function g() {"
129 : " var x = obj;"
130 : " var r = 0;"
131 : " for (var i = 0; i < 100; i++) {"
132 : " r = x.draft;"
133 : " }"
134 : " return r;"
135 : "}");
136 :
137 6 : ExpectInt32("g()", 456);
138 :
139 : // Reset hidden property.
140 18 : CHECK(obj->SetPrivate(env.local(), priv, v8::Integer::New(isolate, 789))
141 : .FromJust());
142 :
143 : // Test non-global access in Crankshaft.
144 : CompileRun("%OptimizeFunctionOnNextCall(g);");
145 :
146 12 : ExpectInt32("g()", 789);
147 6 : }
148 :
149 23724 : TEST(CachedAccessorOnGlobalObject) {
150 6 : i::FLAG_allow_natives_syntax = true;
151 6 : LocalContext env;
152 6 : v8::Isolate* isolate = env->GetIsolate();
153 12 : v8::HandleScope scope(isolate);
154 :
155 : v8::Local<v8::FunctionTemplate> templ =
156 6 : v8::FunctionTemplate::New(CcTest::isolate());
157 6 : v8::Local<v8::ObjectTemplate> object_template = templ->InstanceTemplate();
158 : v8::Local<v8::Private> priv =
159 6 : v8::Private::ForApi(isolate, v8_str("Foo#draft"));
160 :
161 : object_template->SetAccessorProperty(
162 : v8_str("draft"),
163 : v8::FunctionTemplate::NewWithCache(isolate, UnreachableCallback, priv,
164 12 : v8::Local<v8::Value>()));
165 :
166 : v8::Local<v8::Context> ctx =
167 6 : v8::Context::New(CcTest::isolate(), nullptr, object_template);
168 6 : v8::Local<v8::Object> obj = ctx->Global();
169 :
170 : // Install the private property on the instance.
171 12 : CHECK(obj->SetPrivate(isolate->GetCurrentContext(), priv,
172 : v8::Undefined(isolate))
173 : .FromJust());
174 :
175 : {
176 : v8::Context::Scope context_scope(ctx);
177 :
178 : // Access surrogate accessor.
179 6 : ExpectUndefined("draft");
180 :
181 : // Set hidden property.
182 18 : CHECK(obj->SetPrivate(env.local(), priv, v8::Integer::New(isolate, 123))
183 : .FromJust());
184 :
185 : // Test ICs.
186 : CompileRun(
187 : "function f() {"
188 : " var x;"
189 : " for (var i = 0; i < 100; i++) {"
190 : " x = draft;"
191 : " }"
192 : " return x;"
193 : "}");
194 :
195 6 : ExpectInt32("f()", 123);
196 :
197 : // Reset hidden property.
198 18 : CHECK(obj->SetPrivate(env.local(), priv, v8::Integer::New(isolate, 456))
199 : .FromJust());
200 :
201 : // Test Crankshaft.
202 : CompileRun("%OptimizeFunctionOnNextCall(f);");
203 :
204 6 : ExpectInt32("f()", 456);
205 :
206 18 : CHECK(obj->SetPrivate(env.local(), priv, v8::Integer::New(isolate, 456))
207 : .FromJust());
208 : // Test non-global ICs.
209 : CompileRun(
210 : "var x = this;"
211 : "function g() {"
212 : " var r = 0;"
213 : " for (var i = 0; i < 100; i++) {"
214 : " r = x.draft;"
215 : " }"
216 : " return r;"
217 : "}");
218 :
219 6 : ExpectInt32("g()", 456);
220 :
221 : // Reset hidden property.
222 18 : CHECK(obj->SetPrivate(env.local(), priv, v8::Integer::New(isolate, 789))
223 : .FromJust());
224 :
225 : // Test non-global access in Crankshaft.
226 : CompileRun("%OptimizeFunctionOnNextCall(g);");
227 :
228 6 : ExpectInt32("g()", 789);
229 6 : }
230 6 : }
231 :
232 : namespace {
233 :
234 0 : static void Setter(v8::Local<v8::String> name, v8::Local<v8::Value> value,
235 0 : const v8::PropertyCallbackInfo<void>& info) {}
236 : }
237 :
238 : // Re-declaration of non-configurable accessors should throw.
239 23724 : TEST(RedeclareAccessor) {
240 6 : v8::HandleScope scope(CcTest::isolate());
241 12 : LocalContext env;
242 :
243 : v8::Local<v8::FunctionTemplate> templ =
244 6 : v8::FunctionTemplate::New(CcTest::isolate());
245 :
246 6 : v8::Local<v8::ObjectTemplate> object_template = templ->InstanceTemplate();
247 : object_template->SetAccessor(
248 : v8_str("foo"), nullptr, Setter, v8::Local<v8::Value>(),
249 12 : v8::AccessControl::DEFAULT, v8::PropertyAttribute::DontDelete);
250 :
251 : v8::Local<v8::Context> ctx =
252 6 : v8::Context::New(CcTest::isolate(), nullptr, object_template);
253 :
254 : // Declare function.
255 6 : v8::Local<v8::String> code = v8_str("function foo() {};");
256 :
257 12 : v8::TryCatch try_catch(CcTest::isolate());
258 12 : v8::Script::Compile(ctx, code).ToLocalChecked()->Run(ctx).IsEmpty();
259 12 : CHECK(try_catch.HasCaught());
260 71160 : }
|