The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / test / cctest / test-decls.cc @ f230a1cf

History | View | Annotate | Download (24.7 KB)

1
// Copyright 2007-2008 the V8 project authors. All rights reserved.
2
// Redistribution and use in source and binary forms, with or without
3
// modification, are permitted provided that the following conditions are
4
// met:
5
//
6
//     * Redistributions of source code must retain the above copyright
7
//       notice, this list of conditions and the following disclaimer.
8
//     * Redistributions in binary form must reproduce the above
9
//       copyright notice, this list of conditions and the following
10
//       disclaimer in the documentation and/or other materials provided
11
//       with the distribution.
12
//     * Neither the name of Google Inc. nor the names of its
13
//       contributors may be used to endorse or promote products derived
14
//       from this software without specific prior written permission.
15
//
16
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27

    
28
#include <stdlib.h>
29

    
30
#include "v8.h"
31

    
32
#include "heap.h"
33
#include "cctest.h"
34

    
35
using namespace v8;
36

    
37

    
38
enum Expectations {
39
  EXPECT_RESULT,
40
  EXPECT_EXCEPTION,
41
  EXPECT_ERROR
42
};
43

    
44

    
45
// A DeclarationContext holds a reference to a v8::Context and keeps
46
// track of various declaration related counters to make it easier to
47
// track if global declarations in the presence of interceptors behave
48
// the right way.
49
class DeclarationContext {
50
 public:
51
  DeclarationContext();
52

    
53
  virtual ~DeclarationContext() {
54
    if (is_initialized_) {
55
      Isolate* isolate = CcTest::isolate();
56
      HandleScope scope(isolate);
57
      Local<Context> context = Local<Context>::New(isolate, context_);
58
      context->Exit();
59
      context_.Dispose();
60
    }
61
  }
62

    
63
  void Check(const char* source,
64
             int get, int set, int has,
65
             Expectations expectations,
66
             v8::Handle<Value> value = Local<Value>());
67

    
68
  int get_count() const { return get_count_; }
69
  int set_count() const { return set_count_; }
70
  int query_count() const { return query_count_; }
71

    
72
 protected:
73
  virtual v8::Handle<Value> Get(Local<String> key);
74
  virtual v8::Handle<Value> Set(Local<String> key, Local<Value> value);
75
  virtual v8::Handle<Integer> Query(Local<String> key);
76

    
77
  void InitializeIfNeeded();
78

    
79
  // Perform optional initialization steps on the context after it has
80
  // been created. Defaults to none but may be overwritten.
81
  virtual void PostInitializeContext(Handle<Context> context) {}
82

    
83
  // Get the holder for the interceptor. Default to the instance template
84
  // but may be overwritten.
85
  virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
86
    return function->InstanceTemplate();
87
  }
88

    
89
  // The handlers are called as static functions that forward
90
  // to the instance specific virtual methods.
91
  static void HandleGet(Local<String> key,
92
                        const v8::PropertyCallbackInfo<v8::Value>& info);
93
  static void HandleSet(Local<String> key,
94
                        Local<Value> value,
95
                        const v8::PropertyCallbackInfo<v8::Value>& info);
96
  static void HandleQuery(Local<String> key,
97
                          const v8::PropertyCallbackInfo<v8::Integer>& info);
98

    
99
 private:
100
  bool is_initialized_;
101
  Persistent<Context> context_;
102

    
103
  int get_count_;
104
  int set_count_;
105
  int query_count_;
106

    
107
  static DeclarationContext* GetInstance(Local<Value> data);
