blob: e3d61582c53d5eae1b6ec2c96552899b90d0427e [file] [log] [blame]
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001// Copyright 2007-2008 the V8 project authors. All rights reserved.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002// 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
35using namespace v8;
36
37
38enum Expectations {
39 EXPECT_RESULT,
40 EXPECT_EXCEPTION
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.
48class DeclarationContext {
49 public:
50 DeclarationContext();
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,
62 v8::Handle<Value> value = Local<Value>());
63
64 int get_count() const { return get_count_; }
65 int set_count() const { return set_count_; }
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000066 int query_count() const { return query_count_; }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000067
68 protected:
69 virtual v8::Handle<Value> Get(Local<String> key);
70 virtual v8::Handle<Value> Set(Local<String> key, Local<Value> value);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000071 virtual v8::Handle<Integer> Query(Local<String> key);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000072
73 void InitializeIfNeeded();
74
75 // Get the holder for the interceptor. Default to the instance template
76 // but may be overwritten.
77 virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
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);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000088 static v8::Handle<Integer> HandleQuery(Local<String> key,
89 const AccessorInfo& info);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000090
91 private:
92 bool is_initialized_;
93 Persistent<Context> context_;
94 Local<String> property_;
95
96 int get_count_;
97 int set_count_;
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000098 int query_count_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000099
100 static DeclarationContext* GetInstance(const AccessorInfo& info);
101};
102
103
104DeclarationContext::DeclarationContext()
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000105 : is_initialized_(false), get_count_(0), set_count_(0), query_count_(0) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000106 // Do nothing.
107}
108
109
110void DeclarationContext::InitializeIfNeeded() {
111 if (is_initialized_) return;
112 HandleScope scope;
113 Local<FunctionTemplate> function = FunctionTemplate::New();
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000114 Local<Value> data = External::New(this);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000115 GetHolder(function)->SetNamedPropertyHandler(&HandleGet,
116 &HandleSet,
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000117 &HandleQuery,
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000118 0, 0,
119 data);
120 context_ = Context::New(0, function->InstanceTemplate(), Local<Value>());
121 context_->Enter();
122 is_initialized_ = true;
123}
124
125
126void DeclarationContext::Check(const char* source,
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000127 int get, int set, int query,
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000128 Expectations expectations,
129 v8::Handle<Value> value) {
130 InitializeIfNeeded();
131 // A retry after a GC may pollute the counts, so perform gc now
132 // to avoid that.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000133 HEAP->CollectGarbage(v8::internal::NEW_SPACE);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000134 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());
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000140 CHECK_EQ(query, query_count());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000141 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
156v8::Handle<Value> DeclarationContext::HandleGet(Local<String> key,
157 const AccessorInfo& info) {
158 DeclarationContext* context = GetInstance(info);
159 context->get_count_++;
160 return context->Get(key);
161}
162
163
164v8::Handle<Value> DeclarationContext::HandleSet(Local<String> key,
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
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000173v8::Handle<Integer> DeclarationContext::HandleQuery(Local<String> key,
174 const AccessorInfo& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000175 DeclarationContext* context = GetInstance(info);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000176 context->query_count_++;
177 return context->Query(key);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000178}
179
180
181DeclarationContext* DeclarationContext::GetInstance(const AccessorInfo& info) {
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000182 return static_cast<DeclarationContext*>(External::Unwrap(info.Data()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000183}
184
185
186v8::Handle<Value> DeclarationContext::Get(Local<String> key) {
187 return v8::Handle<Value>();
188}
189
190
191v8::Handle<Value> DeclarationContext::Set(Local<String> key,
192 Local<Value> value) {
193 return v8::Handle<Value>();
194}
195
196
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000197v8::Handle<Integer> DeclarationContext::Query(Local<String> key) {
198 return v8::Handle<Integer>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000199}
200
201
202// Test global declaration of a property the interceptor doesn't know
203// about and doesn't handle.
204TEST(Unknown) {
205 HandleScope scope;
206
207 { DeclarationContext context;
208 context.Check("var x; x",
209 1, // access
210 1, // declaration
211 2, // declaration + initialization
212 EXPECT_RESULT, Undefined());
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
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000226 0,
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000227 0,
228 EXPECT_RESULT);
229 }
230
231 { DeclarationContext context;
232 context.Check("const x; x",
233 1, // access
234 2, // declaration + initialization
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000235 1, // declaration
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000236 EXPECT_RESULT, Undefined());
237 }
238
239 { DeclarationContext context;
240 context.Check("const x = 0; x",
241 1, // access
242 2, // declaration + initialization
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000243 1, // declaration
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000244 EXPECT_RESULT, Undefined()); // SB 0 - BUG 1213579
245 }
246}
247
248
249
250class PresentPropertyContext: public DeclarationContext {
251 protected:
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000252 virtual v8::Handle<Integer> Query(Local<String> key) {
253 return Integer::New(v8::None);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000254 }
255};
256
257
258
259TEST(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
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000281 0,
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000282 0,
283 EXPECT_RESULT);
284 }
285
286 { PresentPropertyContext context;
287 context.Check("const x; x",
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000288 1, // access
289 1, // initialization
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000290 1, // (re-)declaration
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000291 EXPECT_RESULT, Undefined());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000292 }
293
294 { PresentPropertyContext context;
295 context.Check("const x = 0; x",
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000296 1, // access
297 1, // initialization
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000298 1, // (re-)declaration
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000299 EXPECT_RESULT, Number::New(0));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000300 }
301}
302
303
304
305class AbsentPropertyContext: public DeclarationContext {
306 protected:
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000307 virtual v8::Handle<Integer> Query(Local<String> key) {
308 return v8::Handle<Integer>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000309 }
310};
311
312
313TEST(Absent) {
314 HandleScope scope;
315
316 { AbsentPropertyContext context;
317 context.Check("var x; x",
318 1, // access
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000319 1, // declaration
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000320 2, // declaration + initialization
321 EXPECT_RESULT, Undefined());
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
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000335 0,
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000336 0,
337 EXPECT_RESULT);
338 }
339
340 { AbsentPropertyContext context;
341 context.Check("const x; x",
342 1, // access
343 2, // declaration + initialization
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000344 1, // declaration
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000345 EXPECT_RESULT, Undefined());
346 }
347
348 { AbsentPropertyContext context;
349 context.Check("const x = 0; x",
350 1, // access
351 2, // declaration + initialization
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000352 1, // declaration
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000353 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
361 EXPECT_RESULT, Undefined());
362 }
363}
364
365
366
367class AppearingPropertyContext: public DeclarationContext {
368 public:
369 enum State {
370 DECLARE,
371 INITIALIZE_IF_ASSIGN,
372 UNKNOWN
373 };
374
375 AppearingPropertyContext() : state_(DECLARE) { }
376
377 protected:
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000378 virtual v8::Handle<Integer> Query(Local<String> key) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000379 switch (state_) {
380 case DECLARE:
381 // Force declaration by returning that the
382 // property is absent.
383 state_ = INITIALIZE_IF_ASSIGN;
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000384 return Handle<Integer>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000385 case INITIALIZE_IF_ASSIGN:
386 // Return that the property is present so we only get the
387 // setter called when initializing with a value.
388 state_ = UNKNOWN;
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000389 return Integer::New(v8::None);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000390 default:
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000391 CHECK(state_ == UNKNOWN);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000392 break;
393 }
394 // Do the lookup in the object.
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000395 return v8::Handle<Integer>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000396 }
397
398 private:
399 State state_;
400};
401
402
403TEST(Appearing) {
404 HandleScope scope;
405
406 { AppearingPropertyContext context;
407 context.Check("var x; x",
408 1, // access
409 1, // declaration
410 2, // declaration + initialization
411 EXPECT_RESULT, Undefined());
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
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000425 0,
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000426 0,
427 EXPECT_RESULT);
428 }
429
430 { AppearingPropertyContext context;
431 context.Check("const x; x",
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000432 1, // access
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000433 2, // declaration + initialization
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000434 1, // declaration
435 EXPECT_RESULT, Undefined());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000436 }
437
438 { AppearingPropertyContext context;
439 context.Check("const x = 0; x",
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000440 1, // access
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000441 2, // declaration + initialization
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000442 1, // declaration
443 EXPECT_RESULT, Undefined());
444 // Result is undefined because declaration succeeded but
445 // initialization to 0 failed (due to context behavior).
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000446 }
447}
448
449
450
451class ReappearingPropertyContext: public DeclarationContext {
452 public:
453 enum State {
454 DECLARE,
455 DONT_DECLARE,
456 INITIALIZE,
457 UNKNOWN
458 };
459
460 ReappearingPropertyContext() : state_(DECLARE) { }
461
462 protected:
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000463 virtual v8::Handle<Integer> Query(Local<String> key) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000464 switch (state_) {
465 case DECLARE:
466 // Force the first declaration by returning that
467 // the property is absent.
468 state_ = DONT_DECLARE;
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000469 return Handle<Integer>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000470 case DONT_DECLARE:
471 // Ignore the second declaration by returning
472 // that the property is already there.
473 state_ = INITIALIZE;
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000474 return Integer::New(v8::None);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000475 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;
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000481 return Handle<Integer>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000482 default:
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000483 CHECK(state_ == UNKNOWN);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000484 break;
485 }
486 // Do the lookup in the object.
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000487 return Handle<Integer>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000488 }
489
490 private:
491 State state_;
492};
493
494
495TEST(Reappearing) {
496 HandleScope scope;
497
498 { ReappearingPropertyContext context;
499 context.Check("const x; var x = 0",
500 0,
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000501 3, // const declaration+initialization, var initialization
502 3, // 2 x declaration + var initialization
503 EXPECT_RESULT, Undefined());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000504 }
505}
506
507
508
509class ExistsInPrototypeContext: public DeclarationContext {
510 protected:
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000511 virtual v8::Handle<Integer> Query(Local<String> key) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000512 // Let it seem that the property exists in the prototype object.
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000513 return Integer::New(v8::None);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000514 }
515
516 // Use the prototype as the holder for the interceptors.
517 virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
518 return function->PrototypeTemplate();
519 }
520};
521
522
523TEST(ExistsInPrototype) {
524 HandleScope scope;
525
526 // Sanity check to make sure that the holder of the interceptor
527 // really is the prototype object.
528 { ExistsInPrototypeContext context;
529 context.Check("this.x = 87; this.x",
530 0,
531 0,
532 0,
533 EXPECT_RESULT, Number::New(87));
534 }
535
536 { ExistsInPrototypeContext context;
537 context.Check("var x; x",
erik.corry@gmail.comed49e962012-04-17 11:57:53 +0000538 0, // get
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000539 0,
erik.corry@gmail.comed49e962012-04-17 11:57:53 +0000540 0, // declaration
541 EXPECT_RESULT, Undefined());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000542 }
543
544 { ExistsInPrototypeContext context;
545 context.Check("var x = 0; x",
546 0,
547 0,
erik.corry@gmail.comed49e962012-04-17 11:57:53 +0000548 0, // declaration
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000549 EXPECT_RESULT, Number::New(0));
550 }
551
552 { ExistsInPrototypeContext context;
553 context.Check("const x; x",
554 0,
555 0,
erik.corry@gmail.comed49e962012-04-17 11:57:53 +0000556 0, // declaration
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000557 EXPECT_RESULT, Undefined());
558 }
559
560 { ExistsInPrototypeContext context;
561 context.Check("const x = 0; x",
562 0,
563 0,
erik.corry@gmail.comed49e962012-04-17 11:57:53 +0000564 0, // declaration
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000565 EXPECT_RESULT, Number::New(0));
566 }
567}
568
569
570
571class AbsentInPrototypeContext: public DeclarationContext {
572 protected:
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000573 virtual v8::Handle<Integer> Query(Local<String> key) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000574 // Let it seem that the property is absent in the prototype object.
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000575 return Handle<Integer>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000576 }
577
578 // Use the prototype as the holder for the interceptors.
579 virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
580 return function->PrototypeTemplate();
581 }
582};
583
584
585TEST(AbsentInPrototype) {
586 HandleScope scope;
587
588 { AbsentInPrototypeContext context;
589 context.Check("if (false) { var x = 0; }; x",
590 0,
591 0,
erik.corry@gmail.comed49e962012-04-17 11:57:53 +0000592 0, // declaration
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000593 EXPECT_RESULT, Undefined());
594 }
595}