v8  3.14.5(node0.10.28)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
test-accessors.cc
Go to the documentation of this file.
1 // Copyright 2012 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 "api.h"
33 #include "cctest.h"
34 #include "frames-inl.h"
35 #include "string-stream.h"
36 
37 using ::v8::ObjectTemplate;
38 using ::v8::Value;
39 using ::v8::Context;
40 using ::v8::Local;
41 using ::v8::String;
42 using ::v8::Script;
43 using ::v8::Function;
44 using ::v8::AccessorInfo;
45 using ::v8::Extension;
46 
47 static v8::Handle<Value> handle_property(Local<String> name,
48  const AccessorInfo&) {
50  return v8_num(900);
51 }
52 
53 
54 THREADED_TEST(PropertyHandler) {
55  v8::HandleScope scope;
56  Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
57  fun_templ->InstanceTemplate()->SetAccessor(v8_str("foo"), handle_property);
58  LocalContext env;
59  Local<Function> fun = fun_templ->GetFunction();
60  env->Global()->Set(v8_str("Fun"), fun);
61  Local<Script> getter = v8_compile("var obj = new Fun(); obj.foo;");
62  CHECK_EQ(900, getter->Run()->Int32Value());
63  Local<Script> setter = v8_compile("obj.foo = 901;");
64  CHECK_EQ(901, setter->Run()->Int32Value());
65 }
66 
67 
68 static v8::Handle<Value> GetIntValue(Local<String> property,
69  const AccessorInfo& info) {
71  int* value =
72  static_cast<int*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
73  return v8_num(*value);
74 }
75 
76 
77 static void SetIntValue(Local<String> property,
78  Local<Value> value,
79  const AccessorInfo& info) {
80  int* field =
81  static_cast<int*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
82  *field = value->Int32Value();
83 }
84 
85 int foo, bar, baz;
86 
87 THREADED_TEST(GlobalVariableAccess) {
88  foo = 0;
89  bar = -4;
90  baz = 10;
91  v8::HandleScope scope;
93  templ->InstanceTemplate()->SetAccessor(v8_str("foo"),
94  GetIntValue,
95  SetIntValue,
96  v8::External::New(&foo));
97  templ->InstanceTemplate()->SetAccessor(v8_str("bar"),
98  GetIntValue,
99  SetIntValue,
100  v8::External::New(&bar));
101  templ->InstanceTemplate()->SetAccessor(v8_str("baz"),
102  GetIntValue,
103  SetIntValue,
104  v8::External::New(&baz));
105  LocalContext env(0, templ->InstanceTemplate());
106  v8_compile("foo = (++bar) + baz")->Run();
107  CHECK_EQ(bar, -3);
108  CHECK_EQ(foo, 7);
109 }
110 
111 
112 static int x_register = 0;
113 static v8::Handle<v8::Object> x_receiver;
114 static v8::Handle<v8::Object> x_holder;
115 
116 
117 static v8::Handle<Value> XGetter(Local<String> name, const AccessorInfo& info) {
120  CHECK_EQ(isolate, info.GetIsolate());
121  CHECK_EQ(x_receiver, info.This());
122  CHECK_EQ(x_holder, info.Holder());
123  return v8_num(x_register);
124 }
125 
126 
127 static void XSetter(Local<String> name,
128  Local<Value> value,
129  const AccessorInfo& info) {
131  CHECK_EQ(isolate, info.GetIsolate());
132  CHECK_EQ(x_holder, info.This());
133  CHECK_EQ(x_holder, info.Holder());
134  x_register = value->Int32Value();
135 }
136 
137 
138 THREADED_TEST(AccessorIC) {
139  v8::HandleScope scope;
140  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
141  obj->SetAccessor(v8_str("x"), XGetter, XSetter);
142  LocalContext context;
143  x_holder = obj->NewInstance();
144  context->Global()->Set(v8_str("holder"), x_holder);
145  x_receiver = v8::Object::New();
146  context->Global()->Set(v8_str("obj"), x_receiver);
148  "obj.__proto__ = holder;"
149  "var result = [];"
150  "for (var i = 0; i < 10; i++) {"
151  " holder.x = i;"
152  " result.push(obj.x);"
153  "}"
154  "result"));
155  CHECK_EQ(10, array->Length());
156  for (int i = 0; i < 10; i++) {
157  v8::Handle<Value> entry = array->Get(v8::Integer::New(i));
158  CHECK_EQ(v8::Integer::New(i), entry);
159  }
160 }
161 
162 
163 static v8::Handle<Value> AccessorProhibitsOverwritingGetter(
164  Local<String> name,
165  const AccessorInfo& info) {
167  return v8::True();
168 }
169 
170 
171 THREADED_TEST(AccessorProhibitsOverwriting) {
172  v8::HandleScope scope;
173  LocalContext context;
174  Local<ObjectTemplate> templ = ObjectTemplate::New();
175  templ->SetAccessor(v8_str("x"),
176  AccessorProhibitsOverwritingGetter,
177  0,
180  v8::ReadOnly);
181  Local<v8::Object> instance = templ->NewInstance();
182  context->Global()->Set(v8_str("obj"), instance);
183  Local<Value> value = CompileRun(
184  "obj.__defineGetter__('x', function() { return false; });"
185  "obj.x");
186  CHECK(value->BooleanValue());
187  value = CompileRun(
188  "var setter_called = false;"
189  "obj.__defineSetter__('x', function() { setter_called = true; });"
190  "obj.x = 42;"
191  "setter_called");
192  CHECK(!value->BooleanValue());
193  value = CompileRun(
194  "obj2 = {};"
195  "obj2.__proto__ = obj;"
196  "obj2.__defineGetter__('x', function() { return false; });"
197  "obj2.x");
198  CHECK(value->BooleanValue());
199  value = CompileRun(
200  "var setter_called = false;"
201  "obj2 = {};"
202  "obj2.__proto__ = obj;"
203  "obj2.__defineSetter__('x', function() { setter_called = true; });"
204  "obj2.x = 42;"
205  "setter_called");
206  CHECK(!value->BooleanValue());
207 }
208 
209 
210 template <int C>
211 static v8::Handle<Value> HandleAllocatingGetter(Local<String> name,
212  const AccessorInfo& info) {
214  for (int i = 0; i < C; i++)
215  v8::String::New("foo");
216  return v8::String::New("foo");
217 }
218 
219 
220 THREADED_TEST(HandleScopePop) {
221  v8::HandleScope scope;
222  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
223  obj->SetAccessor(v8_str("one"), HandleAllocatingGetter<1>);
224  obj->SetAccessor(v8_str("many"), HandleAllocatingGetter<1024>);
225  LocalContext context;
226  v8::Handle<v8::Object> inst = obj->NewInstance();
227  context->Global()->Set(v8::String::New("obj"), inst);
228  int count_before = i::HandleScope::NumberOfHandles();
229  {
230  v8::HandleScope scope;
231  CompileRun(
232  "for (var i = 0; i < 1000; i++) {"
233  " obj.one;"
234  " obj.many;"
235  "}");
236  }
237  int count_after = i::HandleScope::NumberOfHandles();
238  CHECK_EQ(count_before, count_after);
239 }
240 
241 static v8::Handle<Value> CheckAccessorArgsCorrect(Local<String> name,
242  const AccessorInfo& info) {
243  CHECK(info.GetIsolate() == v8::Isolate::GetCurrent());
244  CHECK(info.This() == info.Holder());
245  CHECK(info.Data()->Equals(v8::String::New("data")));
247  CHECK(info.GetIsolate() == v8::Isolate::GetCurrent());
248  CHECK(info.This() == info.Holder());
249  CHECK(info.Data()->Equals(v8::String::New("data")));
250  HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
251  CHECK(info.GetIsolate() == v8::Isolate::GetCurrent());
252  CHECK(info.This() == info.Holder());
253  CHECK(info.Data()->Equals(v8::String::New("data")));
254  return v8::Integer::New(17);
255 }
256 
257 THREADED_TEST(DirectCall) {
258  v8::HandleScope scope;
259  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
260  obj->SetAccessor(v8_str("xxx"),
261  CheckAccessorArgsCorrect,
262  NULL,
263  v8::String::New("data"));
264  LocalContext context;
265  v8::Handle<v8::Object> inst = obj->NewInstance();
266  context->Global()->Set(v8::String::New("obj"), inst);
267  Local<Script> scr = v8::Script::Compile(v8::String::New("obj.xxx"));
268  for (int i = 0; i < 10; i++) {
269  Local<Value> result = scr->Run();
270  CHECK(!result.IsEmpty());
271  CHECK_EQ(17, result->Int32Value());
272  }
273 }
274 
275 static v8::Handle<Value> EmptyGetter(Local<String> name,
276  const AccessorInfo& info) {
277  CheckAccessorArgsCorrect(name, info);
279  CheckAccessorArgsCorrect(name, info);
280  return v8::Handle<v8::Value>();
281 }
282 
283 THREADED_TEST(EmptyResult) {
284  v8::HandleScope scope;
285  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
286  obj->SetAccessor(v8_str("xxx"), EmptyGetter, NULL, v8::String::New("data"));
287  LocalContext context;
288  v8::Handle<v8::Object> inst = obj->NewInstance();
289  context->Global()->Set(v8::String::New("obj"), inst);
290  Local<Script> scr = v8::Script::Compile(v8::String::New("obj.xxx"));
291  for (int i = 0; i < 10; i++) {
292  Local<Value> result = scr->Run();
293  CHECK(result == v8::Undefined());
294  }
295 }
296 
297 
298 THREADED_TEST(NoReuseRegress) {
299  // Check that the IC generated for the one test doesn't get reused
300  // for the other.
301  v8::HandleScope scope;
302  {
303  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
304  obj->SetAccessor(v8_str("xxx"), EmptyGetter, NULL, v8::String::New("data"));
305  LocalContext context;
306  v8::Handle<v8::Object> inst = obj->NewInstance();
307  context->Global()->Set(v8::String::New("obj"), inst);
308  Local<Script> scr = v8::Script::Compile(v8::String::New("obj.xxx"));
309  for (int i = 0; i < 2; i++) {
310  Local<Value> result = scr->Run();
311  CHECK(result == v8::Undefined());
312  }
313  }
314  {
315  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
316  obj->SetAccessor(v8_str("xxx"),
317  CheckAccessorArgsCorrect,
318  NULL,
319  v8::String::New("data"));
320  LocalContext context;
321  v8::Handle<v8::Object> inst = obj->NewInstance();
322  context->Global()->Set(v8::String::New("obj"), inst);
323  Local<Script> scr = v8::Script::Compile(v8::String::New("obj.xxx"));
324  for (int i = 0; i < 10; i++) {
325  Local<Value> result = scr->Run();
326  CHECK(!result.IsEmpty());
327  CHECK_EQ(17, result->Int32Value());
328  }
329  }
330 }
331 
332 static v8::Handle<Value> ThrowingGetAccessor(Local<String> name,
333  const AccessorInfo& info) {
335  return v8::ThrowException(v8_str("g"));
336 }
337 
338 
339 static void ThrowingSetAccessor(Local<String> name,
340  Local<Value> value,
341  const AccessorInfo& info) {
342  v8::ThrowException(value);
343 }
344 
345 
346 THREADED_TEST(Regress1054726) {
347  v8::HandleScope scope;
348  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
349  obj->SetAccessor(v8_str("x"),
350  ThrowingGetAccessor,
351  ThrowingSetAccessor,
352  Local<Value>());
353 
354  LocalContext env;
355  env->Global()->Set(v8_str("obj"), obj->NewInstance());
356 
357  // Use the throwing property setter/getter in a loop to force
358  // the accessor ICs to be initialized.
359  v8::Handle<Value> result;
360  result = Script::Compile(v8_str(
361  "var result = '';"
362  "for (var i = 0; i < 5; i++) {"
363  " try { obj.x; } catch (e) { result += e; }"
364  "}; result"))->Run();
365  CHECK_EQ(v8_str("ggggg"), result);
366 
367  result = Script::Compile(String::New(
368  "var result = '';"
369  "for (var i = 0; i < 5; i++) {"
370  " try { obj.x = i; } catch (e) { result += e; }"
371  "}; result"))->Run();
372  CHECK_EQ(v8_str("01234"), result);
373 }
374 
375 
376 static v8::Handle<Value> AllocGetter(Local<String> name,
377  const AccessorInfo& info) {
379  return v8::Array::New(1000);
380 }
381 
382 
384  v8::HandleScope scope;
385  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
386  obj->SetAccessor(v8_str("xxx"), AllocGetter);
387  LocalContext env;
388  env->Global()->Set(v8_str("obj"), obj->NewInstance());
389  Script::Compile(String::New(
390  "var last = [];"
391  "for (var i = 0; i < 2048; i++) {"
392  " var result = obj.xxx;"
393  " result[0] = last;"
394  " last = result;"
395  "}"))->Run();
396 }
397 
398 
399 static v8::Handle<Value> StackCheck(Local<String> name,
400  const AccessorInfo& info) {
401  i::StackFrameIterator iter;
402  for (int i = 0; !iter.done(); i++) {
403  i::StackFrame* frame = iter.frame();
404  CHECK(i != 0 || (frame->type() == i::StackFrame::EXIT));
405  i::Code* code = frame->LookupCode();
406  CHECK(code->IsCode());
407  i::Address pc = frame->pc();
408  CHECK(code->contains(pc));
409  iter.Advance();
410  }
411  return v8::Undefined();
412 }
413 
414 
415 THREADED_TEST(StackIteration) {
416  v8::HandleScope scope;
417  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
419  obj->SetAccessor(v8_str("xxx"), StackCheck);
420  LocalContext env;
421  env->Global()->Set(v8_str("obj"), obj->NewInstance());
422  Script::Compile(String::New(
423  "function foo() {"
424  " return obj.xxx;"
425  "}"
426  "for (var i = 0; i < 100; i++) {"
427  " foo();"
428  "}"))->Run();
429 }
430 
431 
432 static v8::Handle<Value> AllocateHandles(Local<String> name,
433  const AccessorInfo& info) {
434  for (int i = 0; i < i::kHandleBlockSize + 1; i++) {
436  }
437  return v8::Integer::New(100);
438 }
439 
440 
441 THREADED_TEST(HandleScopeSegment) {
442  // Check that we can return values past popping of handle scope
443  // segments.
444  v8::HandleScope scope;
445  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
446  obj->SetAccessor(v8_str("xxx"), AllocateHandles);
447  LocalContext env;
448  env->Global()->Set(v8_str("obj"), obj->NewInstance());
449  v8::Handle<v8::Value> result = Script::Compile(String::New(
450  "var result;"
451  "for (var i = 0; i < 4; i++)"
452  " result = obj.xxx;"
453  "result;"))->Run();
454  CHECK_EQ(100, result->Int32Value());
455 }
byte * Address
Definition: globals.h:157
static Isolate * GetCurrent()
Definition: api.cc:5520
static Local< Script > Compile(Handle< String > source, ScriptOrigin *origin=NULL, ScriptData *pre_data=NULL, Handle< String > script_data=Handle< String >())
Definition: api.cc:1568
static int NumberOfHandles()
Definition: handles.cc:48
#define CHECK_EQ(expected, value)
Definition: checks.h:219
static Local< FunctionTemplate > New(InvocationCallback callback=0, Handle< Value > data=Handle< Value >(), Handle< Signature > signature=Handle< Signature >())
Definition: api.cc:951
Handle< Boolean > V8EXPORT True()
Definition: api.cc:569
V8EXPORT Local< Value > Get(Handle< Value > key)
Definition: api.cc:2853
Local< Object > NewInstance()
Definition: api.cc:4660
static V8EXPORT Local< String > New(const char *data, int length=-1)
Definition: api.cc:4779
Local< ObjectTemplate > InstanceTemplate()
Definition: api.cc:1122
static Handle< T > Cast(Handle< S > that)
Definition: v8.h:244
#define CHECK(condition)
Definition: checks.h:56
bool contains(byte *pc)
Definition: objects-inl.h:4690
int foo
HANDLE HANDLE LPSTACKFRAME64 StackFrame
static void Fuzz()
Definition: test-api.cc:10620
static const int kNoGCFlags
Definition: heap.h:1081
void SetAccessor(Handle< String > name, AccessorGetter getter, AccessorSetter setter=0, Handle< Value > data=Handle< Value >(), AccessControl settings=DEFAULT, PropertyAttribute attribute=None, Handle< AccessorSignature > signature=Handle< AccessorSignature >())
Definition: api.cc:1291
V8EXPORT int32_t Int32Value() const
Definition: api.cc:2662
Local< Object > Global()
Definition: api.cc:4570
const Register pc
static Local< T > New(Handle< T > that)
Definition: v8.h:4193
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
int baz
#define HEAP
Definition: isolate.h:1433
const int kHandleBlockSize
Definition: api.h:510
static V8EXPORT Local< Integer > New(int32_t value)
Definition: api.cc:5228
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if NULL
Handle< Primitive > V8EXPORT Undefined()
Definition: api.cc:549
static void ClearMentionedObjectCache()
V8EXPORT uint32_t Length() const
Definition: api.cc:5168
static V8EXPORT Local< External > New(void *value)
Definition: api.cc:4752
int bar
Handle< Value > V8EXPORT ThrowException(Handle< Value > exception)
Definition: api.cc:486
THREADED_TEST(PropertyHandler)
static V8EXPORT Local< Object > New()
Definition: api.cc:4957