108
};
109

    
110

    
111
DeclarationContext::DeclarationContext()
112
    : is_initialized_(false), get_count_(0), set_count_(0), query_count_(0) {
113
  // Do nothing.
114
}
115

    
116

    
117
void DeclarationContext::InitializeIfNeeded() {
118
  if (is_initialized_) return;
119
  Isolate* isolate = CcTest::isolate();
120
  HandleScope scope(isolate);
121
  Local<FunctionTemplate> function = FunctionTemplate::New();
122
  Local<Value> data = External::New(this);
123
  GetHolder(function)->SetNamedPropertyHandler(&HandleGet,
124
                                               &HandleSet,
125
                                               &HandleQuery,
126
                                               0, 0,
127
                                               data);
128
  Local<Context> context = Context::New(isolate,
129
                                        0,
130
                                        function->InstanceTemplate(),
131
                                        Local<Value>());
132
  context_.Reset(isolate, context);
133
  context->Enter();
134
  is_initialized_ = true;
135
  PostInitializeContext(context);
136
}
137

    
138

    
139
void DeclarationContext::Check(const char* source,
140
                               int get, int set, int query,
141
                               Expectations expectations,
142
                               v8::Handle<Value> value) {
143
  InitializeIfNeeded();
144
  // A retry after a GC may pollute the counts, so perform gc now
145
  // to avoid that.
146
  CcTest::heap()->CollectGarbage(v8::internal::NEW_SPACE);
147
  HandleScope scope(CcTest::isolate());
148
  TryCatch catcher;
149
  catcher.SetVerbose(true);
150
  Local<Script> script = Script::Compile(String::New(source));
151
  if (expectations == EXPECT_ERROR) {
152
    CHECK(script.IsEmpty());
153
    return;
154
  }
155
  CHECK(!script.IsEmpty());
156
  Local<Value> result = script->Run();
157
  CHECK_EQ(get, get_count());
158
  CHECK_EQ(set, set_count());
159
  CHECK_EQ(query, query_count());
160
  if (expectations == EXPECT_RESULT) {
161
    CHECK(!catcher.HasCaught());
162
    if (!value.IsEmpty()) {
163
      CHECK_EQ(value, result);
164
    }
165
  } else {
166
    CHECK(expectations == EXPECT_EXCEPTION);
167
    CHECK(catcher.HasCaught());
168
    if (!value.IsEmpty()) {
169
      CHECK_EQ(value, catcher.Exception());
170
    }
171
  }
172
  // Clean slate for the next test.
173
  CcTest::heap()->CollectAllAvailableGarbage();
174
}
175

    
176

    
177
void DeclarationContext::HandleGet(
178
    Local<String> key,
179
    const v8::PropertyCallbackInfo<v8::Value>& info) {
180
  DeclarationContext* context = GetInstance(info.Data());
181
  context->get_count_++;
182
  info.GetReturnValue().Set(context->Get(key));
183
}
184

    
185

    
186
void DeclarationContext::HandleSet(
187
    Local<String> key,
188
    Local<Value> value,
189
    const v8::PropertyCallbackInfo<v8::Value>& info) {
190
  DeclarationContext* context = GetInstance(info.Data());
191
  context->set_count_++;
192
  info.GetReturnValue().Set(context->Set(key, value));
193
}
194

    
195

    
196
void DeclarationContext::HandleQuery(
197
    Local<String> key,
198
    const v8::PropertyCallbackInfo<v8::Integer>& info) {
199
  DeclarationContext* context = GetInstance(info.Data());
200
  context->query_count_++;
201
  info.GetReturnValue().Set(context->Query(key));
202
}
203

    
204

    
205
DeclarationContext* DeclarationContext::GetInstance(Local<Value> data) {
206
  void* value = Local<External>::Cast(data)->Value();
207
  return static_cast<DeclarationContext*>(value);
208
}
209

    
210

    
211
v8::Handle<Value> DeclarationContext::Get(Local<String> key) {
212
  return v8::Handle<Value>();
213
}
214

    
215

    
216
v8::Handle<Value> DeclarationContext::Set(Local<String> key,
217
                                          Local<Value> value) {
218
  return v8::Handle<Value>();
219
}
220

    
221

    
222
v8::Handle<Integer> DeclarationContext::Query(Local<String> key) {
223
  return v8::Handle<Integer>();
224
}
225

    
226

    
227
// Test global declaration of a property the interceptor doesn't know
228
// about and doesn't handle.
229
TEST(Unknown) {
230
  HandleScope scope(CcTest::isolate());
231
  v8::V8::Initialize();
232

    
233
  { DeclarationContext context;
234
    context.Check("var x; x",
235
                  1,  // access
236
                  1,  // declaration
237
                  2,  // declaration + initialization
238
                  EXPECT_RESULT, Undefined(CcTest::isolate()));
239
  }
240

    
241
  { DeclarationContext context;
242
    context.Check("var x = 0; x",
243
                  1,  // access
244
                  2,  // declaration + initialization
245
                  2,  // declaration + initialization
246
                  EXPECT_RESULT, Number::New(0));
247
  }
248

    
249
  { DeclarationContext context;
250
    context.Check("function x() { }; x",
251
                  1,  // access
252
                  0,
253
                  0,
254
                  EXPECT_RESULT);
255
  }
256

    
257
  { DeclarationContext context;
258
    context.Check("const x; x",
259
                  1,  // access
260
                  2,  // declaration + initialization
261
                  1,  // declaration
262
                  EXPECT_RESULT, Undefined(CcTest::isolate()));
263
  }
264

    
265
  { DeclarationContext context;
266
    // SB 0 - BUG 1213579
267
    context.Check("const x = 0; x",
268
                  1,  // access
269
                  2,  // declaration + initialization
270
                  1,  // declaration
271
                  EXPECT_RESULT, Undefined(CcTest::isolate()));
272
  }
273
}
274

    
275

    
276

    
277
class PresentPropertyContext: public DeclarationContext {
278
 protected:
279
  virtual v8::Handle<Integer> Query(Local<String> key) {
280
    return Integer::New(v8::None);
281
  }
282
};
283

    
284

    
285

    
286
TEST(Present) {
287
  HandleScope scope(CcTest::isolate());
288

    
289
  { PresentPropertyContext context;
290
    context.Check("var x; x",
291
                  1,  // access
292
                  0,
293
                  2,  // declaration + initialization
294
                  EXPECT_EXCEPTION);  // x is not defined!
295
  }
296

    
297
  { PresentPropertyContext context;
298
    context.Check("var x = 0; x",
299
                  1,  // access
300
                  1,  // initialization
301
                  2,  // declaration + initialization
302
                  EXPECT_RESULT, Number::New(0));
303
  }
304

    
305
  { PresentPropertyContext context;
306
    context.Check("function x() { }; x",
307
                  1,  // access
308
                  0,
309
                  0,
310
                  EXPECT_RESULT);
311
  }
312

    
313
  { PresentPropertyContext context;
314
    context.Check("const x; x",
315
                  1,  // access
316
                  1,  // initialization
317
                  1,  // (re-)declaration
318
                  EXPECT_RESULT, Undefined(CcTest::isolate()));
319
  }
320

    
321
  { PresentPropertyContext context;
322
    context.Check("const x = 0; x",
323
                  1,  // access
324
                  1,  // initialization
325
                  1,  // (re-)declaration
326
                  EXPECT_RESULT, Number::New(0));
327
  }
328
}
329

    
330

    
331

    
332
class AbsentPropertyContext: public DeclarationContext {
333
 protected:
334
  virtual v8::Handle<Integer> Query(Local<String> key) {
335
    return v8::Handle<Integer>();
336
  }
337
};
338

    
339

    
340
TEST(Absent) {
341
  v8::Isolate* isolate = CcTest::isolate();
342
  v8::V8::Initialize();
343
  HandleScope scope(isolate);
344

    
345
  { AbsentPropertyContext context;
346
    context.Check("var x; x",
347
                  1,  // access
348
                  1,  // declaration
349
                  2,  // declaration + initialization
350
                  EXPECT_RESULT, Undefined(isolate));
351
  }
352

    
353
  { AbsentPropertyContext context;
354
    context.Check("var x = 0; x",
355
                  1,  // access
356
                  2,  // declaration + initialization
357
                  2,  // declaration + initialization
358
                  EXPECT_RESULT, Number::New(0));
359
  }
360

    
361
  { AbsentPropertyContext context;
362
    context.Check("function x() { }; x",
363
                  1,  // access
364
                  0,
365
                  0,
366
                  EXPECT_RESULT);
367
  }
368

    
369
  { AbsentPropertyContext context;
370
    context.Check("const x; x",
371
                  1,  // access
372
                  2,  // declaration + initialization
373
                  1,  // declaration
374
                  EXPECT_RESULT, Undefined(isolate));
375
  }
376

    
377
  { AbsentPropertyContext context;
378
    context.Check("const x = 0; x",
379
                  1,  // access
380
                  2,  // declaration + initialization
381
                  1,  // declaration
382
                  EXPECT_RESULT, Undefined(isolate));  // SB 0 - BUG 1213579
383
  }
384

    
385
  { AbsentPropertyContext context;
386
    context.Check("if (false) { var x = 0 }; x",
387
                  1,  // access
388
                  1,  // declaration
389
                  1,  // declaration + initialization
390
                  EXPECT_RESULT, Undefined(isolate));
391
  }
392
}
393

    
394

    
395

    
396
class AppearingPropertyContext: public DeclarationContext {
397
 public:
398
  enum State {
399
    DECLARE,
400
    INITIALIZE_IF_ASSIGN,
401
    UNKNOWN
402
  };
403

    
404
  AppearingPropertyContext() : state_(DECLARE) { }
405

    
406
 protected:
407
  virtual v8::Handle<Integer> Query(Local<String> key) {
408
    switch (state_) {
409
      case DECLARE:
410
        // Force declaration by returning that the
411
        // property is absent.
412
        state_ = INITIALIZE_IF_ASSIGN;
413
        return Handle<Integer>();
414
      case INITIALIZE_IF_ASSIGN:
415
        // Return that the property is present so we only get the
416
        // setter called when initializing with a value.
417
        state_ = UNKNOWN;
418
        return Integer::New(v8::None);
419
      default:
420
        CHECK(state_ == UNKNOWN);
421
        break;
422
    }
423
    // Do the lookup in the object.
424
    return v8::Handle<Integer>();
425
  }
426

    
427
 private:
428
  State state_;
429
};
430

    
431

    
432
TEST(Appearing) {
433
  v8::V8::Initialize();
434
  HandleScope scope(CcTest::isolate());
435

    
436
  { AppearingPropertyContext context;
437
    context.Check("var x; x",
438
                  1,  // access
439
                  1,  // declaration
440
                  2,  // declaration + initialization
441
                  EXPECT_RESULT, Undefined(CcTest::isolate()));
442
  }
443

    
444
  { AppearingPropertyContext context;
445
    context.Check("var x = 0; x",
446
                  1,  // access
447
                  2,  // declaration + initialization
448
                  2,  // declaration + initialization
449
                  EXPECT_RESULT, Number::New(0));
450
  }
451

    
452
  { AppearingPropertyContext context;
453
    context.Check("function x() { }; x",
454
                  1,  // access
455
                  0,
456
                  0,
457
                  EXPECT_RESULT);
458
  }
459

    
460
  { AppearingPropertyContext context;
461
    context.Check("const x; x",
462
                  1,  // access
463
                  2,  // declaration + initialization
464
                  1,  // declaration
465
                  EXPECT_RESULT, Undefined(CcTest::isolate()));
466
  }
467

    
468
  { AppearingPropertyContext context;
469
    context.Check("const x = 0; x",
470
                  1,  // access
471
                  2,  // declaration + initialization
472
                  1,  // declaration
473
                  EXPECT_RESULT, Undefined(CcTest::isolate()));
474
                  // Result is undefined because declaration succeeded but
475
                  // initialization to 0 failed (due to context behavior).
476
  }
477
}
478

    
479

    
480

    
481
class ReappearingPropertyContext: public DeclarationContext {
482
 public:
483
  enum State {
484
    DECLARE,
485
    DONT_DECLARE,
486
    INITIALIZE,
487
    UNKNOWN
488
  };
489

    
490
  ReappearingPropertyContext() : state_(DECLARE) { }
491

    
492
 protected:
493
  virtual v8::Handle<Integer> Query(Local<String> key) {
494
    switch (state_) {
495
      case DECLARE:
496
        // Force the first declaration by returning that
497
        // the property is absent.
498
        state_ = DONT_DECLARE;
499
        return Handle<Integer>();
500
      case DONT_DECLARE:
501
        // Ignore the second declaration by returning
502
        // that the property is already there.
503
        state_ = INITIALIZE;
504
        return Integer::New(v8::None);
505
      case INITIALIZE:
506
        // Force an initialization by returning that
507
        // the property is absent. This will make sure
508
        // that the setter is called and it will not
509
        // lead to redeclaration conflicts (yet).
510
        state_ = UNKNOWN;
511
        return Handle<Integer>();
512
      default:
513
        CHECK(state_ == UNKNOWN);
514
        break;
515
    }
516
    // Do the lookup in the object.
517
    return Handle<Integer>();
518
  }
519

    
520
 private:
521
  State state_;
522
};
523

    
524

    
525
TEST(Reappearing) {
526
  v8::V8::Initialize();
527
  HandleScope scope(CcTest::isolate());
528

    
529
  { ReappearingPropertyContext context;
530
    context.Check("const x; var x = 0",
531
                  0,
532
                  3,  // const declaration+initialization, var initialization
533
                  3,  // 2 x declaration + var initialization
534
                  EXPECT_RESULT, Undefined(CcTest::isolate()));
535
  }
536
}
537

    
538

    
539

    
540
class ExistsInPrototypeContext: public DeclarationContext {
541
 protected:
542
  virtual v8::Handle<Integer> Query(Local<String> key) {
543
    // Let it seem that the property exists in the prototype object.
544
    return Integer::New(v8::None);
545
  }
546

    
547
  // Use the prototype as the holder for the interceptors.
548
  virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
549
    return function->PrototypeTemplate();
550
  }
