blob: 35cb515dc100f7357e6047056b7870b7128054d8 [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 Murdochb8a8cc12014-11-26 15:28:44 +0000230 HandleScope scope(CcTest::isolate());
231 v8::V8::Initialize();
Steve Blocka7e24c12009-10-30 11:49:00 +0000232
233 { DeclarationContext context;
234 context.Check("var x; x",
235 1, // access
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000236 0, 0, EXPECT_RESULT, Undefined(CcTest::isolate()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000237 }
238
239 { DeclarationContext context;
240 context.Check("var x = 0; x",
241 1, // access
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000242 1, // initialization
243 0, EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
Steve Blocka7e24c12009-10-30 11:49:00 +0000244 }
245
246 { DeclarationContext context;
247 context.Check("function x() { }; x",
248 1, // access
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100249 0,
Steve Blocka7e24c12009-10-30 11:49:00 +0000250 0,
251 EXPECT_RESULT);
252 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000253}
254
255
Steve Blocka7e24c12009-10-30 11:49:00 +0000256class AbsentPropertyContext: public DeclarationContext {
257 protected:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000258 virtual v8::Local<Integer> Query(Local<Name> key) {
259 return v8::Local<Integer>();
Steve Blocka7e24c12009-10-30 11:49:00 +0000260 }
261};
262
263
264TEST(Absent) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000265 v8::Isolate* isolate = CcTest::isolate();
266 v8::V8::Initialize();
267 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000268
269 { AbsentPropertyContext context;
270 context.Check("var x; x",
271 1, // access
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000272 0, 0, EXPECT_RESULT, Undefined(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +0000273 }
274
275 { AbsentPropertyContext context;
276 context.Check("var x = 0; x",
277 1, // access
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000278 1, // initialization
279 0, EXPECT_RESULT, Number::New(isolate, 0));
Steve Blocka7e24c12009-10-30 11:49:00 +0000280 }
281
282 { AbsentPropertyContext context;
283 context.Check("function x() { }; x",
284 1, // access
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100285 0,
Steve Blocka7e24c12009-10-30 11:49:00 +0000286 0,
287 EXPECT_RESULT);
288 }
289
290 { AbsentPropertyContext context;
Steve Blocka7e24c12009-10-30 11:49:00 +0000291 context.Check("if (false) { var x = 0 }; x",
292 1, // access
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000293 0, 0, EXPECT_RESULT, Undefined(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +0000294 }
295}
296
297
298
299class AppearingPropertyContext: public DeclarationContext {
300 public:
301 enum State {
302 DECLARE,
303 INITIALIZE_IF_ASSIGN,
304 UNKNOWN
305 };
306
307 AppearingPropertyContext() : state_(DECLARE) { }
308
309 protected:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000310 virtual v8::Local<Integer> Query(Local<Name> key) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000311 switch (state_) {
312 case DECLARE:
313 // Force declaration by returning that the
314 // property is absent.
315 state_ = INITIALIZE_IF_ASSIGN;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000316 return Local<Integer>();
Steve Blocka7e24c12009-10-30 11:49:00 +0000317 case INITIALIZE_IF_ASSIGN:
318 // Return that the property is present so we only get the
319 // setter called when initializing with a value.
320 state_ = UNKNOWN;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000321 return Integer::New(isolate(), v8::None);
Steve Blocka7e24c12009-10-30 11:49:00 +0000322 default:
323 CHECK(state_ == UNKNOWN);
324 break;
325 }
326 // Do the lookup in the object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000327 return v8::Local<Integer>();
Steve Blocka7e24c12009-10-30 11:49:00 +0000328 }
329
330 private:
331 State state_;
332};
333
334
335TEST(Appearing) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000336 v8::V8::Initialize();
337 HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000338
339 { AppearingPropertyContext context;
340 context.Check("var x; x",
341 1, // access
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000342 0, 0, EXPECT_RESULT, Undefined(CcTest::isolate()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000343 }
344
345 { AppearingPropertyContext context;
346 context.Check("var x = 0; x",
347 1, // access
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000348 1, // initialization
349 0, EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
Steve Blocka7e24c12009-10-30 11:49:00 +0000350 }
351
352 { AppearingPropertyContext context;
353 context.Check("function x() { }; x",
354 1, // access
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100355 0,
Steve Blocka7e24c12009-10-30 11:49:00 +0000356 0,
357 EXPECT_RESULT);
358 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000359}
360
361
362
363class ExistsInPrototypeContext: public DeclarationContext {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000364 public:
365 ExistsInPrototypeContext() { InitializeIfNeeded(); }
Steve Blocka7e24c12009-10-30 11:49:00 +0000366 protected:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000367 virtual v8::Local<Integer> Query(Local<Name> key) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000368 // Let it seem that the property exists in the prototype object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000369 return Integer::New(isolate(), v8::None);
Steve Blocka7e24c12009-10-30 11:49:00 +0000370 }
371
372 // Use the prototype as the holder for the interceptors.
373 virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
374 return function->PrototypeTemplate();
375 }
376};
377
378
379TEST(ExistsInPrototype) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000380 HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000381
382 // Sanity check to make sure that the holder of the interceptor
383 // really is the prototype object.
384 { ExistsInPrototypeContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000385 context.Check("this.x = 87; this.x", 0, 0, 1, EXPECT_RESULT,
386 Number::New(CcTest::isolate(), 87));
Steve Blocka7e24c12009-10-30 11:49:00 +0000387 }
388
389 { ExistsInPrototypeContext context;
390 context.Check("var x; x",
Steve Blocka7e24c12009-10-30 11:49:00 +0000391 0,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000392 0,
393 0,
394 EXPECT_RESULT, Undefined(CcTest::isolate()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000395 }
396
397 { ExistsInPrototypeContext context;
398 context.Check("var x = 0; x",
399 0,
400 0,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000401 0,
402 EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
Steve Blocka7e24c12009-10-30 11:49:00 +0000403 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000404}
405
406
407
408class AbsentInPrototypeContext: public DeclarationContext {
409 protected:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000410 virtual v8::Local<Integer> Query(Local<Name> key) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000411 // Let it seem that the property is absent in the prototype object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000412 return Local<Integer>();
Steve Blocka7e24c12009-10-30 11:49:00 +0000413 }
414
415 // Use the prototype as the holder for the interceptors.
416 virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
417 return function->PrototypeTemplate();
418 }
419};
420
421
422TEST(AbsentInPrototype) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000423 v8::V8::Initialize();
424 HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000425
426 { AbsentInPrototypeContext context;
427 context.Check("if (false) { var x = 0; }; x",
428 0,
429 0,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000430 0,
431 EXPECT_RESULT, Undefined(CcTest::isolate()));
432 }
433}
434
435
436
437class ExistsInHiddenPrototypeContext: public DeclarationContext {
438 public:
439 ExistsInHiddenPrototypeContext() {
440 hidden_proto_ = FunctionTemplate::New(CcTest::isolate());
441 hidden_proto_->SetHiddenPrototype(true);
442 }
443
444 protected:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000445 virtual v8::Local<Integer> Query(Local<Name> key) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000446 // Let it seem that the property exists in the hidden prototype object.
447 return Integer::New(isolate(), v8::None);
448 }
449
450 // Install the hidden prototype after the global object has been created.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000451 virtual void PostInitializeContext(Local<Context> context) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000452 Local<Object> global_object = context->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000453 Local<Object> hidden_proto = hidden_proto_->GetFunction(context)
454 .ToLocalChecked()
455 ->NewInstance(context)
456 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000457 Local<Object> inner_global =
458 Local<Object>::Cast(global_object->GetPrototype());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000459 inner_global->SetPrototype(context, hidden_proto).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000460 }
461
462 // Use the hidden prototype as the holder for the interceptors.
463 virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
464 return hidden_proto_->InstanceTemplate();
465 }
466
467 private:
468 Local<FunctionTemplate> hidden_proto_;
469};
470
471
472TEST(ExistsInHiddenPrototype) {
473 HandleScope scope(CcTest::isolate());
474
475 { ExistsInHiddenPrototypeContext context;
476 context.Check("var x; x", 0, 0, 0, EXPECT_RESULT,
477 Undefined(CcTest::isolate()));
478 }
479
480 { ExistsInHiddenPrototypeContext context;
481 context.Check("var x = 0; x", 0, 0, 0, EXPECT_RESULT,
482 Number::New(CcTest::isolate(), 0));
483 }
484
485 { ExistsInHiddenPrototypeContext context;
486 context.Check("function x() { }; x",
487 0,
488 0,
489 0,
490 EXPECT_RESULT);
491 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000492}
493
494
495
496class SimpleContext {
497 public:
498 SimpleContext()
499 : handle_scope_(CcTest::isolate()),
500 context_(Context::New(CcTest::isolate())) {
501 context_->Enter();
502 }
503
504 ~SimpleContext() {
505 context_->Exit();
506 }
507
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000508 void Check(const char* source, Expectations expectations,
509 v8::Local<Value> value = Local<Value>()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000510 HandleScope scope(context_->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000511 TryCatch catcher(context_->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000512 catcher.SetVerbose(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000513 MaybeLocal<Script> script = Script::Compile(
514 context_, String::NewFromUtf8(context_->GetIsolate(), source,
515 v8::NewStringType::kNormal)
516 .ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000517 if (expectations == EXPECT_ERROR) {
518 CHECK(script.IsEmpty());
519 return;
520 }
521 CHECK(!script.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000522 MaybeLocal<Value> result = script.ToLocalChecked()->Run(context_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000523 if (expectations == EXPECT_RESULT) {
524 CHECK(!catcher.HasCaught());
525 if (!value.IsEmpty()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000526 CHECK(value->Equals(context_, result.ToLocalChecked()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000527 }
528 } else {
529 CHECK(expectations == EXPECT_EXCEPTION);
530 CHECK(catcher.HasCaught());
531 if (!value.IsEmpty()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000532 CHECK(value->Equals(context_, catcher.Exception()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000533 }
534 }
535 }
536
537 private:
538 HandleScope handle_scope_;
539 Local<Context> context_;
540};
541
542
543TEST(CrossScriptReferences) {
544 v8::Isolate* isolate = CcTest::isolate();
545 HandleScope scope(isolate);
546
547 { SimpleContext context;
548 context.Check("var x = 1; x",
549 EXPECT_RESULT, Number::New(isolate, 1));
550 context.Check("var x = 2; x",
551 EXPECT_RESULT, Number::New(isolate, 2));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000552 context.Check("x = 5; x",
553 EXPECT_RESULT, Number::New(isolate, 5));
554 context.Check("var x = 6; x",
555 EXPECT_RESULT, Number::New(isolate, 6));
556 context.Check("this.x",
557 EXPECT_RESULT, Number::New(isolate, 6));
558 context.Check("function x() { return 7 }; x()",
559 EXPECT_RESULT, Number::New(isolate, 7));
560 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000561}
562
563
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400564TEST(CrossScriptReferences_Simple) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000565 i::FLAG_use_strict = true;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400566
567 v8::Isolate* isolate = CcTest::isolate();
568 HandleScope scope(isolate);
569
570 {
571 SimpleContext context;
572 context.Check("let x = 1; x", EXPECT_RESULT, Number::New(isolate, 1));
573 context.Check("let x = 5; x", EXPECT_EXCEPTION);
574 }
575}
576
577
578TEST(CrossScriptReferences_Simple2) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400579 i::FLAG_use_strict = true;
580
581 v8::Isolate* isolate = CcTest::isolate();
582 HandleScope scope(isolate);
583
584 for (int k = 0; k < 100; k++) {
585 SimpleContext context;
586 bool cond = (k % 2) == 0;
587 if (cond) {
588 context.Check("let x = 1; x", EXPECT_RESULT, Number::New(isolate, 1));
589 context.Check("let z = 4; z", EXPECT_RESULT, Number::New(isolate, 4));
590 } else {
591 context.Check("let z = 1; z", EXPECT_RESULT, Number::New(isolate, 1));
592 context.Check("let x = 4; x", EXPECT_RESULT, Number::New(isolate, 4));
593 }
594 context.Check("let y = 2; x", EXPECT_RESULT,
595 Number::New(isolate, cond ? 1 : 4));
596 }
597}
598
599
600TEST(CrossScriptReferencesHarmony) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000601 v8::Isolate* isolate = CcTest::isolate();
602 HandleScope scope(isolate);
603
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400604 // Check that simple cross-script global scope access works.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000605 const char* decs[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400606 "'use strict'; var x = 1; x", "x",
607 "'use strict'; function x() { return 1 }; x()", "x()",
608 "'use strict'; let x = 1; x", "x",
609 "'use strict'; const x = 1; x", "x",
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000610 NULL
611 };
612
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400613 for (int i = 0; decs[i] != NULL; i += 2) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000614 SimpleContext context;
615 context.Check(decs[i], EXPECT_RESULT, Number::New(isolate, 1));
616 context.Check(decs[i+1], EXPECT_RESULT, Number::New(isolate, 1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000617 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400618
619 // Check that cross-script global scope access works with late declarations.
620 {
621 SimpleContext context;
622 context.Check("function d0() { return x0 }", // dynamic lookup
623 EXPECT_RESULT, Undefined(isolate));
624 context.Check("this.x0 = -1;"
625 "d0()",
626 EXPECT_RESULT, Number::New(isolate, -1));
627 context.Check("'use strict';"
628 "function f0() { let y = 10; return x0 + y }"
629 "function g0() { let y = 10; return eval('x0 + y') }"
630 "function h0() { let y = 10; return (1,eval)('x0') + y }"
631 "x0 + f0() + g0() + h0()",
632 EXPECT_RESULT, Number::New(isolate, 26));
633
634 context.Check("'use strict';"
635 "let x1 = 1;"
636 "function f1() { let y = 10; return x1 + y }"
637 "function g1() { let y = 10; return eval('x1 + y') }"
638 "function h1() { let y = 10; return (1,eval)('x1') + y }"
639 "function i1() { "
640 " let y = 10; return (typeof x2 === 'undefined' ? 0 : 2) + y"
641 "}"
642 "function j1() { let y = 10; return eval('x2 + y') }"
643 "function k1() { let y = 10; return (1,eval)('x2') + y }"
644 "function cl() { "
645 " let y = 10; "
646 " return { "
647 " f: function(){ return x1 + y },"
648 " g: function(){ return eval('x1 + y') },"
649 " h: function(){ return (1,eval)('x1') + y },"
650 " i: function(){"
651 " return (typeof x2 == 'undefined' ? 0 : 2) + y"
652 " },"
653 " j: function(){ return eval('x2 + y') },"
654 " k: function(){ return (1,eval)('x2') + y },"
655 " }"
656 "}"
657 "let o = cl();"
658 "x1 + eval('x1') + (1,eval)('x1') + f1() + g1() + h1();",
659 EXPECT_RESULT, Number::New(isolate, 36));
660 context.Check("x1 + eval('x1') + (1,eval)('x1') + f1() + g1() + h1();",
661 EXPECT_RESULT, Number::New(isolate, 36));
662 context.Check("o.f() + o.g() + o.h();",
663 EXPECT_RESULT, Number::New(isolate, 33));
664 context.Check("i1() + o.i();",
665 EXPECT_RESULT, Number::New(isolate, 20));
666
667 context.Check("'use strict';"
668 "let x2 = 2;"
669 "function f2() { let y = 20; return x2 + y }"
670 "function g2() { let y = 20; return eval('x2 + y') }"
671 "function h2() { let y = 20; return (1,eval)('x2') + y }"
672 "function i2() { let y = 20; return x1 + y }"
673 "function j2() { let y = 20; return eval('x1 + y') }"
674 "function k2() { let y = 20; return (1,eval)('x1') + y }"
675 "x2 + eval('x2') + (1,eval)('x2') + f2() + g2() + h2();",
676 EXPECT_RESULT, Number::New(isolate, 72));
677 context.Check("x1 + eval('x1') + (1,eval)('x1') + f1() + g1() + h1();",
678 EXPECT_RESULT, Number::New(isolate, 36));
679 context.Check("i1() + j1() + k1();",
680 EXPECT_RESULT, Number::New(isolate, 36));
681 context.Check("i2() + j2() + k2();",
682 EXPECT_RESULT, Number::New(isolate, 63));
683 context.Check("o.f() + o.g() + o.h();",
684 EXPECT_RESULT, Number::New(isolate, 33));
685 context.Check("o.i() + o.j() + o.k();",
686 EXPECT_RESULT, Number::New(isolate, 36));
687 context.Check("i1() + o.i();",
688 EXPECT_RESULT, Number::New(isolate, 24));
689
690 context.Check("'use strict';"
691 "let x0 = 100;"
692 "x0 + eval('x0') + (1,eval)('x0') + "
693 " d0() + f0() + g0() + h0();",
694 EXPECT_RESULT, Number::New(isolate, 730));
695 context.Check("x0 + eval('x0') + (1,eval)('x0') + "
696 " d0() + f0() + g0() + h0();",
697 EXPECT_RESULT, Number::New(isolate, 730));
698 context.Check("delete this.x0;"
699 "x0 + eval('x0') + (1,eval)('x0') + "
700 " d0() + f0() + g0() + h0();",
701 EXPECT_RESULT, Number::New(isolate, 730));
702 context.Check("this.x1 = 666;"
703 "x1 + eval('x1') + (1,eval)('x1') + f1() + g1() + h1();",
704 EXPECT_RESULT, Number::New(isolate, 36));
705 context.Check("delete this.x1;"
706 "x1 + eval('x1') + (1,eval)('x1') + f1() + g1() + h1();",
707 EXPECT_RESULT, Number::New(isolate, 36));
708 }
709
710 // Check that caching does respect scopes.
711 {
712 SimpleContext context;
713 const char* script1 = "(function(){ return y1 })()";
714 const char* script2 = "(function(){ return y2 })()";
715
716 context.Check(script1, EXPECT_EXCEPTION);
717 context.Check("this.y1 = 1; this.y2 = 2; 0;",
718 EXPECT_RESULT, Number::New(isolate, 0));
719 context.Check(script1,
720 EXPECT_RESULT, Number::New(isolate, 1));
721 context.Check("'use strict'; let y1 = 3; 0;",
722 EXPECT_RESULT, Number::New(isolate, 0));
723 context.Check(script1,
724 EXPECT_RESULT, Number::New(isolate, 3));
725 context.Check("y1 = 4;",
726 EXPECT_RESULT, Number::New(isolate, 4));
727 context.Check(script1,
728 EXPECT_RESULT, Number::New(isolate, 4));
729
730 context.Check(script2,
731 EXPECT_RESULT, Number::New(isolate, 2));
732 context.Check("'use strict'; let y2 = 5; 0;",
733 EXPECT_RESULT, Number::New(isolate, 0));
734 context.Check(script1,
735 EXPECT_RESULT, Number::New(isolate, 4));
736 context.Check(script2,
737 EXPECT_RESULT, Number::New(isolate, 5));
738 }
739}
740
741
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000742TEST(CrossScriptReferencesHarmonyRegress) {
743 v8::Isolate* isolate = CcTest::isolate();
744 HandleScope scope(isolate);
745 SimpleContext context;
746 context.Check(
747 "'use strict';"
748 "function i1() { "
749 " let y = 10; return (typeof x2 === 'undefined' ? 0 : 2) + y"
750 "}"
751 "i1();"
752 "i1();",
753 EXPECT_RESULT, Number::New(isolate, 10));
754 context.Check(
755 "'use strict';"
756 "let x2 = 2; i1();",
757 EXPECT_RESULT, Number::New(isolate, 12));
758}
759
760
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400761TEST(GlobalLexicalOSR) {
762 i::FLAG_use_strict = true;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400763
764 v8::Isolate* isolate = CcTest::isolate();
765 HandleScope scope(isolate);
766 SimpleContext context;
767
768 context.Check("'use strict';"
769 "let x = 1; x;",
770 EXPECT_RESULT, Number::New(isolate, 1));
771 context.Check("'use strict';"
772 "let y = 2*x;"
773 "++x;"
774 "let z = 0;"
775 "const limit = 100000;"
776 "for (var i = 0; i < limit; ++i) {"
777 " z += x + y;"
778 "}"
779 "z;",
780 EXPECT_RESULT, Number::New(isolate, 400000));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000781}
782
783
784TEST(CrossScriptConflicts) {
785 i::FLAG_use_strict = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000786
787 HandleScope scope(CcTest::isolate());
788
789 const char* firsts[] = {
790 "var x = 1; x",
791 "function x() { return 1 }; x()",
792 "let x = 1; x",
793 "const x = 1; x",
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000794 NULL
795 };
796 const char* seconds[] = {
797 "var x = 2; x",
798 "function x() { return 2 }; x()",
799 "let x = 2; x",
800 "const x = 2; x",
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000801 NULL
802 };
803
804 for (int i = 0; firsts[i] != NULL; ++i) {
805 for (int j = 0; seconds[j] != NULL; ++j) {
806 SimpleContext context;
807 context.Check(firsts[i], EXPECT_RESULT,
808 Number::New(CcTest::isolate(), 1));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400809 bool success_case = i < 2 && j < 2;
810 Local<Value> success_result;
811 if (success_case) success_result = Number::New(CcTest::isolate(), 2);
812
813 context.Check(seconds[j], success_case ? EXPECT_RESULT : EXPECT_EXCEPTION,
814 success_result);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000815 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000816 }
817}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400818
819
820TEST(CrossScriptDynamicLookup) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400821 HandleScope handle_scope(CcTest::isolate());
822
823 {
824 SimpleContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000825 Local<String> undefined_string =
826 String::NewFromUtf8(CcTest::isolate(), "undefined",
827 v8::NewStringType::kInternalized)
828 .ToLocalChecked();
829 Local<String> number_string =
830 String::NewFromUtf8(CcTest::isolate(), "number",
831 v8::NewStringType::kInternalized)
832 .ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400833
834 context.Check(
835 "function f(o) { with(o) { return x; } }"
836 "function g(o) { with(o) { x = 15; } }"
837 "function h(o) { with(o) { return typeof x; } }",
838 EXPECT_RESULT, Undefined(CcTest::isolate()));
839 context.Check("h({})", EXPECT_RESULT, undefined_string);
840 context.Check(
841 "'use strict';"
842 "let x = 1;"
843 "f({})",
844 EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
845 context.Check(
846 "'use strict';"
847 "g({});0",
848 EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
849 context.Check("f({})", EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
850 context.Check("h({})", EXPECT_RESULT, number_string);
851 }
852}
853
854
855TEST(CrossScriptGlobal) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400856 HandleScope handle_scope(CcTest::isolate());
857 {
858 SimpleContext context;
859
860 context.Check(
861 "var global = this;"
862 "global.x = 255;"
863 "x",
864 EXPECT_RESULT, Number::New(CcTest::isolate(), 255));
865 context.Check(
866 "'use strict';"
867 "let x = 1;"
868 "global.x",
869 EXPECT_RESULT, Number::New(CcTest::isolate(), 255));
870 context.Check("global.x = 15; x", EXPECT_RESULT,
871 Number::New(CcTest::isolate(), 1));
872 context.Check("x = 221; global.x", EXPECT_RESULT,
873 Number::New(CcTest::isolate(), 15));
874 context.Check(
875 "z = 15;"
876 "function f() { return z; };"
877 "for (var k = 0; k < 3; k++) { f(); }"
878 "f()",
879 EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
880 context.Check(
881 "'use strict';"
882 "let z = 5; f()",
883 EXPECT_RESULT, Number::New(CcTest::isolate(), 5));
884 context.Check(
885 "function f() { konst = 10; return konst; };"
886 "f()",
887 EXPECT_RESULT, Number::New(CcTest::isolate(), 10));
888 context.Check(
889 "'use strict';"
890 "const konst = 255;"
891 "f()",
892 EXPECT_EXCEPTION);
893 }
894}
895
896
897TEST(CrossScriptStaticLookupUndeclared) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400898 HandleScope handle_scope(CcTest::isolate());
899
900 {
901 SimpleContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000902 Local<String> undefined_string =
903 String::NewFromUtf8(CcTest::isolate(), "undefined",
904 v8::NewStringType::kInternalized)
905 .ToLocalChecked();
906 Local<String> number_string =
907 String::NewFromUtf8(CcTest::isolate(), "number",
908 v8::NewStringType::kInternalized)
909 .ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400910
911 context.Check(
912 "function f(o) { return x; }"
913 "function g(v) { x = v; }"
914 "function h(o) { return typeof x; }",
915 EXPECT_RESULT, Undefined(CcTest::isolate()));
916 context.Check("h({})", EXPECT_RESULT, undefined_string);
917 context.Check(
918 "'use strict';"
919 "let x = 1;"
920 "f({})",
921 EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
922 context.Check(
923 "'use strict';"
924 "g(15);x",
925 EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
926 context.Check("h({})", EXPECT_RESULT, number_string);
927 context.Check("f({})", EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
928 context.Check("h({})", EXPECT_RESULT, number_string);
929 }
930}
931
932
933TEST(CrossScriptLoadICs) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400934 i::FLAG_allow_natives_syntax = true;
935
936 HandleScope handle_scope(CcTest::isolate());
937
938 {
939 SimpleContext context;
940 context.Check(
941 "x = 15;"
942 "function f() { return x; }"
943 "function g() { return x; }"
944 "f()",
945 EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
946 context.Check(
947 "'use strict';"
948 "let x = 5;"
949 "f()",
950 EXPECT_RESULT, Number::New(CcTest::isolate(), 5));
951 for (int k = 0; k < 3; k++) {
952 context.Check("g()", EXPECT_RESULT, Number::New(CcTest::isolate(), 5));
953 }
954 for (int k = 0; k < 3; k++) {
955 context.Check("f()", EXPECT_RESULT, Number::New(CcTest::isolate(), 5));
956 }
957 context.Check("%OptimizeFunctionOnNextCall(g); g()", EXPECT_RESULT,
958 Number::New(CcTest::isolate(), 5));
959 context.Check("%OptimizeFunctionOnNextCall(f); f()", EXPECT_RESULT,
960 Number::New(CcTest::isolate(), 5));
961 }
962 {
963 SimpleContext context;
964 context.Check(
965 "x = 15;"
966 "function f() { return x; }"
967 "f()",
968 EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
969 for (int k = 0; k < 3; k++) {
970 context.Check("f()", EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
971 }
972 context.Check("%OptimizeFunctionOnNextCall(f); f()", EXPECT_RESULT,
973 Number::New(CcTest::isolate(), 15));
974 context.Check(
975 "'use strict';"
976 "let x = 5;"
977 "f()",
978 EXPECT_RESULT, Number::New(CcTest::isolate(), 5));
979 for (int k = 0; k < 3; k++) {
980 context.Check("f()", EXPECT_RESULT, Number::New(CcTest::isolate(), 5));
981 }
982 context.Check("%OptimizeFunctionOnNextCall(f); f()", EXPECT_RESULT,
983 Number::New(CcTest::isolate(), 5));
984 }
985}
986
987
988TEST(CrossScriptStoreICs) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400989 i::FLAG_allow_natives_syntax = true;
990
991 HandleScope handle_scope(CcTest::isolate());
992
993 {
994 SimpleContext context;
995 context.Check(
996 "var global = this;"
997 "x = 15;"
998 "function f(v) { x = v; }"
999 "function g(v) { x = v; }"
1000 "f(10); x",
1001 EXPECT_RESULT, Number::New(CcTest::isolate(), 10));
1002 context.Check(
1003 "'use strict';"
1004 "let x = 5;"
1005 "f(7); x",
1006 EXPECT_RESULT, Number::New(CcTest::isolate(), 7));
1007 context.Check("global.x", EXPECT_RESULT,
1008 Number::New(CcTest::isolate(), 10));
1009 for (int k = 0; k < 3; k++) {
1010 context.Check("g(31); x", EXPECT_RESULT,
1011 Number::New(CcTest::isolate(), 31));
1012 }
1013 context.Check("global.x", EXPECT_RESULT,
1014 Number::New(CcTest::isolate(), 10));
1015 for (int k = 0; k < 3; k++) {
1016 context.Check("f(32); x", EXPECT_RESULT,
1017 Number::New(CcTest::isolate(), 32));
1018 }
1019 context.Check("global.x", EXPECT_RESULT,
1020 Number::New(CcTest::isolate(), 10));
1021 context.Check("%OptimizeFunctionOnNextCall(g); g(18); x", EXPECT_RESULT,
1022 Number::New(CcTest::isolate(), 18));
1023 context.Check("global.x", EXPECT_RESULT,
1024 Number::New(CcTest::isolate(), 10));
1025 context.Check("%OptimizeFunctionOnNextCall(f); f(33); x", EXPECT_RESULT,
1026 Number::New(CcTest::isolate(), 33));
1027 context.Check("global.x", EXPECT_RESULT,
1028 Number::New(CcTest::isolate(), 10));
1029 }
1030 {
1031 SimpleContext context;
1032 context.Check(
1033 "var global = this;"
1034 "x = 15;"
1035 "function f(v) { x = v; }"
1036 "f(10); x",
1037 EXPECT_RESULT, Number::New(CcTest::isolate(), 10));
1038 for (int k = 0; k < 3; k++) {
1039 context.Check("f(18); x", EXPECT_RESULT,
1040 Number::New(CcTest::isolate(), 18));
1041 }
1042 context.Check("%OptimizeFunctionOnNextCall(f); f(20); x", EXPECT_RESULT,
1043 Number::New(CcTest::isolate(), 20));
1044 context.Check(
1045 "'use strict';"
1046 "let x = 5;"
1047 "f(8); x",
1048 EXPECT_RESULT, Number::New(CcTest::isolate(), 8));
1049 context.Check("global.x", EXPECT_RESULT,
1050 Number::New(CcTest::isolate(), 20));
1051 for (int k = 0; k < 3; k++) {
1052 context.Check("f(13); x", EXPECT_RESULT,
1053 Number::New(CcTest::isolate(), 13));
1054 }
1055 context.Check("global.x", EXPECT_RESULT,
1056 Number::New(CcTest::isolate(), 20));
1057 context.Check("%OptimizeFunctionOnNextCall(f); f(41); x", EXPECT_RESULT,
1058 Number::New(CcTest::isolate(), 41));
1059 context.Check("global.x", EXPECT_RESULT,
1060 Number::New(CcTest::isolate(), 20));
1061 }
1062}
1063
1064
1065TEST(CrossScriptAssignmentToConst) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001066 i::FLAG_allow_natives_syntax = true;
1067
1068 HandleScope handle_scope(CcTest::isolate());
1069
1070 {
1071 SimpleContext context;
1072
1073 context.Check("function f() { x = 27; }", EXPECT_RESULT,
1074 Undefined(CcTest::isolate()));
1075 context.Check("'use strict';const x = 1; x", EXPECT_RESULT,
1076 Number::New(CcTest::isolate(), 1));
1077 context.Check("f();", EXPECT_EXCEPTION);
1078 context.Check("x", EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
1079 context.Check("f();", EXPECT_EXCEPTION);
1080 context.Check("x", EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
1081 context.Check("%OptimizeFunctionOnNextCall(f);f();", EXPECT_EXCEPTION);
1082 context.Check("x", EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
1083 }
1084}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001085
1086
1087TEST(Regress425510) {
1088 i::FLAG_allow_natives_syntax = true;
1089
1090 HandleScope handle_scope(CcTest::isolate());
1091
1092 {
1093 SimpleContext context;
1094
1095 context.Check("'use strict'; o; const o = 10", EXPECT_EXCEPTION);
1096
1097 for (int i = 0; i < 100; i++) {
1098 context.Check("o.prototype", EXPECT_EXCEPTION);
1099 }
1100 }
1101}
1102
1103
1104TEST(Regress3941) {
1105 i::FLAG_allow_natives_syntax = true;
1106
1107 HandleScope handle_scope(CcTest::isolate());
1108
1109 {
1110 SimpleContext context;
1111 context.Check("function f() { x = 1; }", EXPECT_RESULT,
1112 Undefined(CcTest::isolate()));
1113 context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);
1114 }
1115
1116
1117 {
1118 // Train ICs.
1119 SimpleContext context;
1120 context.Check("function f() { x = 1; }", EXPECT_RESULT,
1121 Undefined(CcTest::isolate()));
1122 for (int i = 0; i < 4; i++) {
1123 context.Check("f(); x", EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
1124 }
1125 context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);
1126 }
1127
1128
1129 {
1130 // Optimize.
1131 SimpleContext context;
1132 context.Check("function f() { x = 1; }", EXPECT_RESULT,
1133 Undefined(CcTest::isolate()));
1134 for (int i = 0; i < 4; i++) {
1135 context.Check("f(); x", EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
1136 }
1137 context.Check("%OptimizeFunctionOnNextCall(f); f(); x", EXPECT_RESULT,
1138 Number::New(CcTest::isolate(), 1));
1139
1140 context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);
1141 }
1142}
1143
1144
1145TEST(Regress3941_Reads) {
1146 i::FLAG_allow_natives_syntax = true;
1147
1148 HandleScope handle_scope(CcTest::isolate());
1149
1150 {
1151 SimpleContext context;
1152 context.Check("function f() { return x; }", EXPECT_RESULT,
1153 Undefined(CcTest::isolate()));
1154 context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);
1155 }
1156
1157
1158 {
1159 // Train ICs.
1160 SimpleContext context;
1161 context.Check("function f() { return x; }", EXPECT_RESULT,
1162 Undefined(CcTest::isolate()));
1163 for (int i = 0; i < 4; i++) {
1164 context.Check("f()", EXPECT_EXCEPTION);
1165 }
1166 context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);
1167 }
1168
1169
1170 {
1171 // Optimize.
1172 SimpleContext context;
1173 context.Check("function f() { return x; }", EXPECT_RESULT,
1174 Undefined(CcTest::isolate()));
1175 for (int i = 0; i < 4; i++) {
1176 context.Check("f()", EXPECT_EXCEPTION);
1177 }
1178 context.Check("%OptimizeFunctionOnNextCall(f);", EXPECT_RESULT,
1179 Undefined(CcTest::isolate()));
1180
1181 context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);
1182 }
1183}