blob: 4e9595258a1b33cd3556b9ed1ac4364a8306a0d1 [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// 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
Ben Murdochb8a8cc12014-11-26 15:28:44 +000030#include "src/v8.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000031
Ben Murdochb8a8cc12014-11-26 15:28:44 +000032#include "src/heap/heap.h"
33#include "test/cctest/cctest.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000034
35using namespace v8;
36
37
38enum Expectations {
39 EXPECT_RESULT,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000040 EXPECT_EXCEPTION,
41 EXPECT_ERROR
Steve Blocka7e24c12009-10-30 11:49:00 +000042};
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.
49class DeclarationContext {
50 public:
51 DeclarationContext();
52
53 virtual ~DeclarationContext() {
54 if (is_initialized_) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000055 Isolate* isolate = CcTest::isolate();
56 HandleScope scope(isolate);
57 Local<Context> context = Local<Context>::New(isolate, context_);
58 context->Exit();
59 context_.Reset();
Steve Blocka7e24c12009-10-30 11:49:00 +000060 }
61 }
62
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000063 void Check(const char* source, int get, int set, int has,
Steve Blocka7e24c12009-10-30 11:49:00 +000064 Expectations expectations,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000065 v8::Local<Value> value = Local<Value>());
Steve Blocka7e24c12009-10-30 11:49:00 +000066
67 int get_count() const { return get_count_; }
68 int set_count() const { return set_count_; }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010069 int query_count() const { return query_count_; }
Steve Blocka7e24c12009-10-30 11:49:00 +000070
71 protected:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000072 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);
Steve Blocka7e24c12009-10-30 11:49:00 +000075
76 void InitializeIfNeeded();
77
Ben Murdochb8a8cc12014-11-26 15:28:44 +000078 // Perform optional initialization steps on the context after it has
79 // been created. Defaults to none but may be overwritten.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000080 virtual void PostInitializeContext(Local<Context> context) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000081
Steve Blocka7e24c12009-10-30 11:49:00 +000082 // Get the holder for the interceptor. Default to the instance template
83 // but may be overwritten.
84 virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
85 return function->InstanceTemplate();
86 }
87
88 // The handlers are called as static functions that forward
89 // to the instance specific virtual methods.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040090 static void HandleGet(Local<Name> key,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000091 const v8::PropertyCallbackInfo<v8::Value>& info);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040092 static void HandleSet(Local<Name> key, Local<Value> value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000093 const v8::PropertyCallbackInfo<v8::Value>& info);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040094 static void HandleQuery(Local<Name> key,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000095 const v8::PropertyCallbackInfo<v8::Integer>& info);
96
97 v8::Isolate* isolate() const { return CcTest::isolate(); }
Steve Blocka7e24c12009-10-30 11:49:00 +000098
99 private:
100 bool is_initialized_;
101 Persistent<Context> context_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000102
103 int get_count_;
104 int set_count_;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100105 int query_count_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000106
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000107 static DeclarationContext* GetInstance(Local<Value> data);
Steve Blocka7e24c12009-10-30 11:49:00 +0000108};
109
110
111DeclarationContext::DeclarationContext()
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100112 : is_initialized_(false), get_count_(0), set_count_(0), query_count_(0) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000113 // Do nothing.
114}
115
116
117void DeclarationContext::InitializeIfNeeded() {
118 if (is_initialized_) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000119 Isolate* isolate = CcTest::isolate();
120 HandleScope scope(isolate);
121 Local<FunctionTemplate> function = FunctionTemplate::New(isolate);
122 Local<Value> data = External::New(CcTest::isolate(), this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400123 GetHolder(function)->SetHandler(v8::NamedPropertyHandlerConfiguration(
124 &HandleGet, &HandleSet, &HandleQuery, 0, 0, data));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000125 Local<Context> context = Context::New(isolate,
126 0,
127 function->InstanceTemplate(),
128 Local<Value>());
129 context_.Reset(isolate, context);
130 context->Enter();
Steve Blocka7e24c12009-10-30 11:49:00 +0000131 is_initialized_ = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000132 // Reset counts. Bootstrapping might have called into the interceptor.
133 get_count_ = 0;
134 set_count_ = 0;
135 query_count_ = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000136 PostInitializeContext(context);
Steve Blocka7e24c12009-10-30 11:49:00 +0000137}
138
139
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000140void DeclarationContext::Check(const char* source, int get, int set, int query,
Steve Blocka7e24c12009-10-30 11:49:00 +0000141 Expectations expectations,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000142 v8::Local<Value> value) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000143 InitializeIfNeeded();
144 // A retry after a GC may pollute the counts, so perform gc now
145 // to avoid that.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000146 CcTest::heap()->CollectGarbage(v8::internal::NEW_SPACE);
147 HandleScope scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000148 TryCatch catcher(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000149 catcher.SetVerbose(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000150 Local<Context> context = CcTest::isolate()->GetCurrentContext();
151 MaybeLocal<Script> script = Script::Compile(
152 context,
153 String::NewFromUtf8(CcTest::isolate(), source, v8::NewStringType::kNormal)
154 .ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000155 if (expectations == EXPECT_ERROR) {
156 CHECK(script.IsEmpty());
157 return;
158 }
159 CHECK(!script.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000160 MaybeLocal<Value> result = script.ToLocalChecked()->Run(context);
Steve Blocka7e24c12009-10-30 11:49:00 +0000161 CHECK_EQ(get, get_count());
162 CHECK_EQ(set, set_count());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100163 CHECK_EQ(query, query_count());
Steve Blocka7e24c12009-10-30 11:49:00 +0000164 if (expectations == EXPECT_RESULT) {
165 CHECK(!catcher.HasCaught());
166 if (!value.IsEmpty()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000167 CHECK(value->Equals(context, result.ToLocalChecked()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +0000168 }
169 } else {
170 CHECK(expectations == EXPECT_EXCEPTION);
171 CHECK(catcher.HasCaught());
172 if (!value.IsEmpty()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000173 CHECK(value->Equals(context, catcher.Exception()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +0000174 }
175 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000176 // Clean slate for the next test.
177 CcTest::heap()->CollectAllAvailableGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +0000178}
179
180
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000181void DeclarationContext::HandleGet(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400182 Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000183 DeclarationContext* context = GetInstance(info.Data());
Steve Blocka7e24c12009-10-30 11:49:00 +0000184 context->get_count_++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000185 info.GetReturnValue().Set(context->Get(key));
Steve Blocka7e24c12009-10-30 11:49:00 +0000186}
187
188
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000189void DeclarationContext::HandleSet(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400190 Local<Name> key, Local<Value> value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000191 const v8::PropertyCallbackInfo<v8::Value>& info) {
192 DeclarationContext* context = GetInstance(info.Data());
Steve Blocka7e24c12009-10-30 11:49:00 +0000193 context->set_count_++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000194 info.GetReturnValue().Set(context->Set(key, value));
Steve Blocka7e24c12009-10-30 11:49:00 +0000195}
196
197
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000198void DeclarationContext::HandleQuery(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400199 Local<Name> key, const v8::PropertyCallbackInfo<v8::Integer>& info) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000200 DeclarationContext* context = GetInstance(info.Data());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100201 context->query_count_++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000202 info.GetReturnValue().Set(context->Query(key));
Steve Blocka7e24c12009-10-30 11:49:00 +0000203}
204
205
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000206DeclarationContext* DeclarationContext::GetInstance(Local<Value> data) {
207 void* value = Local<External>::Cast(data)->Value();
208 return static_cast<DeclarationContext*>(value);
Steve Blocka7e24c12009-10-30 11:49:00 +0000209}
210
211
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000212v8::Local<Value> DeclarationContext::Get(Local<Name> key) {
213 return v8::Local<Value>();
Steve Blocka7e24c12009-10-30 11:49:00 +0000214}
215
216
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000217v8::Local<Value> DeclarationContext::Set(Local<Name> key, Local<Value> value) {
218 return v8::Local<Value>();
Steve Blocka7e24c12009-10-30 11:49:00 +0000219}
220
221
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000222v8::Local<Integer> DeclarationContext::Query(Local<Name> key) {
223 return v8::Local<Integer>();
Steve Blocka7e24c12009-10-30 11:49:00 +0000224}
225
226
227// Test global declaration of a property the interceptor doesn't know
228// about and doesn't handle.
229TEST(Unknown) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000230 i::FLAG_legacy_const = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000231 HandleScope scope(CcTest::isolate());
232 v8::V8::Initialize();
Steve Blocka7e24c12009-10-30 11:49:00 +0000233
234 { DeclarationContext context;
235 context.Check("var x; x",
236 1, // access
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000237 0, 0, EXPECT_RESULT, Undefined(CcTest::isolate()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000238 }
239
240 { DeclarationContext context;
241 context.Check("var x = 0; x",
242 1, // access
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000243 1, // initialization
244 0, EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
Steve Blocka7e24c12009-10-30 11:49:00 +0000245 }
246
247 { DeclarationContext context;
248 context.Check("function x() { }; x",
249 1, // access
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100250 0,
Steve Blocka7e24c12009-10-30 11:49:00 +0000251 0,
252 EXPECT_RESULT);
253 }
254
255 { DeclarationContext context;
256 context.Check("const x; x",
257 1, // access
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000258 0, 0, EXPECT_RESULT, Undefined(CcTest::isolate()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000259 }
260
261 { DeclarationContext context;
262 context.Check("const x = 0; x",
263 1, // access
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000264 0,
265 0,
266 EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
Steve Blocka7e24c12009-10-30 11:49:00 +0000267 }
268}
269
270
Steve Blocka7e24c12009-10-30 11:49:00 +0000271class AbsentPropertyContext: public DeclarationContext {
272 protected:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000273 virtual v8::Local<Integer> Query(Local<Name> key) {
274 return v8::Local<Integer>();
Steve Blocka7e24c12009-10-30 11:49:00 +0000275 }
276};
277
278
279TEST(Absent) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000280 i::FLAG_legacy_const = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000281 v8::Isolate* isolate = CcTest::isolate();
282 v8::V8::Initialize();
283 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000284
285 { AbsentPropertyContext context;
286 context.Check("var x; x",
287 1, // access
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000288 0, 0, EXPECT_RESULT, Undefined(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +0000289 }
290
291 { AbsentPropertyContext context;
292 context.Check("var x = 0; x",
293 1, // access
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000294 1, // initialization
295 0, EXPECT_RESULT, Number::New(isolate, 0));
Steve Blocka7e24c12009-10-30 11:49:00 +0000296 }
297
298 { AbsentPropertyContext context;
299 context.Check("function x() { }; x",
300 1, // access
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100301 0,
Steve Blocka7e24c12009-10-30 11:49:00 +0000302 0,
303 EXPECT_RESULT);
304 }
305
306 { AbsentPropertyContext context;
307 context.Check("const x; x",
308 1, // access
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000309 0, 0, EXPECT_RESULT, Undefined(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +0000310 }
311
312 { AbsentPropertyContext context;
313 context.Check("const x = 0; x",
314 1, // access
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000315 0, 0, EXPECT_RESULT, Number::New(isolate, 0));
Steve Blocka7e24c12009-10-30 11:49:00 +0000316 }
317
318 { AbsentPropertyContext context;
319 context.Check("if (false) { var x = 0 }; x",
320 1, // access
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000321 0, 0, EXPECT_RESULT, Undefined(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +0000322 }
323}
324
325
326
327class AppearingPropertyContext: public DeclarationContext {
328 public:
329 enum State {
330 DECLARE,
331 INITIALIZE_IF_ASSIGN,
332 UNKNOWN
333 };
334
335 AppearingPropertyContext() : state_(DECLARE) { }
336
337 protected:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000338 virtual v8::Local<Integer> Query(Local<Name> key) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000339 switch (state_) {
340 case DECLARE:
341 // Force declaration by returning that the
342 // property is absent.
343 state_ = INITIALIZE_IF_ASSIGN;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000344 return Local<Integer>();
Steve Blocka7e24c12009-10-30 11:49:00 +0000345 case INITIALIZE_IF_ASSIGN:
346 // Return that the property is present so we only get the
347 // setter called when initializing with a value.
348 state_ = UNKNOWN;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000349 return Integer::New(isolate(), v8::None);
Steve Blocka7e24c12009-10-30 11:49:00 +0000350 default:
351 CHECK(state_ == UNKNOWN);
352 break;
353 }
354 // Do the lookup in the object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000355 return v8::Local<Integer>();
Steve Blocka7e24c12009-10-30 11:49:00 +0000356 }
357
358 private:
359 State state_;
360};
361
362
363TEST(Appearing) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000364 i::FLAG_legacy_const = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000365 v8::V8::Initialize();
366 HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000367
368 { AppearingPropertyContext context;
369 context.Check("var x; x",
370 1, // access
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000371 0, 0, EXPECT_RESULT, Undefined(CcTest::isolate()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000372 }
373
374 { AppearingPropertyContext context;
375 context.Check("var x = 0; x",
376 1, // access
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000377 1, // initialization
378 0, EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
Steve Blocka7e24c12009-10-30 11:49:00 +0000379 }
380
381 { AppearingPropertyContext context;
382 context.Check("function x() { }; x",
383 1, // access
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100384 0,
Steve Blocka7e24c12009-10-30 11:49:00 +0000385 0,
386 EXPECT_RESULT);
387 }
388
389 { AppearingPropertyContext context;
390 context.Check("const x; x",
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100391 1, // access
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000392 0, 0, EXPECT_RESULT, Undefined(CcTest::isolate()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000393 }
394
395 { AppearingPropertyContext context;
396 context.Check("const x = 0; x",
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100397 1, // access
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000398 0, 0, EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
Steve Blocka7e24c12009-10-30 11:49:00 +0000399 }
400}
401
402
403
404class ExistsInPrototypeContext: public DeclarationContext {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000405 public:
406 ExistsInPrototypeContext() { InitializeIfNeeded(); }
Steve Blocka7e24c12009-10-30 11:49:00 +0000407 protected:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000408 virtual v8::Local<Integer> Query(Local<Name> key) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000409 // Let it seem that the property exists in the prototype object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000410 return Integer::New(isolate(), v8::None);
Steve Blocka7e24c12009-10-30 11:49:00 +0000411 }
412
413 // Use the prototype as the holder for the interceptors.
414 virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
415 return function->PrototypeTemplate();
416 }
417};
418
419
420TEST(ExistsInPrototype) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000421 i::FLAG_legacy_const = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000422 HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000423
424 // Sanity check to make sure that the holder of the interceptor
425 // really is the prototype object.
426 { ExistsInPrototypeContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000427 context.Check("this.x = 87; this.x", 0, 0, 1, EXPECT_RESULT,
428 Number::New(CcTest::isolate(), 87));
Steve Blocka7e24c12009-10-30 11:49:00 +0000429 }
430
431 { ExistsInPrototypeContext context;
432 context.Check("var x; x",
Steve Blocka7e24c12009-10-30 11:49:00 +0000433 0,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000434 0,
435 0,
436 EXPECT_RESULT, Undefined(CcTest::isolate()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000437 }
438
439 { ExistsInPrototypeContext context;
440 context.Check("var x = 0; x",
441 0,
442 0,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000443 0,
444 EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
Steve Blocka7e24c12009-10-30 11:49:00 +0000445 }
446
447 { ExistsInPrototypeContext context;
448 context.Check("const x; x",
449 0,
450 0,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000451 0,
452 EXPECT_RESULT, Undefined(CcTest::isolate()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000453 }
454
455 { ExistsInPrototypeContext context;
456 context.Check("const x = 0; x",
457 0,
458 0,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000459 0,
460 EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
Steve Blocka7e24c12009-10-30 11:49:00 +0000461 }
462}
463
464
465
466class AbsentInPrototypeContext: public DeclarationContext {
467 protected:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000468 virtual v8::Local<Integer> Query(Local<Name> key) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000469 // Let it seem that the property is absent in the prototype object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000470 return Local<Integer>();
Steve Blocka7e24c12009-10-30 11:49:00 +0000471 }
472
473 // Use the prototype as the holder for the interceptors.
474 virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
475 return function->PrototypeTemplate();
476 }
477};
478
479
480TEST(AbsentInPrototype) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000481 v8::V8::Initialize();
482 HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000483
484 { AbsentInPrototypeContext context;
485 context.Check("if (false) { var x = 0; }; x",
486 0,
487 0,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000488 0,
489 EXPECT_RESULT, Undefined(CcTest::isolate()));
490 }
491}
492
493
494
495class ExistsInHiddenPrototypeContext: public DeclarationContext {
496 public:
497 ExistsInHiddenPrototypeContext() {
498 hidden_proto_ = FunctionTemplate::New(CcTest::isolate());
499 hidden_proto_->SetHiddenPrototype(true);
500 }
501
502 protected:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000503 virtual v8::Local<Integer> Query(Local<Name> key) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000504 // Let it seem that the property exists in the hidden prototype object.
505 return Integer::New(isolate(), v8::None);
506 }
507
508 // Install the hidden prototype after the global object has been created.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000509 virtual void PostInitializeContext(Local<Context> context) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000510 Local<Object> global_object = context->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000511 Local<Object> hidden_proto = hidden_proto_->GetFunction(context)
512 .ToLocalChecked()
513 ->NewInstance(context)
514 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000515 Local<Object> inner_global =
516 Local<Object>::Cast(global_object->GetPrototype());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000517 inner_global->SetPrototype(context, hidden_proto).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000518 }
519
520 // Use the hidden prototype as the holder for the interceptors.
521 virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
522 return hidden_proto_->InstanceTemplate();
523 }
524
525 private:
526 Local<FunctionTemplate> hidden_proto_;
527};
528
529
530TEST(ExistsInHiddenPrototype) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000531 i::FLAG_legacy_const = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000532 HandleScope scope(CcTest::isolate());
533
534 { ExistsInHiddenPrototypeContext context;
535 context.Check("var x; x", 0, 0, 0, EXPECT_RESULT,
536 Undefined(CcTest::isolate()));
537 }
538
539 { ExistsInHiddenPrototypeContext context;
540 context.Check("var x = 0; x", 0, 0, 0, EXPECT_RESULT,
541 Number::New(CcTest::isolate(), 0));
542 }
543
544 { ExistsInHiddenPrototypeContext context;
545 context.Check("function x() { }; x",
546 0,
547 0,
548 0,
549 EXPECT_RESULT);
550 }
551
552 // TODO(mstarzinger): The semantics of global const is vague.
553 { ExistsInHiddenPrototypeContext context;
554 context.Check("const x; x", 0, 0, 0, EXPECT_RESULT,
555 Undefined(CcTest::isolate()));
556 }
557
558 // TODO(mstarzinger): The semantics of global const is vague.
559 { ExistsInHiddenPrototypeContext context;
560 context.Check("const x = 0; x", 0, 0, 0, EXPECT_RESULT,
561 Number::New(CcTest::isolate(), 0));
562 }
563}
564
565
566
567class SimpleContext {
568 public:
569 SimpleContext()
570 : handle_scope_(CcTest::isolate()),
571 context_(Context::New(CcTest::isolate())) {
572 context_->Enter();
573 }
574
575 ~SimpleContext() {
576 context_->Exit();
577 }
578
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000579 void Check(const char* source, Expectations expectations,
580 v8::Local<Value> value = Local<Value>()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000581 HandleScope scope(context_->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000582 TryCatch catcher(context_->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000583 catcher.SetVerbose(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000584 MaybeLocal<Script> script = Script::Compile(
585 context_, String::NewFromUtf8(context_->GetIsolate(), source,
586 v8::NewStringType::kNormal)
587 .ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000588 if (expectations == EXPECT_ERROR) {
589 CHECK(script.IsEmpty());
590 return;
591 }
592 CHECK(!script.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000593 MaybeLocal<Value> result = script.ToLocalChecked()->Run(context_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000594 if (expectations == EXPECT_RESULT) {
595 CHECK(!catcher.HasCaught());
596 if (!value.IsEmpty()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000597 CHECK(value->Equals(context_, result.ToLocalChecked()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000598 }
599 } else {
600 CHECK(expectations == EXPECT_EXCEPTION);
601 CHECK(catcher.HasCaught());
602 if (!value.IsEmpty()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000603 CHECK(value->Equals(context_, catcher.Exception()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000604 }
605 }
606 }
607
608 private:
609 HandleScope handle_scope_;
610 Local<Context> context_;
611};
612
613
614TEST(CrossScriptReferences) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000615 i::FLAG_legacy_const = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000616 v8::Isolate* isolate = CcTest::isolate();
617 HandleScope scope(isolate);
618
619 { SimpleContext context;
620 context.Check("var x = 1; x",
621 EXPECT_RESULT, Number::New(isolate, 1));
622 context.Check("var x = 2; x",
623 EXPECT_RESULT, Number::New(isolate, 2));
624 context.Check("const x = 3; x", EXPECT_EXCEPTION);
625 context.Check("const x = 4; x", EXPECT_EXCEPTION);
626 context.Check("x = 5; x",
627 EXPECT_RESULT, Number::New(isolate, 5));
628 context.Check("var x = 6; x",
629 EXPECT_RESULT, Number::New(isolate, 6));
630 context.Check("this.x",
631 EXPECT_RESULT, Number::New(isolate, 6));
632 context.Check("function x() { return 7 }; x()",
633 EXPECT_RESULT, Number::New(isolate, 7));
634 }
635
636 { SimpleContext context;
637 context.Check("const x = 1; x",
638 EXPECT_RESULT, Number::New(isolate, 1));
639 context.Check("var x = 2; x", // assignment ignored
640 EXPECT_RESULT, Number::New(isolate, 1));
641 context.Check("const x = 3; x", EXPECT_EXCEPTION);
642 context.Check("x = 4; x", // assignment ignored
643 EXPECT_RESULT, Number::New(isolate, 1));
644 context.Check("var x = 5; x", // assignment ignored
645 EXPECT_RESULT, Number::New(isolate, 1));
646 context.Check("this.x",
647 EXPECT_RESULT, Number::New(isolate, 1));
648 context.Check("function x() { return 7 }; x",
649 EXPECT_EXCEPTION);
650 }
651}
652
653
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400654TEST(CrossScriptReferences_Simple) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000655 i::FLAG_use_strict = true;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400656
657 v8::Isolate* isolate = CcTest::isolate();
658 HandleScope scope(isolate);
659
660 {
661 SimpleContext context;
662 context.Check("let x = 1; x", EXPECT_RESULT, Number::New(isolate, 1));
663 context.Check("let x = 5; x", EXPECT_EXCEPTION);
664 }
665}
666
667
668TEST(CrossScriptReferences_Simple2) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400669 i::FLAG_use_strict = true;
670
671 v8::Isolate* isolate = CcTest::isolate();
672 HandleScope scope(isolate);
673
674 for (int k = 0; k < 100; k++) {
675 SimpleContext context;
676 bool cond = (k % 2) == 0;
677 if (cond) {
678 context.Check("let x = 1; x", EXPECT_RESULT, Number::New(isolate, 1));
679 context.Check("let z = 4; z", EXPECT_RESULT, Number::New(isolate, 4));
680 } else {
681 context.Check("let z = 1; z", EXPECT_RESULT, Number::New(isolate, 1));
682 context.Check("let x = 4; x", EXPECT_RESULT, Number::New(isolate, 4));
683 }
684 context.Check("let y = 2; x", EXPECT_RESULT,
685 Number::New(isolate, cond ? 1 : 4));
686 }
687}
688
689
690TEST(CrossScriptReferencesHarmony) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000691 v8::Isolate* isolate = CcTest::isolate();
692 HandleScope scope(isolate);
693
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400694 // Check that simple cross-script global scope access works.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000695 const char* decs[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400696 "'use strict'; var x = 1; x", "x",
697 "'use strict'; function x() { return 1 }; x()", "x()",
698 "'use strict'; let x = 1; x", "x",
699 "'use strict'; const x = 1; x", "x",
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000700 NULL
701 };
702
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400703 for (int i = 0; decs[i] != NULL; i += 2) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000704 SimpleContext context;
705 context.Check(decs[i], EXPECT_RESULT, Number::New(isolate, 1));
706 context.Check(decs[i+1], EXPECT_RESULT, Number::New(isolate, 1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000707 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400708
709 // Check that cross-script global scope access works with late declarations.
710 {
711 SimpleContext context;
712 context.Check("function d0() { return x0 }", // dynamic lookup
713 EXPECT_RESULT, Undefined(isolate));
714 context.Check("this.x0 = -1;"
715 "d0()",
716 EXPECT_RESULT, Number::New(isolate, -1));
717 context.Check("'use strict';"
718 "function f0() { let y = 10; return x0 + y }"
719 "function g0() { let y = 10; return eval('x0 + y') }"
720 "function h0() { let y = 10; return (1,eval)('x0') + y }"
721 "x0 + f0() + g0() + h0()",
722 EXPECT_RESULT, Number::New(isolate, 26));
723
724 context.Check("'use strict';"
725 "let x1 = 1;"
726 "function f1() { let y = 10; return x1 + y }"
727 "function g1() { let y = 10; return eval('x1 + y') }"
728 "function h1() { let y = 10; return (1,eval)('x1') + y }"
729 "function i1() { "
730 " let y = 10; return (typeof x2 === 'undefined' ? 0 : 2) + y"
731 "}"
732 "function j1() { let y = 10; return eval('x2 + y') }"
733 "function k1() { let y = 10; return (1,eval)('x2') + y }"
734 "function cl() { "
735 " let y = 10; "
736 " return { "
737 " f: function(){ return x1 + y },"
738 " g: function(){ return eval('x1 + y') },"
739 " h: function(){ return (1,eval)('x1') + y },"
740 " i: function(){"
741 " return (typeof x2 == 'undefined' ? 0 : 2) + y"
742 " },"
743 " j: function(){ return eval('x2 + y') },"
744 " k: function(){ return (1,eval)('x2') + y },"
745 " }"
746 "}"
747 "let o = cl();"
748 "x1 + eval('x1') + (1,eval)('x1') + f1() + g1() + h1();",
749 EXPECT_RESULT, Number::New(isolate, 36));
750 context.Check("x1 + eval('x1') + (1,eval)('x1') + f1() + g1() + h1();",
751 EXPECT_RESULT, Number::New(isolate, 36));
752 context.Check("o.f() + o.g() + o.h();",
753 EXPECT_RESULT, Number::New(isolate, 33));
754 context.Check("i1() + o.i();",
755 EXPECT_RESULT, Number::New(isolate, 20));
756
757 context.Check("'use strict';"
758 "let x2 = 2;"
759 "function f2() { let y = 20; return x2 + y }"
760 "function g2() { let y = 20; return eval('x2 + y') }"
761 "function h2() { let y = 20; return (1,eval)('x2') + y }"
762 "function i2() { let y = 20; return x1 + y }"
763 "function j2() { let y = 20; return eval('x1 + y') }"
764 "function k2() { let y = 20; return (1,eval)('x1') + y }"
765 "x2 + eval('x2') + (1,eval)('x2') + f2() + g2() + h2();",
766 EXPECT_RESULT, Number::New(isolate, 72));
767 context.Check("x1 + eval('x1') + (1,eval)('x1') + f1() + g1() + h1();",
768 EXPECT_RESULT, Number::New(isolate, 36));
769 context.Check("i1() + j1() + k1();",
770 EXPECT_RESULT, Number::New(isolate, 36));
771 context.Check("i2() + j2() + k2();",
772 EXPECT_RESULT, Number::New(isolate, 63));
773 context.Check("o.f() + o.g() + o.h();",
774 EXPECT_RESULT, Number::New(isolate, 33));
775 context.Check("o.i() + o.j() + o.k();",
776 EXPECT_RESULT, Number::New(isolate, 36));
777 context.Check("i1() + o.i();",
778 EXPECT_RESULT, Number::New(isolate, 24));
779
780 context.Check("'use strict';"
781 "let x0 = 100;"
782 "x0 + eval('x0') + (1,eval)('x0') + "
783 " d0() + f0() + g0() + h0();",
784 EXPECT_RESULT, Number::New(isolate, 730));
785 context.Check("x0 + eval('x0') + (1,eval)('x0') + "
786 " d0() + f0() + g0() + h0();",
787 EXPECT_RESULT, Number::New(isolate, 730));
788 context.Check("delete this.x0;"
789 "x0 + eval('x0') + (1,eval)('x0') + "
790 " d0() + f0() + g0() + h0();",
791 EXPECT_RESULT, Number::New(isolate, 730));
792 context.Check("this.x1 = 666;"
793 "x1 + eval('x1') + (1,eval)('x1') + f1() + g1() + h1();",
794 EXPECT_RESULT, Number::New(isolate, 36));
795 context.Check("delete this.x1;"
796 "x1 + eval('x1') + (1,eval)('x1') + f1() + g1() + h1();",
797 EXPECT_RESULT, Number::New(isolate, 36));
798 }
799
800 // Check that caching does respect scopes.
801 {
802 SimpleContext context;
803 const char* script1 = "(function(){ return y1 })()";
804 const char* script2 = "(function(){ return y2 })()";
805
806 context.Check(script1, EXPECT_EXCEPTION);
807 context.Check("this.y1 = 1; this.y2 = 2; 0;",
808 EXPECT_RESULT, Number::New(isolate, 0));
809 context.Check(script1,
810 EXPECT_RESULT, Number::New(isolate, 1));
811 context.Check("'use strict'; let y1 = 3; 0;",
812 EXPECT_RESULT, Number::New(isolate, 0));
813 context.Check(script1,
814 EXPECT_RESULT, Number::New(isolate, 3));
815 context.Check("y1 = 4;",
816 EXPECT_RESULT, Number::New(isolate, 4));
817 context.Check(script1,
818 EXPECT_RESULT, Number::New(isolate, 4));
819
820 context.Check(script2,
821 EXPECT_RESULT, Number::New(isolate, 2));
822 context.Check("'use strict'; let y2 = 5; 0;",
823 EXPECT_RESULT, Number::New(isolate, 0));
824 context.Check(script1,
825 EXPECT_RESULT, Number::New(isolate, 4));
826 context.Check(script2,
827 EXPECT_RESULT, Number::New(isolate, 5));
828 }
829}
830
831
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000832TEST(CrossScriptReferencesHarmonyRegress) {
833 v8::Isolate* isolate = CcTest::isolate();
834 HandleScope scope(isolate);
835 SimpleContext context;
836 context.Check(
837 "'use strict';"
838 "function i1() { "
839 " let y = 10; return (typeof x2 === 'undefined' ? 0 : 2) + y"
840 "}"
841 "i1();"
842 "i1();",
843 EXPECT_RESULT, Number::New(isolate, 10));
844 context.Check(
845 "'use strict';"
846 "let x2 = 2; i1();",
847 EXPECT_RESULT, Number::New(isolate, 12));
848}
849
850
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400851TEST(GlobalLexicalOSR) {
852 i::FLAG_use_strict = true;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400853
854 v8::Isolate* isolate = CcTest::isolate();
855 HandleScope scope(isolate);
856 SimpleContext context;
857
858 context.Check("'use strict';"
859 "let x = 1; x;",
860 EXPECT_RESULT, Number::New(isolate, 1));
861 context.Check("'use strict';"
862 "let y = 2*x;"
863 "++x;"
864 "let z = 0;"
865 "const limit = 100000;"
866 "for (var i = 0; i < limit; ++i) {"
867 " z += x + y;"
868 "}"
869 "z;",
870 EXPECT_RESULT, Number::New(isolate, 400000));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000871}
872
873
874TEST(CrossScriptConflicts) {
875 i::FLAG_use_strict = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000876
877 HandleScope scope(CcTest::isolate());
878
879 const char* firsts[] = {
880 "var x = 1; x",
881 "function x() { return 1 }; x()",
882 "let x = 1; x",
883 "const x = 1; x",
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000884 NULL
885 };
886 const char* seconds[] = {
887 "var x = 2; x",
888 "function x() { return 2 }; x()",
889 "let x = 2; x",
890 "const x = 2; x",
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000891 NULL
892 };
893
894 for (int i = 0; firsts[i] != NULL; ++i) {
895 for (int j = 0; seconds[j] != NULL; ++j) {
896 SimpleContext context;
897 context.Check(firsts[i], EXPECT_RESULT,
898 Number::New(CcTest::isolate(), 1));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400899 bool success_case = i < 2 && j < 2;
900 Local<Value> success_result;
901 if (success_case) success_result = Number::New(CcTest::isolate(), 2);
902
903 context.Check(seconds[j], success_case ? EXPECT_RESULT : EXPECT_EXCEPTION,
904 success_result);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000905 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000906 }
907}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400908
909
910TEST(CrossScriptDynamicLookup) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400911 HandleScope handle_scope(CcTest::isolate());
912
913 {
914 SimpleContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000915 Local<String> undefined_string =
916 String::NewFromUtf8(CcTest::isolate(), "undefined",
917 v8::NewStringType::kInternalized)
918 .ToLocalChecked();
919 Local<String> number_string =
920 String::NewFromUtf8(CcTest::isolate(), "number",
921 v8::NewStringType::kInternalized)
922 .ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400923
924 context.Check(
925 "function f(o) { with(o) { return x; } }"
926 "function g(o) { with(o) { x = 15; } }"
927 "function h(o) { with(o) { return typeof x; } }",
928 EXPECT_RESULT, Undefined(CcTest::isolate()));
929 context.Check("h({})", EXPECT_RESULT, undefined_string);
930 context.Check(
931 "'use strict';"
932 "let x = 1;"
933 "f({})",
934 EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
935 context.Check(
936 "'use strict';"
937 "g({});0",
938 EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
939 context.Check("f({})", EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
940 context.Check("h({})", EXPECT_RESULT, number_string);
941 }
942}
943
944
945TEST(CrossScriptGlobal) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400946 HandleScope handle_scope(CcTest::isolate());
947 {
948 SimpleContext context;
949
950 context.Check(
951 "var global = this;"
952 "global.x = 255;"
953 "x",
954 EXPECT_RESULT, Number::New(CcTest::isolate(), 255));
955 context.Check(
956 "'use strict';"
957 "let x = 1;"
958 "global.x",
959 EXPECT_RESULT, Number::New(CcTest::isolate(), 255));
960 context.Check("global.x = 15; x", EXPECT_RESULT,
961 Number::New(CcTest::isolate(), 1));
962 context.Check("x = 221; global.x", EXPECT_RESULT,
963 Number::New(CcTest::isolate(), 15));
964 context.Check(
965 "z = 15;"
966 "function f() { return z; };"
967 "for (var k = 0; k < 3; k++) { f(); }"
968 "f()",
969 EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
970 context.Check(
971 "'use strict';"
972 "let z = 5; f()",
973 EXPECT_RESULT, Number::New(CcTest::isolate(), 5));
974 context.Check(
975 "function f() { konst = 10; return konst; };"
976 "f()",
977 EXPECT_RESULT, Number::New(CcTest::isolate(), 10));
978 context.Check(
979 "'use strict';"
980 "const konst = 255;"
981 "f()",
982 EXPECT_EXCEPTION);
983 }
984}
985
986
987TEST(CrossScriptStaticLookupUndeclared) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400988 HandleScope handle_scope(CcTest::isolate());
989
990 {
991 SimpleContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000992 Local<String> undefined_string =
993 String::NewFromUtf8(CcTest::isolate(), "undefined",
994 v8::NewStringType::kInternalized)
995 .ToLocalChecked();
996 Local<String> number_string =
997 String::NewFromUtf8(CcTest::isolate(), "number",
998 v8::NewStringType::kInternalized)
999 .ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001000
1001 context.Check(
1002 "function f(o) { return x; }"
1003 "function g(v) { x = v; }"
1004 "function h(o) { return typeof x; }",
1005 EXPECT_RESULT, Undefined(CcTest::isolate()));
1006 context.Check("h({})", EXPECT_RESULT, undefined_string);
1007 context.Check(
1008 "'use strict';"
1009 "let x = 1;"
1010 "f({})",
1011 EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
1012 context.Check(
1013 "'use strict';"
1014 "g(15);x",
1015 EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
1016 context.Check("h({})", EXPECT_RESULT, number_string);
1017 context.Check("f({})", EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
1018 context.Check("h({})", EXPECT_RESULT, number_string);
1019 }
1020}
1021
1022
1023TEST(CrossScriptLoadICs) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001024 i::FLAG_allow_natives_syntax = true;
1025
1026 HandleScope handle_scope(CcTest::isolate());
1027
1028 {
1029 SimpleContext context;
1030 context.Check(
1031 "x = 15;"
1032 "function f() { return x; }"
1033 "function g() { return x; }"
1034 "f()",
1035 EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
1036 context.Check(
1037 "'use strict';"
1038 "let x = 5;"
1039 "f()",
1040 EXPECT_RESULT, Number::New(CcTest::isolate(), 5));
1041 for (int k = 0; k < 3; k++) {
1042 context.Check("g()", EXPECT_RESULT, Number::New(CcTest::isolate(), 5));
1043 }
1044 for (int k = 0; k < 3; k++) {
1045 context.Check("f()", EXPECT_RESULT, Number::New(CcTest::isolate(), 5));
1046 }
1047 context.Check("%OptimizeFunctionOnNextCall(g); g()", EXPECT_RESULT,
1048 Number::New(CcTest::isolate(), 5));
1049 context.Check("%OptimizeFunctionOnNextCall(f); f()", EXPECT_RESULT,
1050 Number::New(CcTest::isolate(), 5));
1051 }
1052 {
1053 SimpleContext context;
1054 context.Check(
1055 "x = 15;"
1056 "function f() { return x; }"
1057 "f()",
1058 EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
1059 for (int k = 0; k < 3; k++) {
1060 context.Check("f()", EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
1061 }
1062 context.Check("%OptimizeFunctionOnNextCall(f); f()", EXPECT_RESULT,
1063 Number::New(CcTest::isolate(), 15));
1064 context.Check(
1065 "'use strict';"
1066 "let x = 5;"
1067 "f()",
1068 EXPECT_RESULT, Number::New(CcTest::isolate(), 5));
1069 for (int k = 0; k < 3; k++) {
1070 context.Check("f()", EXPECT_RESULT, Number::New(CcTest::isolate(), 5));
1071 }
1072 context.Check("%OptimizeFunctionOnNextCall(f); f()", EXPECT_RESULT,
1073 Number::New(CcTest::isolate(), 5));
1074 }
1075}
1076
1077
1078TEST(CrossScriptStoreICs) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001079 i::FLAG_allow_natives_syntax = true;
1080
1081 HandleScope handle_scope(CcTest::isolate());
1082
1083 {
1084 SimpleContext context;
1085 context.Check(
1086 "var global = this;"
1087 "x = 15;"
1088 "function f(v) { x = v; }"
1089 "function g(v) { x = v; }"
1090 "f(10); x",
1091 EXPECT_RESULT, Number::New(CcTest::isolate(), 10));
1092 context.Check(
1093 "'use strict';"
1094 "let x = 5;"
1095 "f(7); x",
1096 EXPECT_RESULT, Number::New(CcTest::isolate(), 7));
1097 context.Check("global.x", EXPECT_RESULT,
1098 Number::New(CcTest::isolate(), 10));
1099 for (int k = 0; k < 3; k++) {
1100 context.Check("g(31); x", EXPECT_RESULT,
1101 Number::New(CcTest::isolate(), 31));
1102 }
1103 context.Check("global.x", EXPECT_RESULT,
1104 Number::New(CcTest::isolate(), 10));
1105 for (int k = 0; k < 3; k++) {
1106 context.Check("f(32); x", EXPECT_RESULT,
1107 Number::New(CcTest::isolate(), 32));
1108 }
1109 context.Check("global.x", EXPECT_RESULT,
1110 Number::New(CcTest::isolate(), 10));
1111 context.Check("%OptimizeFunctionOnNextCall(g); g(18); x", EXPECT_RESULT,
1112 Number::New(CcTest::isolate(), 18));
1113 context.Check("global.x", EXPECT_RESULT,
1114 Number::New(CcTest::isolate(), 10));
1115 context.Check("%OptimizeFunctionOnNextCall(f); f(33); x", EXPECT_RESULT,
1116 Number::New(CcTest::isolate(), 33));
1117 context.Check("global.x", EXPECT_RESULT,
1118 Number::New(CcTest::isolate(), 10));
1119 }
1120 {
1121 SimpleContext context;
1122 context.Check(
1123 "var global = this;"
1124 "x = 15;"
1125 "function f(v) { x = v; }"
1126 "f(10); x",
1127 EXPECT_RESULT, Number::New(CcTest::isolate(), 10));
1128 for (int k = 0; k < 3; k++) {
1129 context.Check("f(18); x", EXPECT_RESULT,
1130 Number::New(CcTest::isolate(), 18));
1131 }
1132 context.Check("%OptimizeFunctionOnNextCall(f); f(20); x", EXPECT_RESULT,
1133 Number::New(CcTest::isolate(), 20));
1134 context.Check(
1135 "'use strict';"
1136 "let x = 5;"
1137 "f(8); x",
1138 EXPECT_RESULT, Number::New(CcTest::isolate(), 8));
1139 context.Check("global.x", EXPECT_RESULT,
1140 Number::New(CcTest::isolate(), 20));
1141 for (int k = 0; k < 3; k++) {
1142 context.Check("f(13); x", EXPECT_RESULT,
1143 Number::New(CcTest::isolate(), 13));
1144 }
1145 context.Check("global.x", EXPECT_RESULT,
1146 Number::New(CcTest::isolate(), 20));
1147 context.Check("%OptimizeFunctionOnNextCall(f); f(41); x", EXPECT_RESULT,
1148 Number::New(CcTest::isolate(), 41));
1149 context.Check("global.x", EXPECT_RESULT,
1150 Number::New(CcTest::isolate(), 20));
1151 }
1152}
1153
1154
1155TEST(CrossScriptAssignmentToConst) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001156 i::FLAG_allow_natives_syntax = true;
1157
1158 HandleScope handle_scope(CcTest::isolate());
1159
1160 {
1161 SimpleContext context;
1162
1163 context.Check("function f() { x = 27; }", EXPECT_RESULT,
1164 Undefined(CcTest::isolate()));
1165 context.Check("'use strict';const x = 1; x", EXPECT_RESULT,
1166 Number::New(CcTest::isolate(), 1));
1167 context.Check("f();", EXPECT_EXCEPTION);
1168 context.Check("x", EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
1169 context.Check("f();", EXPECT_EXCEPTION);
1170 context.Check("x", EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
1171 context.Check("%OptimizeFunctionOnNextCall(f);f();", EXPECT_EXCEPTION);
1172 context.Check("x", EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
1173 }
1174}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001175
1176
1177TEST(Regress425510) {
1178 i::FLAG_allow_natives_syntax = true;
1179
1180 HandleScope handle_scope(CcTest::isolate());
1181
1182 {
1183 SimpleContext context;
1184
1185 context.Check("'use strict'; o; const o = 10", EXPECT_EXCEPTION);
1186
1187 for (int i = 0; i < 100; i++) {
1188 context.Check("o.prototype", EXPECT_EXCEPTION);
1189 }
1190 }
1191}
1192
1193
1194TEST(Regress3941) {
1195 i::FLAG_allow_natives_syntax = true;
1196
1197 HandleScope handle_scope(CcTest::isolate());
1198
1199 {
1200 SimpleContext context;
1201 context.Check("function f() { x = 1; }", EXPECT_RESULT,
1202 Undefined(CcTest::isolate()));
1203 context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);
1204 }
1205
1206
1207 {
1208 // Train ICs.
1209 SimpleContext context;
1210 context.Check("function f() { x = 1; }", EXPECT_RESULT,
1211 Undefined(CcTest::isolate()));
1212 for (int i = 0; i < 4; i++) {
1213 context.Check("f(); x", EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
1214 }
1215 context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);
1216 }
1217
1218
1219 {
1220 // Optimize.
1221 SimpleContext context;
1222 context.Check("function f() { x = 1; }", EXPECT_RESULT,
1223 Undefined(CcTest::isolate()));
1224 for (int i = 0; i < 4; i++) {
1225 context.Check("f(); x", EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
1226 }
1227 context.Check("%OptimizeFunctionOnNextCall(f); f(); x", EXPECT_RESULT,
1228 Number::New(CcTest::isolate(), 1));
1229
1230 context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);
1231 }
1232}
1233
1234
1235TEST(Regress3941_Reads) {
1236 i::FLAG_allow_natives_syntax = true;
1237
1238 HandleScope handle_scope(CcTest::isolate());
1239
1240 {
1241 SimpleContext context;
1242 context.Check("function f() { return x; }", EXPECT_RESULT,
1243 Undefined(CcTest::isolate()));
1244 context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);
1245 }
1246
1247
1248 {
1249 // Train ICs.
1250 SimpleContext context;
1251 context.Check("function f() { return x; }", EXPECT_RESULT,
1252 Undefined(CcTest::isolate()));
1253 for (int i = 0; i < 4; i++) {
1254 context.Check("f()", EXPECT_EXCEPTION);
1255 }
1256 context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);
1257 }
1258
1259
1260 {
1261 // Optimize.
1262 SimpleContext context;
1263 context.Check("function f() { return x; }", EXPECT_RESULT,
1264 Undefined(CcTest::isolate()));
1265 for (int i = 0; i < 4; i++) {
1266 context.Check("f()", EXPECT_EXCEPTION);
1267 }
1268 context.Check("%OptimizeFunctionOnNextCall(f);", EXPECT_RESULT,
1269 Undefined(CcTest::isolate()));
1270
1271 context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);
1272 }
1273}