551
};
552

    
553

    
554
TEST(ExistsInPrototype) {
555
  i::FLAG_es52_globals = true;
556
  HandleScope scope(CcTest::isolate());
557

    
558
  // Sanity check to make sure that the holder of the interceptor
559
  // really is the prototype object.
560
  { ExistsInPrototypeContext context;
561
    context.Check("this.x = 87; this.x",
562
                  0,
563
                  0,
564
                  0,
565
                  EXPECT_RESULT, Number::New(87));
566
  }
567

    
568
  { ExistsInPrototypeContext context;
569
    context.Check("var x; x",
570
                  0,
571
                  0,
572
                  0,
573
                  EXPECT_RESULT, Undefined(CcTest::isolate()));
574
  }
575

    
576
  { ExistsInPrototypeContext context;
577
    context.Check("var x = 0; x",
578
                  0,
579
                  0,
580
                  0,
581
                  EXPECT_RESULT, Number::New(0));
582
  }
583

    
584
  { ExistsInPrototypeContext context;
585
    context.Check("const x; x",
586
                  0,
587
                  0,
588
                  0,
589
                  EXPECT_RESULT, Undefined(CcTest::isolate()));
590
  }
591

    
592
  { ExistsInPrototypeContext context;
593
    context.Check("const x = 0; x",
594
                  0,
595
                  0,
596
                  0,
597
                  EXPECT_RESULT, Number::New(0));
598
  }
599
}
600

    
601

    
602

    
603
class AbsentInPrototypeContext: public DeclarationContext {
604
 protected:
605
  virtual v8::Handle<Integer> Query(Local<String> key) {
606
    // Let it seem that the property is absent in the prototype object.
607
    return Handle<Integer>();
608
  }
609

    
610
  // Use the prototype as the holder for the interceptors.
611
  virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
612
    return function->PrototypeTemplate();
613
  }
