v8  3.11.10(node0.8.26)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
test-decls.cc
Go to the documentation of this file.
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 
41 };
42 
43 
44 // A DeclarationContext holds a reference to a v8::Context and keeps
45 // track of various declaration related counters to make it easier to
46 // track if global declarations in the presence of interceptors behave
47 // the right way.
49  public:
51 
52  virtual ~DeclarationContext() {
53  if (is_initialized_) {
54  context_->Exit();
55  context_.Dispose();
56  }
57  }
58 
59  void Check(const char* source,
60  int get, int set, int has,
61  Expectations expectations,
63 
64  int get_count() const { return get_count_; }
65  int set_count() const { return set_count_; }
66  int query_count() const { return query_count_; }
67 
68  protected:
69  virtual v8::Handle<Value> Get(Local<String> key);
70  virtual v8::Handle<Value> Set(Local<String> key, Local<Value> value);
71  virtual v8::Handle<Integer> Query(Local<String> key);
72 
73  void InitializeIfNeeded();
74 
75  // Get the holder for the interceptor. Default to the instance template
76  // but may be overwritten.
78  return function->InstanceTemplate();
79  }
80 
81  // The handlers are called as static functions that forward
82  // to the instance specific virtual methods.
83  static v8::Handle<Value> HandleGet(Local<String> key,
84  const AccessorInfo& info);
85  static v8::Handle<Value> HandleSet(Local<String> key,
86  Local<Value> value,
87  const AccessorInfo& info);
88  static v8::Handle<Integer> HandleQuery(Local<String> key,
89  const AccessorInfo& info);
90 
91  private:
92  bool is_initialized_;
93  Persistent<Context> context_;
94  Local<String> property_;
95 
96  int get_count_;
97  int set_count_;
98  int query_count_;
99 
100  static DeclarationContext* GetInstance(const AccessorInfo& info);
101 };
102 
103 
105  : is_initialized_(false), get_count_(0), set_count_(0), query_count_(0) {
106  // Do nothing.
107 }
108 
109 
111  if (is_initialized_) return;
112  HandleScope scope;
113  Local<FunctionTemplate> function = FunctionTemplate::New();
114  Local<Value> data = External::New(this);
115  GetHolder(function)->SetNamedPropertyHandler(&HandleGet,
116  &HandleSet,
117  &HandleQuery,
118  0, 0,
119  data);
120  context_ = Context::New(0, function->InstanceTemplate(), Local<Value>());
121  context_->Enter();
122  is_initialized_ = true;
123 }
124 
125 
126 void DeclarationContext::Check(const char* source,
127  int get, int set, int query,
128  Expectations expectations,
129  v8::Handle<Value> value) {
131  // A retry after a GC may pollute the counts, so perform gc now
132  // to avoid that.
133  HEAP->CollectGarbage(v8::internal::NEW_SPACE);
134  HandleScope scope;
135  TryCatch catcher;
136  catcher.SetVerbose(true);
137  Local<Value> result = Script::Compile(String::New(source))->Run();
138  CHECK_EQ(get, get_count());
139  CHECK_EQ(set, set_count());
140  CHECK_EQ(query, query_count());
141  if (expectations == EXPECT_RESULT) {
142  CHECK(!catcher.HasCaught());
143  if (!value.IsEmpty()) {
144  CHECK_EQ(value, result);
145  }
146  } else {
147  CHECK(expectations == EXPECT_EXCEPTION);
148  CHECK(catcher.HasCaught());
149  if (!value.IsEmpty()) {
150  CHECK_EQ(value, catcher.Exception());
151  }
152  }
153 }
154 
155 
157  const AccessorInfo& info) {
158  DeclarationContext* context = GetInstance(info);
159  context->get_count_++;
160  return context->Get(key);
161 }
162 
163 
165  Local<Value> value,
166  const AccessorInfo& info) {
167  DeclarationContext* context = GetInstance(info);
168  context->set_count_++;
169  return context->Set(key, value);
170 }
171 
172 
174  const AccessorInfo& info) {
175  DeclarationContext* context = GetInstance(info);
176  context->query_count_++;
177  return context->Query(key);
178 }
179 
180 
181 DeclarationContext* DeclarationContext::GetInstance(const AccessorInfo& info) {
182  return static_cast<DeclarationContext*>(External::Unwrap(info.Data()));
183 }
184 
185 
187  return v8::Handle<Value>();
188 }
189 
190 
192  Local<Value> value) {
193  return v8::Handle<Value>();
194 }
195 
196 
198  return v8::Handle<Integer>();
199 }
200 
201 
202 // Test global declaration of a property the interceptor doesn't know
203 // about and doesn't handle.
204 TEST(Unknown) {
205  HandleScope scope;
206 
207  { DeclarationContext context;
208  context.Check("var x; x",
209  1, // access
210  1, // declaration
211  2, // declaration + initialization
213  }
214 
215  { DeclarationContext context;
216  context.Check("var x = 0; x",
217  1, // access
218  2, // declaration + initialization
219  2, // declaration + initialization
220  EXPECT_RESULT, Number::New(0));
221  }
222 
223  { DeclarationContext context;
224  context.Check("function x() { }; x",
225  1, // access
226  0,
227  0,
228  EXPECT_RESULT);
229  }
230 
231  { DeclarationContext context;
232  context.Check("const x; x",
233  1, // access
234  2, // declaration + initialization
235  1, // declaration
237  }
238 
239  { DeclarationContext context;
240  context.Check("const x = 0; x",
241  1, // access
242  2, // declaration + initialization
243  1, // declaration
244  EXPECT_RESULT, Undefined()); // SB 0 - BUG 1213579
245  }
246 }
247 
248 
249 
251  protected:
253  return Integer::New(v8::None);
254  }
255 };
256 
257 
258 
259 TEST(Present) {
260  HandleScope scope;
261 
262  { PresentPropertyContext context;
263  context.Check("var x; x",
264  1, // access
265  0,
266  2, // declaration + initialization
267  EXPECT_EXCEPTION); // x is not defined!
268  }
269 
270  { PresentPropertyContext context;
271  context.Check("var x = 0; x",
272  1, // access
273  1, // initialization
274  2, // declaration + initialization
275  EXPECT_RESULT, Number::New(0));
276  }
277 
278  { PresentPropertyContext context;
279  context.Check("function x() { }; x",
280  1, // access
281  0,
282  0,
283  EXPECT_RESULT);
284  }
285 
286  { PresentPropertyContext context;
287  context.Check("const x; x",
288  1, // access
289  1, // initialization
290  1, // (re-)declaration
292  }
293 
294  { PresentPropertyContext context;
295  context.Check("const x = 0; x",
296  1, // access
297  1, // initialization
298  1, // (re-)declaration
299  EXPECT_RESULT, Number::New(0));
300  }
301 }
302 
303 
304 
306  protected:
308  return v8::Handle<Integer>();
309  }
310 };
311 
312 
313 TEST(Absent) {
314  HandleScope scope;
315 
316  { AbsentPropertyContext context;
317  context.Check("var x; x",
318  1, // access
319  1, // declaration
320  2, // declaration + initialization
322  }
323 
324  { AbsentPropertyContext context;
325  context.Check("var x = 0; x",
326  1, // access
327  2, // declaration + initialization
328  2, // declaration + initialization
329  EXPECT_RESULT, Number::New(0));
330  }
331 
332  { AbsentPropertyContext context;
333  context.Check("function x() { }; x",
334  1, // access
335  0,
336  0,
337  EXPECT_RESULT);
338  }
339 
340  { AbsentPropertyContext context;
341  context.Check("const x; x",
342  1, // access
343  2, // declaration + initialization
344  1, // declaration
346  }
347 
348  { AbsentPropertyContext context;
349  context.Check("const x = 0; x",
350  1, // access
351  2, // declaration + initialization
352  1, // declaration
353  EXPECT_RESULT, Undefined()); // SB 0 - BUG 1213579
354  }
355 
356  { AbsentPropertyContext context;
357  context.Check("if (false) { var x = 0 }; x",
358  1, // access
359  1, // declaration
360  1, // declaration + initialization
362  }
363 }
364 
365 
366 
368  public:
369  enum State {
373  };
374 
376 
377  protected:
379  switch (state_) {
380  case DECLARE:
381  // Force declaration by returning that the
382  // property is absent.
383  state_ = INITIALIZE_IF_ASSIGN;
384  return Handle<Integer>();
386  // Return that the property is present so we only get the
387  // setter called when initializing with a value.
388  state_ = UNKNOWN;
389  return Integer::New(v8::None);
390  default:
391  CHECK(state_ == UNKNOWN);
392  break;
393  }
394  // Do the lookup in the object.
395  return v8::Handle<Integer>();
396  }
397 
398  private:
399  State state_;
400 };
401 
402 
403 TEST(Appearing) {
404  HandleScope scope;
405 
406  { AppearingPropertyContext context;
407  context.Check("var x; x",
408  1, // access
409  1, // declaration
410  2, // declaration + initialization
412  }
413 
414  { AppearingPropertyContext context;
415  context.Check("var x = 0; x",
416  1, // access
417  2, // declaration + initialization
418  2, // declaration + initialization
419  EXPECT_RESULT, Number::New(0));
420  }
421 
422  { AppearingPropertyContext context;
423  context.Check("function x() { }; x",
424  1, // access
425  0,
426  0,
427  EXPECT_RESULT);
428  }
429 
430  { AppearingPropertyContext context;
431  context.Check("const x; x",
432  1, // access
433  2, // declaration + initialization
434  1, // declaration
436  }
437 
438  { AppearingPropertyContext context;
439  context.Check("const x = 0; x",
440  1, // access
441  2, // declaration + initialization
442  1, // declaration
444  // Result is undefined because declaration succeeded but
445  // initialization to 0 failed (due to context behavior).
446  }
447 }
448 
449 
450 
452  public:
453  enum State {
458  };
459 
461 
462  protected:
464  switch (state_) {
465  case DECLARE:
466  // Force the first declaration by returning that
467  // the property is absent.
468  state_ = DONT_DECLARE;
469  return Handle<Integer>();
470  case DONT_DECLARE:
471  // Ignore the second declaration by returning
472  // that the property is already there.
473  state_ = INITIALIZE;
474  return Integer::New(v8::None);
475  case INITIALIZE:
476  // Force an initialization by returning that
477  // the property is absent. This will make sure
478  // that the setter is called and it will not
479  // lead to redeclaration conflicts (yet).
480  state_ = UNKNOWN;
481  return Handle<Integer>();
482  default:
483  CHECK(state_ == UNKNOWN);
484  break;
485  }
486  // Do the lookup in the object.
487  return Handle<Integer>();
488  }
489 
490  private:
491  State state_;
492 };
493 
494 
495 TEST(Reappearing) {
496  HandleScope scope;
497 
498  { ReappearingPropertyContext context;
499  context.Check("const x; var x = 0",
500  0,
501  3, // const declaration+initialization, var initialization
502  3, // 2 x declaration + var initialization
504  }
505 }
506 
507 
508 
510  protected:
512  // Let it seem that the property exists in the prototype object.
513  return Integer::New(v8::None);
514  }
515 
516  // Use the prototype as the holder for the interceptors.
518  return function->PrototypeTemplate();
519  }
520 };
521 
522 
523 TEST(ExistsInPrototype) {
524  i::FLAG_es52_globals = true;
525  HandleScope scope;
526 
527  // Sanity check to make sure that the holder of the interceptor
528  // really is the prototype object.
529  { ExistsInPrototypeContext context;
530  context.Check("this.x = 87; this.x",
531  0,
532  0,
533  0,
534  EXPECT_RESULT, Number::New(87));
535  }
536 
537  { ExistsInPrototypeContext context;
538  context.Check("var x; x",
539  0, // get
540  0,
541  0, // declaration
543  }
544 
545  { ExistsInPrototypeContext context;
546  context.Check("var x = 0; x",
547  0,
548  0,
549  0, // declaration
550  EXPECT_RESULT, Number::New(0));
551  }
552 
553  { ExistsInPrototypeContext context;
554  context.Check("const x; x",
555  0,
556  0,
557  0, // declaration
559  }
560 
561  { ExistsInPrototypeContext context;
562  context.Check("const x = 0; x",
563  0,
564  0,
565  0, // declaration
566  EXPECT_RESULT, Number::New(0));
567  }
568 }
569 
570 
571 
573  protected:
575  // Let it seem that the property is absent in the prototype object.
576  return Handle<Integer>();
577  }
578 
579  // Use the prototype as the holder for the interceptors.
581  return function->PrototypeTemplate();
582  }
583 };
584 
585 
586 TEST(AbsentInPrototype) {
587  i::FLAG_es52_globals = true;
588  HandleScope scope;
589 
590  { AbsentInPrototypeContext context;
591  context.Check("if (false) { var x = 0; }; x",
592  0,
593  0,
594  0, // declaration
596  }
597 }
#define CHECK_EQ(expected, value)
Definition: checks.h:219
static v8::Handle< Value > HandleGet(Local< String > key, const AccessorInfo &info)
Definition: test-decls.cc:156
Local< Value > Exception() const
Definition: api.cc:1712
TEST(Unknown)
Definition: test-decls.cc:204
int get_count() const
Definition: test-decls.cc:64
void InitializeIfNeeded()
Definition: test-decls.cc:110
bool HasCaught() const
Definition: api.cc:1695
virtual v8::Handle< Integer > Query(Local< String > key)
Definition: test-decls.cc:463
virtual v8::Handle< Integer > Query(Local< String > key)
Definition: test-decls.cc:197
virtual v8::Handle< Integer > Query(Local< String > key)
Definition: test-decls.cc:574
#define CHECK(condition)
Definition: checks.h:56
void SetVerbose(bool value)
Definition: api.cc:1760
virtual v8::Handle< Integer > Query(Local< String > key)
Definition: test-decls.cc:378
static v8::Handle< Integer > HandleQuery(Local< String > key, const AccessorInfo &info)
Definition: test-decls.cc:173
void Check(const char *source, int get, int set, int has, Expectations expectations, v8::Handle< Value > value=Local< Value >())
Definition: test-decls.cc:126
static v8::Handle< Value > HandleSet(Local< String > key, Local< Value > value, const AccessorInfo &info)
Definition: test-decls.cc:164
virtual ~DeclarationContext()
Definition: test-decls.cc:52
virtual Local< ObjectTemplate > GetHolder(Local< FunctionTemplate > function)
Definition: test-decls.cc:580
virtual v8::Handle< Value > Get(Local< String > key)
Definition: test-decls.cc:186
int set_count() const
Definition: test-decls.cc:65
virtual v8::Handle< Integer > Query(Local< String > key)
Definition: test-decls.cc:511
virtual v8::Handle< Integer > Query(Local< String > key)
Definition: test-decls.cc:252
Definition: v8.h:1401
virtual Local< ObjectTemplate > GetHolder(Local< FunctionTemplate > function)
Definition: test-decls.cc:517
#define HEAP
Definition: isolate.h:1408
virtual v8::Handle< Integer > Query(Local< String > key)
Definition: test-decls.cc:307
Handle< Primitive > V8EXPORT Undefined()
Definition: api.cc:546
bool IsEmpty() const
Definition: v8.h:208
Local< Value > Data() const
Definition: v8.h:4423
int query_count() const
Definition: test-decls.cc:66
Definition: v8.h:105
Expectations
Definition: test-decls.cc:38
virtual v8::Handle< Value > Set(Local< String > key, Local< Value > value)
Definition: test-decls.cc:191
virtual Local< ObjectTemplate > GetHolder(Local< FunctionTemplate > function)
Definition: test-decls.cc:77