Line data Source code
1 : // Copyright 2007-2008 the V8 project authors. All rights reserved.
2 : // Redistribution and use in source and binary forms, with or without
3 : // modification, are permitted provided that the following conditions are
4 : // met:
5 : //
6 : // * Redistributions of source code must retain the above copyright
7 : // notice, this list of conditions and the following disclaimer.
8 : // * Redistributions in binary form must reproduce the above
9 : // copyright notice, this list of conditions and the following
10 : // disclaimer in the documentation and/or other materials provided
11 : // with the distribution.
12 : // * Neither the name of Google Inc. nor the names of its
13 : // contributors may be used to endorse or promote products derived
14 : // from this software without specific prior written permission.
15 : //
16 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 : // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 : // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 : // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 : // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 : // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 : // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 : // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 : // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 : // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 :
28 : #include <stdlib.h>
29 :
30 : #include "src/v8.h"
31 :
32 : #include "test/cctest/cctest.h"
33 :
34 : namespace v8 {
35 :
36 : namespace {
37 :
38 : enum Expectations {
39 : EXPECT_RESULT,
40 : EXPECT_EXCEPTION,
41 : EXPECT_ERROR
42 : };
43 :
44 :
45 : // A DeclarationContext holds a reference to a v8::Context and keeps
46 : // track of various declaration related counters to make it easier to
47 : // track if global declarations in the presence of interceptors behave
48 : // the right way.
49 : class DeclarationContext {
50 : public:
51 : DeclarationContext();
52 :
53 140 : virtual ~DeclarationContext() {
54 70 : if (is_initialized_) {
55 70 : Isolate* isolate = CcTest::isolate();
56 140 : HandleScope scope(isolate);
57 : Local<Context> context = Local<Context>::New(isolate, context_);
58 70 : context->Exit();
59 : context_.Reset();
60 : }
61 70 : }
62 :
63 : void Check(const char* source, int get, int set, int has,
64 : Expectations expectations,
65 : v8::Local<Value> value = Local<Value>());
66 :
67 : int get_count() const { return get_count_; }
68 : int set_count() const { return set_count_; }
69 : int query_count() const { return query_count_; }
70 :
71 : protected:
72 : virtual v8::Local<Value> Get(Local<Name> key);
73 : virtual v8::Local<Value> Set(Local<Name> key, Local<Value> value);
74 : virtual v8::Local<Integer> Query(Local<Name> key);
75 :
76 : void InitializeIfNeeded();
77 :
78 : // Perform optional initialization steps on the context after it has
79 : // been created. Defaults to none but may be overwritten.
80 0 : virtual void PostInitializeContext(Local<Context> context) {}
81 :
82 : // Get the holder for the interceptor. Default to the instance template
83 : // but may be overwritten.
84 50 : virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
85 50 : return function->InstanceTemplate();
86 : }
87 :
88 : // The handlers are called as static functions that forward
89 : // to the instance specific virtual methods.
90 : static void HandleGet(Local<Name> key,
91 : const v8::PropertyCallbackInfo<v8::Value>& info);
92 : static void HandleSet(Local<Name> key, Local<Value> value,
93 : const v8::PropertyCallbackInfo<v8::Value>& info);
94 : static void HandleQuery(Local<Name> key,
95 : const v8::PropertyCallbackInfo<v8::Integer>& info);
96 :
97 5 : v8::Isolate* isolate() const { return CcTest::isolate(); }
98 :
99 : private:
100 : bool is_initialized_;
101 : Persistent<Context> context_;
102 :
103 : int get_count_;
104 : int set_count_;
105 : int query_count_;
106 :
107 : static DeclarationContext* GetInstance(Local<Value> data);
108 : };
109 :
110 :
111 : DeclarationContext::DeclarationContext()
112 140 : : is_initialized_(false), get_count_(0), set_count_(0), query_count_(0) {
113 : // Do nothing.
114 : }
115 :
116 :
117 85 : void DeclarationContext::InitializeIfNeeded() {
118 100 : if (is_initialized_) return;
119 70 : Isolate* isolate = CcTest::isolate();
120 140 : HandleScope scope(isolate);
121 70 : Local<FunctionTemplate> function = FunctionTemplate::New(isolate);
122 70 : Local<Value> data = External::New(CcTest::isolate(), this);
123 140 : GetHolder(function)->SetHandler(v8::NamedPropertyHandlerConfiguration(
124 70 : &HandleGet, &HandleSet, &HandleQuery, nullptr, nullptr, data));
125 : Local<Context> context = Context::New(
126 140 : isolate, nullptr, function->InstanceTemplate(), Local<Value>());
127 : context_.Reset(isolate, context);
128 70 : context->Enter();
129 70 : is_initialized_ = true;
130 : // Reset counts. Bootstrapping might have called into the interceptor.
131 70 : get_count_ = 0;
132 70 : set_count_ = 0;
133 70 : query_count_ = 0;
134 : PostInitializeContext(context);
135 : }
136 :
137 :
138 70 : void DeclarationContext::Check(const char* source, int get, int set, int query,
139 : Expectations expectations,
140 : v8::Local<Value> value) {
141 70 : InitializeIfNeeded();
142 : // A retry after a GC may pollute the counts, so perform gc now
143 : // to avoid that.
144 70 : CcTest::CollectGarbage(v8::internal::NEW_SPACE);
145 140 : HandleScope scope(CcTest::isolate());
146 140 : TryCatch catcher(CcTest::isolate());
147 70 : catcher.SetVerbose(true);
148 70 : Local<Context> context = CcTest::isolate()->GetCurrentContext();
149 : MaybeLocal<Script> script = Script::Compile(
150 : context,
151 70 : String::NewFromUtf8(CcTest::isolate(), source, v8::NewStringType::kNormal)
152 70 : .ToLocalChecked());
153 70 : if (expectations == EXPECT_ERROR) {
154 0 : CHECK(script.IsEmpty());
155 0 : return;
156 : }
157 70 : CHECK(!script.IsEmpty());
158 70 : MaybeLocal<Value> result = script.ToLocalChecked()->Run(context);
159 70 : CHECK_EQ(get, get_count());
160 70 : CHECK_EQ(set, set_count());
161 70 : CHECK_EQ(query, query_count());
162 70 : if (expectations == EXPECT_RESULT) {
163 70 : CHECK(!catcher.HasCaught());
164 70 : if (!value.IsEmpty()) {
165 110 : CHECK(value->Equals(context, result.ToLocalChecked()).FromJust());
166 : }
167 : } else {
168 0 : CHECK(expectations == EXPECT_EXCEPTION);
169 0 : CHECK(catcher.HasCaught());
170 0 : if (!value.IsEmpty()) {
171 0 : CHECK(value->Equals(context, catcher.Exception()).FromJust());
172 : }
173 : }
174 : // Clean slate for the next test.
175 70 : CcTest::CollectAllAvailableGarbage();
176 : }
177 :
178 :
179 50 : void DeclarationContext::HandleGet(
180 : Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>& info) {
181 : DeclarationContext* context = GetInstance(info.Data());
182 50 : context->get_count_++;
183 : info.GetReturnValue().Set(context->Get(key));
184 50 : }
185 :
186 :
187 30 : void DeclarationContext::HandleSet(
188 : Local<Name> key, Local<Value> value,
189 : const v8::PropertyCallbackInfo<v8::Value>& info) {
190 : DeclarationContext* context = GetInstance(info.Data());
191 30 : context->set_count_++;
192 : info.GetReturnValue().Set(context->Set(key, value));
193 30 : }
194 :
195 :
196 20 : void DeclarationContext::HandleQuery(
197 : Local<Name> key, const v8::PropertyCallbackInfo<v8::Integer>& info) {
198 : DeclarationContext* context = GetInstance(info.Data());
199 20 : context->query_count_++;
200 20 : info.GetReturnValue().Set(context->Query(key));
201 20 : }
202 :
203 :
204 : DeclarationContext* DeclarationContext::GetInstance(Local<Value> data) {
205 100 : void* value = Local<External>::Cast(data)->Value();
206 : return static_cast<DeclarationContext*>(value);
207 : }
208 :
209 :
210 0 : v8::Local<Value> DeclarationContext::Get(Local<Name> key) {
211 0 : return v8::Local<Value>();
212 : }
213 :
214 :
215 0 : v8::Local<Value> DeclarationContext::Set(Local<Name> key, Local<Value> value) {
216 0 : return v8::Local<Value>();
217 : }
218 :
219 :
220 5 : v8::Local<Integer> DeclarationContext::Query(Local<Name> key) {
221 5 : return v8::Local<Integer>();
222 : }
223 :
224 : } // namespace
225 :
226 : // Test global declaration of a property the interceptor doesn't know
227 : // about and doesn't handle.
228 26644 : TEST(Unknown) {
229 10 : HandleScope scope(CcTest::isolate());
230 5 : v8::V8::Initialize();
231 :
232 5 : { DeclarationContext context;
233 10 : context.Check("var x; x",
234 : 1, // access
235 5 : 0, 0, EXPECT_RESULT, Undefined(CcTest::isolate()));
236 : }
237 :
238 5 : { DeclarationContext context;
239 10 : context.Check("var x = 0; x",
240 : 1, // access
241 : 1, // initialization
242 5 : 0, EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
243 : }
244 :
245 5 : { DeclarationContext context;
246 5 : context.Check("function x() { }; x",
247 : 1, // access
248 5 : 1, 1, EXPECT_RESULT);
249 : }
250 5 : }
251 :
252 :
253 40 : class AbsentPropertyContext: public DeclarationContext {
254 : protected:
255 5 : v8::Local<Integer> Query(Local<Name> key) override {
256 5 : return v8::Local<Integer>();
257 : }
258 : };
259 :
260 :
261 26644 : TEST(Absent) {
262 5 : v8::Isolate* isolate = CcTest::isolate();
263 5 : v8::V8::Initialize();
264 10 : HandleScope scope(isolate);
265 :
266 : { AbsentPropertyContext context;
267 5 : context.Check("var x; x",
268 : 1, // access
269 5 : 0, 0, EXPECT_RESULT, Undefined(isolate));
270 : }
271 :
272 : { AbsentPropertyContext context;
273 10 : context.Check("var x = 0; x",
274 : 1, // access
275 : 1, // initialization
276 5 : 0, EXPECT_RESULT, Number::New(isolate, 0));
277 : }
278 :
279 : { AbsentPropertyContext context;
280 5 : context.Check("function x() { }; x",
281 : 1, // access
282 5 : 1, 1, EXPECT_RESULT);
283 : }
284 :
285 : { AbsentPropertyContext context;
286 5 : context.Check("if (false) { var x = 0 }; x",
287 : 1, // access
288 5 : 0, 0, EXPECT_RESULT, Undefined(isolate));
289 : }
290 5 : }
291 :
292 :
293 :
294 15 : class AppearingPropertyContext: public DeclarationContext {
295 : public:
296 : enum State {
297 : DECLARE,
298 : INITIALIZE_IF_ASSIGN,
299 : UNKNOWN
300 : };
301 :
302 15 : AppearingPropertyContext() : state_(DECLARE) { }
303 :
304 : protected:
305 5 : v8::Local<Integer> Query(Local<Name> key) override {
306 5 : switch (state_) {
307 : case DECLARE:
308 : // Force declaration by returning that the
309 : // property is absent.
310 5 : state_ = INITIALIZE_IF_ASSIGN;
311 5 : return Local<Integer>();
312 : case INITIALIZE_IF_ASSIGN:
313 : // Return that the property is present so we only get the
314 : // setter called when initializing with a value.
315 0 : state_ = UNKNOWN;
316 0 : return Integer::New(isolate(), v8::None);
317 : default:
318 0 : CHECK(state_ == UNKNOWN);
319 : break;
320 : }
321 : // Do the lookup in the object.
322 0 : return v8::Local<Integer>();
323 : }
324 :
325 : private:
326 : State state_;
327 : };
328 :
329 :
330 26644 : TEST(Appearing) {
331 5 : v8::V8::Initialize();
332 10 : HandleScope scope(CcTest::isolate());
333 :
334 : { AppearingPropertyContext context;
335 10 : context.Check("var x; x",
336 : 1, // access
337 5 : 0, 0, EXPECT_RESULT, Undefined(CcTest::isolate()));
338 : }
339 :
340 : { AppearingPropertyContext context;
341 10 : context.Check("var x = 0; x",
342 : 1, // access
343 : 1, // initialization
344 5 : 0, EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
345 : }
346 :
347 : { AppearingPropertyContext context;
348 5 : context.Check("function x() { }; x",
349 : 1, // access
350 5 : 1, 1, EXPECT_RESULT);
351 : }
352 5 : }
353 :
354 :
355 :
356 15 : class ExistsInPrototypeContext: public DeclarationContext {
357 : public:
358 15 : ExistsInPrototypeContext() { InitializeIfNeeded(); }
359 : protected:
360 5 : v8::Local<Integer> Query(Local<Name> key) override {
361 : // Let it seem that the property exists in the prototype object.
362 5 : return Integer::New(isolate(), v8::None);
363 : }
364 :
365 : // Use the prototype as the holder for the interceptors.
366 15 : Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) override {
367 15 : return function->PrototypeTemplate();
368 : }
369 : };
370 :
371 :
372 26644 : TEST(ExistsInPrototype) {
373 10 : HandleScope scope(CcTest::isolate());
374 :
375 : // Sanity check to make sure that the holder of the interceptor
376 : // really is the prototype object.
377 : { ExistsInPrototypeContext context;
378 10 : context.Check("this.x = 87; this.x", 0, 0, 1, EXPECT_RESULT,
379 5 : Number::New(CcTest::isolate(), 87));
380 : }
381 :
382 : { ExistsInPrototypeContext context;
383 10 : context.Check("var x; x",
384 : 0,
385 : 0,
386 : 0,
387 5 : EXPECT_RESULT, Undefined(CcTest::isolate()));
388 : }
389 :
390 : { ExistsInPrototypeContext context;
391 10 : context.Check("var x = 0; x",
392 : 0,
393 : 0,
394 : 0,
395 5 : EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
396 : }
397 5 : }
398 :
399 :
400 :
401 10 : class AbsentInPrototypeContext: public DeclarationContext {
402 : protected:
403 0 : v8::Local<Integer> Query(Local<Name> key) override {
404 : // Let it seem that the property is absent in the prototype object.
405 0 : return Local<Integer>();
406 : }
407 :
408 : // Use the prototype as the holder for the interceptors.
409 5 : Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) override {
410 5 : return function->PrototypeTemplate();
411 : }
412 : };
413 :
414 :
415 26644 : TEST(AbsentInPrototype) {
416 5 : v8::V8::Initialize();
417 10 : HandleScope scope(CcTest::isolate());
418 :
419 : { AbsentInPrototypeContext context;
420 10 : context.Check("if (false) { var x = 0; }; x",
421 : 0,
422 : 0,
423 : 0,
424 5 : EXPECT_RESULT, Undefined(CcTest::isolate()));
425 : }
426 5 : }
427 :
428 :
429 :
430 : class SimpleContext {
431 : public:
432 705 : SimpleContext()
433 : : handle_scope_(CcTest::isolate()),
434 1410 : context_(Context::New(CcTest::isolate())) {
435 705 : context_->Enter();
436 705 : }
437 :
438 705 : ~SimpleContext() {
439 705 : context_->Exit();
440 : }
441 :
442 2950 : void Check(const char* source, Expectations expectations,
443 : v8::Local<Value> value = Local<Value>()) {
444 5900 : HandleScope scope(context_->GetIsolate());
445 5900 : TryCatch catcher(context_->GetIsolate());
446 2950 : catcher.SetVerbose(true);
447 : MaybeLocal<Script> script = Script::Compile(
448 2950 : context_, String::NewFromUtf8(context_->GetIsolate(), source,
449 2950 : v8::NewStringType::kNormal)
450 2950 : .ToLocalChecked());
451 2950 : if (expectations == EXPECT_ERROR) {
452 0 : CHECK(script.IsEmpty());
453 0 : return;
454 : }
455 2950 : CHECK(!script.IsEmpty());
456 2950 : MaybeLocal<Value> result = script.ToLocalChecked()->Run(context_);
457 2950 : if (expectations == EXPECT_RESULT) {
458 2285 : CHECK(!catcher.HasCaught());
459 2285 : if (!value.IsEmpty()) {
460 4570 : CHECK(value->Equals(context_, result.ToLocalChecked()).FromJust());
461 : }
462 : } else {
463 665 : CHECK(expectations == EXPECT_EXCEPTION);
464 665 : CHECK(catcher.HasCaught());
465 665 : if (!value.IsEmpty()) {
466 0 : CHECK(value->Equals(context_, catcher.Exception()).FromJust());
467 : }
468 : }
469 : }
470 :
471 : private:
472 : HandleScope handle_scope_;
473 : Local<Context> context_;
474 : };
475 :
476 :
477 26644 : TEST(CrossScriptReferences) {
478 5 : v8::Isolate* isolate = CcTest::isolate();
479 10 : HandleScope scope(isolate);
480 :
481 5 : { SimpleContext context;
482 10 : context.Check("var x = 1; x",
483 5 : EXPECT_RESULT, Number::New(isolate, 1));
484 10 : context.Check("var x = 2; x",
485 5 : EXPECT_RESULT, Number::New(isolate, 2));
486 10 : context.Check("x = 5; x",
487 5 : EXPECT_RESULT, Number::New(isolate, 5));
488 10 : context.Check("var x = 6; x",
489 5 : EXPECT_RESULT, Number::New(isolate, 6));
490 10 : context.Check("this.x",
491 5 : EXPECT_RESULT, Number::New(isolate, 6));
492 10 : context.Check("function x() { return 7 }; x()",
493 5 : EXPECT_RESULT, Number::New(isolate, 7));
494 : }
495 5 : }
496 :
497 :
498 26644 : TEST(CrossScriptReferences_Simple) {
499 5 : i::FLAG_use_strict = true;
500 :
501 5 : v8::Isolate* isolate = CcTest::isolate();
502 10 : HandleScope scope(isolate);
503 :
504 : {
505 5 : SimpleContext context;
506 10 : context.Check("let x = 1; x", EXPECT_RESULT, Number::New(isolate, 1));
507 5 : context.Check("let x = 5; x", EXPECT_EXCEPTION);
508 : }
509 5 : }
510 :
511 :
512 26644 : TEST(CrossScriptReferences_Simple2) {
513 5 : i::FLAG_use_strict = true;
514 :
515 5 : v8::Isolate* isolate = CcTest::isolate();
516 10 : HandleScope scope(isolate);
517 :
518 1005 : for (int k = 0; k < 100; k++) {
519 500 : SimpleContext context;
520 500 : bool cond = (k % 2) == 0;
521 500 : if (cond) {
522 500 : context.Check("let x = 1; x", EXPECT_RESULT, Number::New(isolate, 1));
523 500 : context.Check("let z = 4; z", EXPECT_RESULT, Number::New(isolate, 4));
524 : } else {
525 500 : context.Check("let z = 1; z", EXPECT_RESULT, Number::New(isolate, 1));
526 500 : context.Check("let x = 4; x", EXPECT_RESULT, Number::New(isolate, 4));
527 : }
528 1000 : context.Check("let y = 2; x", EXPECT_RESULT,
529 500 : Number::New(isolate, cond ? 1 : 4));
530 : }
531 5 : }
532 :
533 :
534 26644 : TEST(CrossScriptReferencesHarmony) {
535 5 : v8::Isolate* isolate = CcTest::isolate();
536 10 : HandleScope scope(isolate);
537 :
538 : // Check that simple cross-script global scope access works.
539 : const char* decs[] = {"'use strict'; var x = 1; x",
540 : "x",
541 : "'use strict'; function x() { return 1 }; x()",
542 : "x()",
543 : "'use strict'; let x = 1; x",
544 : "x",
545 : "'use strict'; const x = 1; x",
546 : "x",
547 5 : nullptr};
548 :
549 45 : for (int i = 0; decs[i] != nullptr; i += 2) {
550 20 : SimpleContext context;
551 40 : context.Check(decs[i], EXPECT_RESULT, Number::New(isolate, 1));
552 40 : context.Check(decs[i+1], EXPECT_RESULT, Number::New(isolate, 1));
553 : }
554 :
555 : // Check that cross-script global scope access works with late declarations.
556 : {
557 5 : SimpleContext context;
558 5 : context.Check("function d0() { return x0 }", // dynamic lookup
559 5 : EXPECT_RESULT, Undefined(isolate));
560 10 : context.Check("this.x0 = -1;"
561 : "d0()",
562 5 : EXPECT_RESULT, Number::New(isolate, -1));
563 10 : context.Check("'use strict';"
564 : "function f0() { let y = 10; return x0 + y }"
565 : "function g0() { let y = 10; return eval('x0 + y') }"
566 : "function h0() { let y = 10; return (1,eval)('x0') + y }"
567 : "x0 + f0() + g0() + h0()",
568 5 : EXPECT_RESULT, Number::New(isolate, 26));
569 :
570 10 : context.Check("'use strict';"
571 : "let x1 = 1;"
572 : "function f1() { let y = 10; return x1 + y }"
573 : "function g1() { let y = 10; return eval('x1 + y') }"
574 : "function h1() { let y = 10; return (1,eval)('x1') + y }"
575 : "function i1() { "
576 : " let y = 10; return (typeof x2 === 'undefined' ? 0 : 2) + y"
577 : "}"
578 : "function j1() { let y = 10; return eval('x2 + y') }"
579 : "function k1() { let y = 10; return (1,eval)('x2') + y }"
580 : "function cl() { "
581 : " let y = 10; "
582 : " return { "
583 : " f: function(){ return x1 + y },"
584 : " g: function(){ return eval('x1 + y') },"
585 : " h: function(){ return (1,eval)('x1') + y },"
586 : " i: function(){"
587 : " return (typeof x2 == 'undefined' ? 0 : 2) + y"
588 : " },"
589 : " j: function(){ return eval('x2 + y') },"
590 : " k: function(){ return (1,eval)('x2') + y },"
591 : " }"
592 : "}"
593 : "let o = cl();"
594 : "x1 + eval('x1') + (1,eval)('x1') + f1() + g1() + h1();",
595 5 : EXPECT_RESULT, Number::New(isolate, 36));
596 10 : context.Check("x1 + eval('x1') + (1,eval)('x1') + f1() + g1() + h1();",
597 5 : EXPECT_RESULT, Number::New(isolate, 36));
598 10 : context.Check("o.f() + o.g() + o.h();",
599 5 : EXPECT_RESULT, Number::New(isolate, 33));
600 10 : context.Check("i1() + o.i();",
601 5 : EXPECT_RESULT, Number::New(isolate, 20));
602 :
603 10 : context.Check("'use strict';"
604 : "let x2 = 2;"
605 : "function f2() { let y = 20; return x2 + y }"
606 : "function g2() { let y = 20; return eval('x2 + y') }"
607 : "function h2() { let y = 20; return (1,eval)('x2') + y }"
608 : "function i2() { let y = 20; return x1 + y }"
609 : "function j2() { let y = 20; return eval('x1 + y') }"
610 : "function k2() { let y = 20; return (1,eval)('x1') + y }"
611 : "x2 + eval('x2') + (1,eval)('x2') + f2() + g2() + h2();",
612 5 : EXPECT_RESULT, Number::New(isolate, 72));
613 10 : context.Check("x1 + eval('x1') + (1,eval)('x1') + f1() + g1() + h1();",
614 5 : EXPECT_RESULT, Number::New(isolate, 36));
615 10 : context.Check("i1() + j1() + k1();",
616 5 : EXPECT_RESULT, Number::New(isolate, 36));
617 10 : context.Check("i2() + j2() + k2();",
618 5 : EXPECT_RESULT, Number::New(isolate, 63));
619 10 : context.Check("o.f() + o.g() + o.h();",
620 5 : EXPECT_RESULT, Number::New(isolate, 33));
621 10 : context.Check("o.i() + o.j() + o.k();",
622 5 : EXPECT_RESULT, Number::New(isolate, 36));
623 10 : context.Check("i1() + o.i();",
624 5 : EXPECT_RESULT, Number::New(isolate, 24));
625 :
626 10 : context.Check("'use strict';"
627 : "let x0 = 100;"
628 : "x0 + eval('x0') + (1,eval)('x0') + "
629 : " d0() + f0() + g0() + h0();",
630 5 : EXPECT_RESULT, Number::New(isolate, 730));
631 10 : context.Check("x0 + eval('x0') + (1,eval)('x0') + "
632 : " d0() + f0() + g0() + h0();",
633 5 : EXPECT_RESULT, Number::New(isolate, 730));
634 10 : context.Check("delete this.x0;"
635 : "x0 + eval('x0') + (1,eval)('x0') + "
636 : " d0() + f0() + g0() + h0();",
637 5 : EXPECT_RESULT, Number::New(isolate, 730));
638 10 : context.Check("this.x1 = 666;"
639 : "x1 + eval('x1') + (1,eval)('x1') + f1() + g1() + h1();",
640 5 : EXPECT_RESULT, Number::New(isolate, 36));
641 10 : context.Check("delete this.x1;"
642 : "x1 + eval('x1') + (1,eval)('x1') + f1() + g1() + h1();",
643 5 : EXPECT_RESULT, Number::New(isolate, 36));
644 : }
645 :
646 : // Check that caching does respect scopes.
647 : {
648 5 : SimpleContext context;
649 : const char* script1 = "(function(){ return y1 })()";
650 : const char* script2 = "(function(){ return y2 })()";
651 :
652 5 : context.Check(script1, EXPECT_EXCEPTION);
653 10 : context.Check("this.y1 = 1; this.y2 = 2; 0;",
654 5 : EXPECT_RESULT, Number::New(isolate, 0));
655 10 : context.Check(script1,
656 5 : EXPECT_RESULT, Number::New(isolate, 1));
657 10 : context.Check("'use strict'; let y1 = 3; 0;",
658 5 : EXPECT_RESULT, Number::New(isolate, 0));
659 10 : context.Check(script1,
660 5 : EXPECT_RESULT, Number::New(isolate, 3));
661 10 : context.Check("y1 = 4;",
662 5 : EXPECT_RESULT, Number::New(isolate, 4));
663 10 : context.Check(script1,
664 5 : EXPECT_RESULT, Number::New(isolate, 4));
665 :
666 10 : context.Check(script2,
667 5 : EXPECT_RESULT, Number::New(isolate, 2));
668 10 : context.Check("'use strict'; let y2 = 5; 0;",
669 5 : EXPECT_RESULT, Number::New(isolate, 0));
670 10 : context.Check(script1,
671 5 : EXPECT_RESULT, Number::New(isolate, 4));
672 10 : context.Check(script2,
673 5 : EXPECT_RESULT, Number::New(isolate, 5));
674 : }
675 5 : }
676 :
677 :
678 26644 : TEST(CrossScriptReferencesHarmonyRegress) {
679 5 : v8::Isolate* isolate = CcTest::isolate();
680 10 : HandleScope scope(isolate);
681 5 : SimpleContext context;
682 10 : context.Check(
683 : "'use strict';"
684 : "function i1() { "
685 : " let y = 10; return (typeof x2 === 'undefined' ? 0 : 2) + y"
686 : "}"
687 : "i1();"
688 : "i1();",
689 5 : EXPECT_RESULT, Number::New(isolate, 10));
690 10 : context.Check(
691 : "'use strict';"
692 : "let x2 = 2; i1();",
693 5 : EXPECT_RESULT, Number::New(isolate, 12));
694 5 : }
695 :
696 :
697 26644 : TEST(GlobalLexicalOSR) {
698 5 : i::FLAG_use_strict = true;
699 :
700 5 : v8::Isolate* isolate = CcTest::isolate();
701 10 : HandleScope scope(isolate);
702 5 : SimpleContext context;
703 :
704 10 : context.Check("'use strict';"
705 : "let x = 1; x;",
706 5 : EXPECT_RESULT, Number::New(isolate, 1));
707 10 : context.Check("'use strict';"
708 : "let y = 2*x;"
709 : "++x;"
710 : "let z = 0;"
711 : "const limit = 100000;"
712 : "for (var i = 0; i < limit; ++i) {"
713 : " z += x + y;"
714 : "}"
715 : "z;",
716 5 : EXPECT_RESULT, Number::New(isolate, 400000));
717 5 : }
718 :
719 :
720 26644 : TEST(CrossScriptConflicts) {
721 5 : i::FLAG_use_strict = true;
722 :
723 10 : HandleScope scope(CcTest::isolate());
724 :
725 : const char* firsts[] = {"var x = 1; x", "function x() { return 1 }; x()",
726 5 : "let x = 1; x", "const x = 1; x", nullptr};
727 : const char* seconds[] = {"var x = 2; x", "function x() { return 2 }; x()",
728 5 : "let x = 2; x", "const x = 2; x", nullptr};
729 :
730 45 : for (int i = 0; firsts[i] != nullptr; ++i) {
731 180 : for (int j = 0; seconds[j] != nullptr; ++j) {
732 80 : SimpleContext context;
733 160 : context.Check(firsts[i], EXPECT_RESULT,
734 80 : Number::New(CcTest::isolate(), 1));
735 80 : bool success_case = i < 2 && j < 2;
736 : Local<Value> success_result;
737 80 : if (success_case) success_result = Number::New(CcTest::isolate(), 2);
738 :
739 80 : context.Check(seconds[j], success_case ? EXPECT_RESULT : EXPECT_EXCEPTION,
740 80 : success_result);
741 : }
742 : }
743 5 : }
744 :
745 :
746 26644 : TEST(CrossScriptDynamicLookup) {
747 10 : HandleScope handle_scope(CcTest::isolate());
748 :
749 : {
750 5 : SimpleContext context;
751 : Local<String> undefined_string =
752 5 : String::NewFromUtf8(CcTest::isolate(), "undefined",
753 5 : v8::NewStringType::kInternalized)
754 : .ToLocalChecked();
755 : Local<String> number_string =
756 5 : String::NewFromUtf8(CcTest::isolate(), "number",
757 5 : v8::NewStringType::kInternalized)
758 : .ToLocalChecked();
759 :
760 10 : context.Check(
761 : "function f(o) { with(o) { return x; } }"
762 : "function g(o) { with(o) { x = 15; } }"
763 : "function h(o) { with(o) { return typeof x; } }",
764 5 : EXPECT_RESULT, Undefined(CcTest::isolate()));
765 5 : context.Check("h({})", EXPECT_RESULT, undefined_string);
766 10 : context.Check(
767 : "'use strict';"
768 : "let x = 1;"
769 : "f({})",
770 5 : EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
771 10 : context.Check(
772 : "'use strict';"
773 : "g({});0",
774 5 : EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
775 10 : context.Check("f({})", EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
776 5 : context.Check("h({})", EXPECT_RESULT, number_string);
777 : }
778 5 : }
779 :
780 :
781 26644 : TEST(CrossScriptGlobal) {
782 10 : HandleScope handle_scope(CcTest::isolate());
783 : {
784 5 : SimpleContext context;
785 :
786 10 : context.Check(
787 : "var global = this;"
788 : "global.x = 255;"
789 : "x",
790 5 : EXPECT_RESULT, Number::New(CcTest::isolate(), 255));
791 10 : context.Check(
792 : "'use strict';"
793 : "let x = 1;"
794 : "global.x",
795 5 : EXPECT_RESULT, Number::New(CcTest::isolate(), 255));
796 10 : context.Check("global.x = 15; x", EXPECT_RESULT,
797 5 : Number::New(CcTest::isolate(), 1));
798 10 : context.Check("x = 221; global.x", EXPECT_RESULT,
799 5 : Number::New(CcTest::isolate(), 15));
800 10 : context.Check(
801 : "z = 15;"
802 : "function f() { return z; };"
803 : "for (var k = 0; k < 3; k++) { f(); }"
804 : "f()",
805 5 : EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
806 10 : context.Check(
807 : "'use strict';"
808 : "let z = 5; f()",
809 5 : EXPECT_RESULT, Number::New(CcTest::isolate(), 5));
810 10 : context.Check(
811 : "function f() { konst = 10; return konst; };"
812 : "f()",
813 5 : EXPECT_RESULT, Number::New(CcTest::isolate(), 10));
814 5 : context.Check(
815 : "'use strict';"
816 : "const konst = 255;"
817 : "f()",
818 5 : EXPECT_EXCEPTION);
819 : }
820 5 : }
821 :
822 :
823 26644 : TEST(CrossScriptStaticLookupUndeclared) {
824 10 : HandleScope handle_scope(CcTest::isolate());
825 :
826 : {
827 5 : SimpleContext context;
828 : Local<String> undefined_string =
829 5 : String::NewFromUtf8(CcTest::isolate(), "undefined",
830 5 : v8::NewStringType::kInternalized)
831 : .ToLocalChecked();
832 : Local<String> number_string =
833 5 : String::NewFromUtf8(CcTest::isolate(), "number",
834 5 : v8::NewStringType::kInternalized)
835 : .ToLocalChecked();
836 :
837 10 : context.Check(
838 : "function f(o) { return x; }"
839 : "function g(v) { x = v; }"
840 : "function h(o) { return typeof x; }",
841 5 : EXPECT_RESULT, Undefined(CcTest::isolate()));
842 5 : context.Check("h({})", EXPECT_RESULT, undefined_string);
843 10 : context.Check(
844 : "'use strict';"
845 : "let x = 1;"
846 : "f({})",
847 5 : EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
848 10 : context.Check(
849 : "'use strict';"
850 : "g(15);x",
851 5 : EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
852 5 : context.Check("h({})", EXPECT_RESULT, number_string);
853 10 : context.Check("f({})", EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
854 5 : context.Check("h({})", EXPECT_RESULT, number_string);
855 : }
856 5 : }
857 :
858 :
859 26644 : TEST(CrossScriptLoadICs) {
860 5 : i::FLAG_allow_natives_syntax = true;
861 :
862 10 : HandleScope handle_scope(CcTest::isolate());
863 :
864 : {
865 5 : SimpleContext context;
866 10 : context.Check(
867 : "x = 15;"
868 : "function f() { return x; }"
869 : "function g() { return x; }"
870 : "f()",
871 5 : EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
872 10 : context.Check(
873 : "'use strict';"
874 : "let x = 5;"
875 : "f()",
876 5 : EXPECT_RESULT, Number::New(CcTest::isolate(), 5));
877 35 : for (int k = 0; k < 3; k++) {
878 30 : context.Check("g()", EXPECT_RESULT, Number::New(CcTest::isolate(), 5));
879 : }
880 35 : for (int k = 0; k < 3; k++) {
881 30 : context.Check("f()", EXPECT_RESULT, Number::New(CcTest::isolate(), 5));
882 : }
883 10 : context.Check("%OptimizeFunctionOnNextCall(g); g()", EXPECT_RESULT,
884 5 : Number::New(CcTest::isolate(), 5));
885 10 : context.Check("%OptimizeFunctionOnNextCall(f); f()", EXPECT_RESULT,
886 5 : Number::New(CcTest::isolate(), 5));
887 : }
888 : {
889 5 : SimpleContext context;
890 10 : context.Check(
891 : "x = 15;"
892 : "function f() { return x; }"
893 : "f()",
894 5 : EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
895 35 : for (int k = 0; k < 3; k++) {
896 30 : context.Check("f()", EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
897 : }
898 10 : context.Check("%OptimizeFunctionOnNextCall(f); f()", EXPECT_RESULT,
899 5 : Number::New(CcTest::isolate(), 15));
900 10 : context.Check(
901 : "'use strict';"
902 : "let x = 5;"
903 : "f()",
904 5 : EXPECT_RESULT, Number::New(CcTest::isolate(), 5));
905 35 : for (int k = 0; k < 3; k++) {
906 30 : context.Check("f()", EXPECT_RESULT, Number::New(CcTest::isolate(), 5));
907 : }
908 10 : context.Check("%OptimizeFunctionOnNextCall(f); f()", EXPECT_RESULT,
909 5 : Number::New(CcTest::isolate(), 5));
910 : }
911 5 : }
912 :
913 :
914 26644 : TEST(CrossScriptStoreICs) {
915 5 : i::FLAG_allow_natives_syntax = true;
916 :
917 10 : HandleScope handle_scope(CcTest::isolate());
918 :
919 : {
920 5 : SimpleContext context;
921 10 : context.Check(
922 : "var global = this;"
923 : "x = 15;"
924 : "function f(v) { x = v; }"
925 : "function g(v) { x = v; }"
926 : "f(10); x",
927 5 : EXPECT_RESULT, Number::New(CcTest::isolate(), 10));
928 10 : context.Check(
929 : "'use strict';"
930 : "let x = 5;"
931 : "f(7); x",
932 5 : EXPECT_RESULT, Number::New(CcTest::isolate(), 7));
933 10 : context.Check("global.x", EXPECT_RESULT,
934 5 : Number::New(CcTest::isolate(), 10));
935 35 : for (int k = 0; k < 3; k++) {
936 30 : context.Check("g(31); x", EXPECT_RESULT,
937 15 : Number::New(CcTest::isolate(), 31));
938 : }
939 10 : context.Check("global.x", EXPECT_RESULT,
940 5 : Number::New(CcTest::isolate(), 10));
941 35 : for (int k = 0; k < 3; k++) {
942 30 : context.Check("f(32); x", EXPECT_RESULT,
943 15 : Number::New(CcTest::isolate(), 32));
944 : }
945 10 : context.Check("global.x", EXPECT_RESULT,
946 5 : Number::New(CcTest::isolate(), 10));
947 10 : context.Check("%OptimizeFunctionOnNextCall(g); g(18); x", EXPECT_RESULT,
948 5 : Number::New(CcTest::isolate(), 18));
949 10 : context.Check("global.x", EXPECT_RESULT,
950 5 : Number::New(CcTest::isolate(), 10));
951 10 : context.Check("%OptimizeFunctionOnNextCall(f); f(33); x", EXPECT_RESULT,
952 5 : Number::New(CcTest::isolate(), 33));
953 10 : context.Check("global.x", EXPECT_RESULT,
954 5 : Number::New(CcTest::isolate(), 10));
955 : }
956 : {
957 5 : SimpleContext context;
958 10 : context.Check(
959 : "var global = this;"
960 : "x = 15;"
961 : "function f(v) { x = v; }"
962 : "f(10); x",
963 5 : EXPECT_RESULT, Number::New(CcTest::isolate(), 10));
964 35 : for (int k = 0; k < 3; k++) {
965 30 : context.Check("f(18); x", EXPECT_RESULT,
966 15 : Number::New(CcTest::isolate(), 18));
967 : }
968 10 : context.Check("%OptimizeFunctionOnNextCall(f); f(20); x", EXPECT_RESULT,
969 5 : Number::New(CcTest::isolate(), 20));
970 10 : context.Check(
971 : "'use strict';"
972 : "let x = 5;"
973 : "f(8); x",
974 5 : EXPECT_RESULT, Number::New(CcTest::isolate(), 8));
975 10 : context.Check("global.x", EXPECT_RESULT,
976 5 : Number::New(CcTest::isolate(), 20));
977 35 : for (int k = 0; k < 3; k++) {
978 30 : context.Check("f(13); x", EXPECT_RESULT,
979 15 : Number::New(CcTest::isolate(), 13));
980 : }
981 10 : context.Check("global.x", EXPECT_RESULT,
982 5 : Number::New(CcTest::isolate(), 20));
983 10 : context.Check("%OptimizeFunctionOnNextCall(f); f(41); x", EXPECT_RESULT,
984 5 : Number::New(CcTest::isolate(), 41));
985 10 : context.Check("global.x", EXPECT_RESULT,
986 5 : Number::New(CcTest::isolate(), 20));
987 : }
988 5 : }
989 :
990 :
991 26644 : TEST(CrossScriptAssignmentToConst) {
992 5 : i::FLAG_allow_natives_syntax = true;
993 :
994 10 : HandleScope handle_scope(CcTest::isolate());
995 :
996 : {
997 5 : SimpleContext context;
998 :
999 10 : context.Check("function f() { x = 27; }", EXPECT_RESULT,
1000 5 : Undefined(CcTest::isolate()));
1001 10 : context.Check("'use strict';const x = 1; x", EXPECT_RESULT,
1002 5 : Number::New(CcTest::isolate(), 1));
1003 5 : context.Check("f();", EXPECT_EXCEPTION);
1004 10 : context.Check("x", EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
1005 5 : context.Check("f();", EXPECT_EXCEPTION);
1006 10 : context.Check("x", EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
1007 5 : context.Check("%OptimizeFunctionOnNextCall(f);f();", EXPECT_EXCEPTION);
1008 10 : context.Check("x", EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
1009 : }
1010 5 : }
1011 :
1012 :
1013 26644 : TEST(Regress425510) {
1014 5 : i::FLAG_allow_natives_syntax = true;
1015 :
1016 10 : HandleScope handle_scope(CcTest::isolate());
1017 :
1018 : {
1019 5 : SimpleContext context;
1020 :
1021 5 : context.Check("'use strict'; o; const o = 10", EXPECT_EXCEPTION);
1022 :
1023 1005 : for (int i = 0; i < 100; i++) {
1024 500 : context.Check("o.prototype", EXPECT_EXCEPTION);
1025 : }
1026 : }
1027 5 : }
1028 :
1029 :
1030 26644 : TEST(Regress3941) {
1031 5 : i::FLAG_allow_natives_syntax = true;
1032 :
1033 10 : HandleScope handle_scope(CcTest::isolate());
1034 :
1035 : {
1036 5 : SimpleContext context;
1037 10 : context.Check("function f() { x = 1; }", EXPECT_RESULT,
1038 5 : Undefined(CcTest::isolate()));
1039 5 : context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);
1040 : }
1041 :
1042 :
1043 : {
1044 : // Train ICs.
1045 5 : SimpleContext context;
1046 10 : context.Check("function f() { x = 1; }", EXPECT_RESULT,
1047 5 : Undefined(CcTest::isolate()));
1048 45 : for (int i = 0; i < 4; i++) {
1049 40 : context.Check("f(); x", EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
1050 : }
1051 5 : context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);
1052 : }
1053 :
1054 :
1055 : {
1056 : // Optimize.
1057 5 : SimpleContext context;
1058 10 : context.Check("function f() { x = 1; }", EXPECT_RESULT,
1059 5 : Undefined(CcTest::isolate()));
1060 45 : for (int i = 0; i < 4; i++) {
1061 40 : context.Check("f(); x", EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
1062 : }
1063 10 : context.Check("%OptimizeFunctionOnNextCall(f); f(); x", EXPECT_RESULT,
1064 5 : Number::New(CcTest::isolate(), 1));
1065 :
1066 5 : context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);
1067 : }
1068 5 : }
1069 :
1070 :
1071 26644 : TEST(Regress3941_Reads) {
1072 5 : i::FLAG_allow_natives_syntax = true;
1073 :
1074 10 : HandleScope handle_scope(CcTest::isolate());
1075 :
1076 : {
1077 5 : SimpleContext context;
1078 10 : context.Check("function f() { return x; }", EXPECT_RESULT,
1079 5 : Undefined(CcTest::isolate()));
1080 5 : context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);
1081 : }
1082 :
1083 :
1084 : {
1085 : // Train ICs.
1086 5 : SimpleContext context;
1087 10 : context.Check("function f() { return x; }", EXPECT_RESULT,
1088 5 : Undefined(CcTest::isolate()));
1089 45 : for (int i = 0; i < 4; i++) {
1090 20 : context.Check("f()", EXPECT_EXCEPTION);
1091 : }
1092 5 : context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);
1093 : }
1094 :
1095 :
1096 : {
1097 : // Optimize.
1098 5 : SimpleContext context;
1099 10 : context.Check("function f() { return x; }", EXPECT_RESULT,
1100 5 : Undefined(CcTest::isolate()));
1101 45 : for (int i = 0; i < 4; i++) {
1102 20 : context.Check("f()", EXPECT_EXCEPTION);
1103 : }
1104 10 : context.Check("%OptimizeFunctionOnNextCall(f);", EXPECT_RESULT,
1105 5 : Undefined(CcTest::isolate()));
1106 :
1107 5 : context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);
1108 : }
1109 5 : }
1110 :
1111 79917 : } // namespace v8
|