614
};
615

    
616

    
617
TEST(AbsentInPrototype) {
618
  i::FLAG_es52_globals = true;
619
  v8::V8::Initialize();
620
  HandleScope scope(CcTest::isolate());
621

    
622
  { AbsentInPrototypeContext context;
623
    context.Check("if (false) { var x = 0; }; x",
624
                  0,
625
                  0,
626
                  0,
627
                  EXPECT_RESULT, Undefined(CcTest::isolate()));
628
  }
629
}
630

    
631

    
632

    
633
class ExistsInHiddenPrototypeContext: public DeclarationContext {
634
 public:
635
  ExistsInHiddenPrototypeContext() {
636
    hidden_proto_ = FunctionTemplate::New();
637
    hidden_proto_->SetHiddenPrototype(true);
638
  }
639

    
640
 protected:
641
  virtual v8::Handle<Integer> Query(Local<String> key) {
642
    // Let it seem that the property exists in the hidden prototype object.
643
    return Integer::New(v8::None);
644
  }
645

    
646
  // Install the hidden prototype after the global object has been created.
647
  virtual void PostInitializeContext(Handle<Context> context) {
648
    Local<Object> global_object = context->Global();
649
    Local<Object> hidden_proto = hidden_proto_->GetFunction()->NewInstance();
650
    context->DetachGlobal();
651
    context->Global()->SetPrototype(hidden_proto);
652
    context->ReattachGlobal(global_object);
653
  }
654

    
655
  // Use the hidden prototype as the holder for the interceptors.
656
  virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
657
    return hidden_proto_->InstanceTemplate();
658
  }
659

    
660
 private:
661
  Local<FunctionTemplate> hidden_proto_;
662
};
663

    
664

    
665
TEST(ExistsInHiddenPrototype) {
666
  i::FLAG_es52_globals = true;
667
  HandleScope scope(CcTest::isolate());
668

    
669
  { ExistsInHiddenPrototypeContext context;
670
    context.Check("var x; x",
671
                  1,  // access
672
                  0,
673
                  2,  // declaration + initialization
674
                  EXPECT_EXCEPTION);  // x is not defined!
675
  }
676

    
677
  { ExistsInHiddenPrototypeContext context;
678
    context.Check("var x = 0; x",
679
                  1,  // access
680
                  1,  // initialization
681
                  2,  // declaration + initialization
682
                  EXPECT_RESULT, Number::New(0));
683
  }
684

    
685
  { ExistsInHiddenPrototypeContext context;
686
    context.Check("function x() { }; x",
687
                  0,
688
                  0,
689
                  0,
690
                  EXPECT_RESULT);
691
  }
692

    
693
  // TODO(mstarzinger): The semantics of global const is vague.
694
  { ExistsInHiddenPrototypeContext context;
695
    context.Check("const x; x",
696
                  0,
697
                  0,
698
                  1,  // (re-)declaration
699
                  EXPECT_RESULT, Undefined(CcTest::isolate()));
700
  }
701

    
702
  // TODO(mstarzinger): The semantics of global const is vague.
703
  { ExistsInHiddenPrototypeContext context;
704
    context.Check("const x = 0; x",
705
                  0,
706
                  0,
707
                  1,  // (re-)declaration
708
                  EXPECT_RESULT, Number::New(0));
709
  }
710
}
711

    
712

    
713

    
714
class SimpleContext {
715
 public:
716
  SimpleContext()
717
      : handle_scope_(CcTest::isolate()),
718
        context_(Context::New(CcTest::isolate())) {
719
    context_->Enter();
720
  }
721

    
722
  ~SimpleContext() {
723
    context_->Exit();
724
  }
725

    
726
  void Check(const char* source,
727
             Expectations expectations,
728
             v8::Handle<Value> value = Local<Value>()) {
729
    HandleScope scope(context_->GetIsolate());
730
    TryCatch catcher;
731
    catcher.SetVerbose(true);
732
    Local<Script> script = Script::Compile(String::New(source));
733
    if (expectations == EXPECT_ERROR) {
734
      CHECK(script.IsEmpty());
735
      return;
736
    }
737
    CHECK(!script.IsEmpty());
738
    Local<Value> result = script->Run();
739
    if (expectations == EXPECT_RESULT) {
740
      CHECK(!catcher.HasCaught());
741
      if (!value.IsEmpty()) {
742
        CHECK_EQ(value, result);
743
      }
744
    } else {
745
      CHECK(expectations == EXPECT_EXCEPTION);
746
      CHECK(catcher.HasCaught());
747
      if (!value.IsEmpty()) {
748
        CHECK_EQ(value, catcher.Exception());
749
      }
750
    }
751
  }
752

    
753
 private:
754
  HandleScope handle_scope_;
755
  Local<Context> context_;
756
};
757

    
758

    
759
TEST(CrossScriptReferences) {
760
  HandleScope scope(CcTest::isolate());
761

    
762
  { SimpleContext context;
763
    context.Check("var x = 1; x",
764
                  EXPECT_RESULT, Number::New(1));
765
    context.Check("var x = 2; x",
766
                  EXPECT_RESULT, Number::New(2));
767
    context.Check("const x = 3; x",
768
                  EXPECT_RESULT, Number::New(3));
769
    context.Check("const x = 4; x",
770
                  EXPECT_RESULT, Number::New(4));
771
    context.Check("x = 5; x",
772
                  EXPECT_RESULT, Number::New(5));
773
    context.Check("var x = 6; x",
774
                  EXPECT_RESULT, Number::New(6));
775
    context.Check("this.x",
776
                  EXPECT_RESULT, Number::New(6));
777
    context.Check("function x() { return 7 }; x()",
778
                  EXPECT_RESULT, Number::New(7));
779
  }
780

    
781
  { SimpleContext context;
782
    context.Check("const x = 1; x",
783
                  EXPECT_RESULT, Number::New(1));
784
    context.Check("var x = 2; x",  // assignment ignored
785
                  EXPECT_RESULT, Number::New(1));
786
    context.Check("const x = 3; x",
787
                  EXPECT_RESULT, Number::New(1));
788
    context.Check("x = 4; x",  // assignment ignored
789
                  EXPECT_RESULT, Number::New(1));
790
    context.Check("var x = 5; x",  // assignment ignored
791
                  EXPECT_RESULT, Number::New(1));
792
    context.Check("this.x",
793
                  EXPECT_RESULT, Number::New(1));
794
    context.Check("function x() { return 7 }; x",
795
                  EXPECT_EXCEPTION);
796
  }
797
}
798

    
799

    
800
TEST(CrossScriptReferencesHarmony) {
801
  i::FLAG_use_strict = true;
802
  i::FLAG_harmony_scoping = true;
803
  i::FLAG_harmony_modules = true;
804

    
805
  HandleScope scope(CcTest::isolate());
806

    
807
  const char* decs[] = {
808
    "var x = 1; x", "x", "this.x",
809
    "function x() { return 1 }; x()", "x()", "this.x()",
810
    "let x = 1; x", "x", "this.x",
811
    "const x = 1; x", "x", "this.x",
812
    "module x { export let a = 1 }; x.a", "x.a", "this.x.a",
813
    NULL
814
  };
815

    
816
  for (int i = 0; decs[i] != NULL; i += 3) {
817
    SimpleContext context;
818
    context.Check(decs[i], EXPECT_RESULT, Number::New(1));
819
    context.Check(decs[i+1], EXPECT_RESULT, Number::New(1));
820
    // TODO(rossberg): The current ES6 draft spec does not reflect lexical
821
    // bindings on the global object. However, this will probably change, in
822
    // which case we reactivate the following test.
823
    if (i/3 < 2) context.Check(decs[i+2], EXPECT_RESULT, Number::New(1));
824
  }
825
}
826

    
827

    
828
TEST(CrossScriptConflicts) {
829
  i::FLAG_use_strict = true;
830
  i::FLAG_harmony_scoping = true;
831
  i::FLAG_harmony_modules = true;
832

    
833
  HandleScope scope(CcTest::isolate());
834

    
835
  const char* firsts[] = {
836
    "var x = 1; x",
837
    "function x() { return 1 }; x()",
838
    "let x = 1; x",
839
    "const x = 1; x",
840
    "module x { export let a = 1 }; x.a",
841
    NULL
842
  };
843
  const char* seconds[] = {
844
    "var x = 2; x",
845
    "function x() { return 2 }; x()",
846
    "let x = 2; x",
847
    "const x = 2; x",
848
    "module x { export let a = 2 }; x.a",
849
    NULL
850
  };
851

    
852
  for (int i = 0; firsts[i] != NULL; ++i) {
853
    for (int j = 0; seconds[j] != NULL; ++j) {
854
      SimpleContext context;
855
      context.Check(firsts[i], EXPECT_RESULT, Number::New(1));
856
      // TODO(rossberg): All tests should actually be errors in Harmony,
857
      // but we currently do not detect the cases where the first declaration
858
      // is not lexical.
859
      context.Check(seconds[j],
860
                    i < 2 ? EXPECT_RESULT : EXPECT_ERROR, Number::New(2));
861
    }
862
  }
863
}