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 "src/v8.h" 31 32#include "src/api.h" 33#include "src/frames-inl.h" 34#include "src/string-stream.h" 35#include "test/cctest/cctest.h" 36 37using ::v8::ObjectTemplate; 38using ::v8::Value; 39using ::v8::Context; 40using ::v8::Local; 41using ::v8::String; 42using ::v8::Script; 43using ::v8::Function; 44using ::v8::Extension; 45 46static void handle_property(Local<String> name, 47 const v8::PropertyCallbackInfo<v8::Value>& info) { 48 ApiTestFuzzer::Fuzz(); 49 info.GetReturnValue().Set(v8_num(900)); 50} 51 52static void handle_property_2(Local<String> name, 53 const v8::PropertyCallbackInfo<v8::Value>& info) { 54 ApiTestFuzzer::Fuzz(); 55 info.GetReturnValue().Set(v8_num(902)); 56} 57 58 59static void handle_property(const v8::FunctionCallbackInfo<v8::Value>& info) { 60 ApiTestFuzzer::Fuzz(); 61 CHECK_EQ(0, info.Length()); 62 info.GetReturnValue().Set(v8_num(907)); 63} 64 65 66THREADED_TEST(PropertyHandler) { 67 LocalContext env; 68 v8::Isolate* isolate = env->GetIsolate(); 69 v8::HandleScope scope(isolate); 70 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate); 71 fun_templ->InstanceTemplate()->SetAccessor(v8_str("foo"), handle_property); 72 Local<v8::FunctionTemplate> getter_templ = 73 v8::FunctionTemplate::New(isolate, handle_property); 74 getter_templ->SetLength(0); 75 fun_templ-> 76 InstanceTemplate()->SetAccessorProperty(v8_str("bar"), getter_templ); 77 fun_templ->InstanceTemplate()-> 78 SetNativeDataProperty(v8_str("instance_foo"), handle_property); 79 fun_templ->SetNativeDataProperty(v8_str("object_foo"), handle_property_2); 80 Local<Function> fun = fun_templ->GetFunction(); 81 env->Global()->Set(v8_str("Fun"), fun); 82 Local<Script> getter; 83 Local<Script> setter; 84 // check function instance accessors 85 getter = v8_compile("var obj = new Fun(); obj.instance_foo;"); 86 CHECK_EQ(900, getter->Run()->Int32Value()); 87 setter = v8_compile("obj.instance_foo = 901;"); 88 CHECK_EQ(901, setter->Run()->Int32Value()); 89 getter = v8_compile("obj.bar;"); 90 CHECK_EQ(907, getter->Run()->Int32Value()); 91 setter = v8_compile("obj.bar = 908;"); 92 CHECK_EQ(908, setter->Run()->Int32Value()); 93 // check function static accessors 94 getter = v8_compile("Fun.object_foo;"); 95 CHECK_EQ(902, getter->Run()->Int32Value()); 96 setter = v8_compile("Fun.object_foo = 903;"); 97 CHECK_EQ(903, setter->Run()->Int32Value()); 98} 99 100 101static void GetIntValue(Local<String> property, 102 const v8::PropertyCallbackInfo<v8::Value>& info) { 103 ApiTestFuzzer::Fuzz(); 104 int* value = 105 static_cast<int*>(v8::Handle<v8::External>::Cast(info.Data())->Value()); 106 info.GetReturnValue().Set(v8_num(*value)); 107} 108 109 110static void SetIntValue(Local<String> property, 111 Local<Value> value, 112 const v8::PropertyCallbackInfo<void>& info) { 113 int* field = 114 static_cast<int*>(v8::Handle<v8::External>::Cast(info.Data())->Value()); 115 *field = value->Int32Value(); 116} 117 118int foo, bar, baz; 119 120THREADED_TEST(GlobalVariableAccess) { 121 foo = 0; 122 bar = -4; 123 baz = 10; 124 v8::Isolate* isolate = CcTest::isolate(); 125 v8::HandleScope scope(isolate); 126 v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate); 127 templ->InstanceTemplate()->SetAccessor( 128 v8_str("foo"), GetIntValue, SetIntValue, 129 v8::External::New(isolate, &foo)); 130 templ->InstanceTemplate()->SetAccessor( 131 v8_str("bar"), GetIntValue, SetIntValue, 132 v8::External::New(isolate, &bar)); 133 templ->InstanceTemplate()->SetAccessor( 134 v8_str("baz"), GetIntValue, SetIntValue, 135 v8::External::New(isolate, &baz)); 136 LocalContext env(0, templ->InstanceTemplate()); 137 v8_compile("foo = (++bar) + baz")->Run(); 138 CHECK_EQ(bar, -3); 139 CHECK_EQ(foo, 7); 140} 141 142 143static int x_register[2] = {0, 0}; 144static v8::Handle<v8::Object> x_receiver; 145static v8::Handle<v8::Object> x_holder; 146 147template<class Info> 148static void XGetter(const Info& info, int offset) { 149 ApiTestFuzzer::Fuzz(); 150 v8::Isolate* isolate = CcTest::isolate(); 151 CHECK_EQ(isolate, info.GetIsolate()); 152 CHECK_EQ(x_receiver, info.This()); 153 info.GetReturnValue().Set(v8_num(x_register[offset])); 154} 155 156 157static void XGetter(Local<String> name, 158 const v8::PropertyCallbackInfo<v8::Value>& info) { 159 CHECK_EQ(x_holder, info.Holder()); 160 XGetter(info, 0); 161} 162 163 164static void XGetter(const v8::FunctionCallbackInfo<v8::Value>& info) { 165 CHECK_EQ(x_receiver, info.Holder()); 166 XGetter(info, 1); 167} 168 169 170template<class Info> 171static void XSetter(Local<Value> value, const Info& info, int offset) { 172 v8::Isolate* isolate = CcTest::isolate(); 173 CHECK_EQ(isolate, info.GetIsolate()); 174 CHECK_EQ(x_holder, info.This()); 175 CHECK_EQ(x_holder, info.Holder()); 176 x_register[offset] = value->Int32Value(); 177 info.GetReturnValue().Set(v8_num(-1)); 178} 179 180 181static void XSetter(Local<String> name, 182 Local<Value> value, 183 const v8::PropertyCallbackInfo<void>& info) { 184 XSetter(value, info, 0); 185} 186 187 188static void XSetter(const v8::FunctionCallbackInfo<v8::Value>& info) { 189 CHECK_EQ(1, info.Length()); 190 XSetter(info[0], info, 1); 191} 192 193 194THREADED_TEST(AccessorIC) { 195 LocalContext context; 196 v8::Isolate* isolate = context->GetIsolate(); 197 v8::HandleScope scope(isolate); 198 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate); 199 obj->SetAccessor(v8_str("x0"), XGetter, XSetter); 200 obj->SetAccessorProperty(v8_str("x1"), 201 v8::FunctionTemplate::New(isolate, XGetter), 202 v8::FunctionTemplate::New(isolate, XSetter)); 203 x_holder = obj->NewInstance(); 204 context->Global()->Set(v8_str("holder"), x_holder); 205 x_receiver = v8::Object::New(isolate); 206 context->Global()->Set(v8_str("obj"), x_receiver); 207 v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(CompileRun( 208 "obj.__proto__ = holder;" 209 "var result = [];" 210 "var key_0 = 'x0';" 211 "var key_1 = 'x1';" 212 "for (var j = 0; j < 10; j++) {" 213 " var i = 4*j;" 214 " result.push(holder.x0 = i);" 215 " result.push(obj.x0);" 216 " result.push(holder.x1 = i + 1);" 217 " result.push(obj.x1);" 218 " result.push(holder[key_0] = i + 2);" 219 " result.push(obj[key_0]);" 220 " result.push(holder[key_1] = i + 3);" 221 " result.push(obj[key_1]);" 222 "}" 223 "result")); 224 CHECK_EQ(80, array->Length()); 225 for (int i = 0; i < 80; i++) { 226 v8::Handle<Value> entry = array->Get(v8::Integer::New(isolate, i)); 227 CHECK_EQ(v8::Integer::New(isolate, i/2), entry); 228 } 229} 230 231 232template <int C> 233static void HandleAllocatingGetter( 234 Local<String> name, 235 const v8::PropertyCallbackInfo<v8::Value>& info) { 236 ApiTestFuzzer::Fuzz(); 237 for (int i = 0; i < C; i++) 238 v8::String::NewFromUtf8(info.GetIsolate(), "foo"); 239 info.GetReturnValue().Set(v8::String::NewFromUtf8(info.GetIsolate(), "foo")); 240} 241 242 243THREADED_TEST(HandleScopePop) { 244 LocalContext context; 245 v8::Isolate* isolate = context->GetIsolate(); 246 v8::HandleScope scope(isolate); 247 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate); 248 obj->SetAccessor(v8_str("one"), HandleAllocatingGetter<1>); 249 obj->SetAccessor(v8_str("many"), HandleAllocatingGetter<1024>); 250 v8::Handle<v8::Object> inst = obj->NewInstance(); 251 context->Global()->Set(v8::String::NewFromUtf8(isolate, "obj"), inst); 252 int count_before = 253 i::HandleScope::NumberOfHandles(reinterpret_cast<i::Isolate*>(isolate)); 254 { 255 v8::HandleScope scope(isolate); 256 CompileRun( 257 "for (var i = 0; i < 1000; i++) {" 258 " obj.one;" 259 " obj.many;" 260 "}"); 261 } 262 int count_after = 263 i::HandleScope::NumberOfHandles(reinterpret_cast<i::Isolate*>(isolate)); 264 CHECK_EQ(count_before, count_after); 265} 266 267static void CheckAccessorArgsCorrect( 268 Local<String> name, 269 const v8::PropertyCallbackInfo<v8::Value>& info) { 270 CHECK(info.GetIsolate() == CcTest::isolate()); 271 CHECK(info.This() == info.Holder()); 272 CHECK( 273 info.Data()->Equals(v8::String::NewFromUtf8(CcTest::isolate(), "data"))); 274 ApiTestFuzzer::Fuzz(); 275 CHECK(info.GetIsolate() == CcTest::isolate()); 276 CHECK(info.This() == info.Holder()); 277 CHECK( 278 info.Data()->Equals(v8::String::NewFromUtf8(CcTest::isolate(), "data"))); 279 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); 280 CHECK(info.GetIsolate() == CcTest::isolate()); 281 CHECK(info.This() == info.Holder()); 282 CHECK( 283 info.Data()->Equals(v8::String::NewFromUtf8(CcTest::isolate(), "data"))); 284 info.GetReturnValue().Set(17); 285} 286 287 288THREADED_TEST(DirectCall) { 289 LocalContext context; 290 v8::Isolate* isolate = context->GetIsolate(); 291 v8::HandleScope scope(isolate); 292 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate); 293 obj->SetAccessor(v8_str("xxx"), 294 CheckAccessorArgsCorrect, 295 NULL, 296 v8::String::NewFromUtf8(isolate, "data")); 297 v8::Handle<v8::Object> inst = obj->NewInstance(); 298 context->Global()->Set(v8::String::NewFromUtf8(isolate, "obj"), 299 inst); 300 Local<Script> scr = v8::Script::Compile( 301 v8::String::NewFromUtf8(isolate, "obj.xxx")); 302 for (int i = 0; i < 10; i++) { 303 Local<Value> result = scr->Run(); 304 CHECK(!result.IsEmpty()); 305 CHECK_EQ(17, result->Int32Value()); 306 } 307} 308 309static void EmptyGetter(Local<String> name, 310 const v8::PropertyCallbackInfo<v8::Value>& info) { 311 CheckAccessorArgsCorrect(name, info); 312 ApiTestFuzzer::Fuzz(); 313 CheckAccessorArgsCorrect(name, info); 314 info.GetReturnValue().Set(v8::Handle<v8::Value>()); 315} 316 317 318THREADED_TEST(EmptyResult) { 319 LocalContext context; 320 v8::Isolate* isolate = context->GetIsolate(); 321 v8::HandleScope scope(isolate); 322 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate); 323 obj->SetAccessor(v8_str("xxx"), EmptyGetter, NULL, 324 v8::String::NewFromUtf8(isolate, "data")); 325 v8::Handle<v8::Object> inst = obj->NewInstance(); 326 context->Global()->Set(v8::String::NewFromUtf8(isolate, "obj"), inst); 327 Local<Script> scr = 328 v8::Script::Compile(v8::String::NewFromUtf8(isolate, "obj.xxx")); 329 for (int i = 0; i < 10; i++) { 330 Local<Value> result = scr->Run(); 331 CHECK(result == v8::Undefined(isolate)); 332 } 333} 334 335 336THREADED_TEST(NoReuseRegress) { 337 // Check that the IC generated for the one test doesn't get reused 338 // for the other. 339 v8::Isolate* isolate = CcTest::isolate(); 340 v8::HandleScope scope(isolate); 341 { 342 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate); 343 obj->SetAccessor(v8_str("xxx"), EmptyGetter, NULL, 344 v8::String::NewFromUtf8(isolate, "data")); 345 LocalContext context; 346 v8::Handle<v8::Object> inst = obj->NewInstance(); 347 context->Global()->Set(v8::String::NewFromUtf8(isolate, "obj"), inst); 348 Local<Script> scr = 349 v8::Script::Compile(v8::String::NewFromUtf8(isolate, "obj.xxx")); 350 for (int i = 0; i < 2; i++) { 351 Local<Value> result = scr->Run(); 352 CHECK(result == v8::Undefined(isolate)); 353 } 354 } 355 { 356 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate); 357 obj->SetAccessor(v8_str("xxx"), 358 CheckAccessorArgsCorrect, 359 NULL, 360 v8::String::NewFromUtf8(isolate, "data")); 361 LocalContext context; 362 v8::Handle<v8::Object> inst = obj->NewInstance(); 363 context->Global()->Set(v8::String::NewFromUtf8(isolate, "obj"), inst); 364 Local<Script> scr = 365 v8::Script::Compile(v8::String::NewFromUtf8(isolate, "obj.xxx")); 366 for (int i = 0; i < 10; i++) { 367 Local<Value> result = scr->Run(); 368 CHECK(!result.IsEmpty()); 369 CHECK_EQ(17, result->Int32Value()); 370 } 371 } 372} 373 374static void ThrowingGetAccessor( 375 Local<String> name, 376 const v8::PropertyCallbackInfo<v8::Value>& info) { 377 ApiTestFuzzer::Fuzz(); 378 info.GetIsolate()->ThrowException(v8_str("g")); 379} 380 381 382static void ThrowingSetAccessor(Local<String> name, 383 Local<Value> value, 384 const v8::PropertyCallbackInfo<void>& info) { 385 info.GetIsolate()->ThrowException(value); 386} 387 388 389THREADED_TEST(Regress1054726) { 390 LocalContext env; 391 v8::Isolate* isolate = env->GetIsolate(); 392 v8::HandleScope scope(isolate); 393 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate); 394 obj->SetAccessor(v8_str("x"), 395 ThrowingGetAccessor, 396 ThrowingSetAccessor, 397 Local<Value>()); 398 399 env->Global()->Set(v8_str("obj"), obj->NewInstance()); 400 401 // Use the throwing property setter/getter in a loop to force 402 // the accessor ICs to be initialized. 403 v8::Handle<Value> result; 404 result = Script::Compile(v8_str( 405 "var result = '';" 406 "for (var i = 0; i < 5; i++) {" 407 " try { obj.x; } catch (e) { result += e; }" 408 "}; result"))->Run(); 409 CHECK_EQ(v8_str("ggggg"), result); 410 411 result = Script::Compile(String::NewFromUtf8( 412 isolate, 413 "var result = '';" 414 "for (var i = 0; i < 5; i++) {" 415 " try { obj.x = i; } catch (e) { result += e; }" 416 "}; result"))->Run(); 417 CHECK_EQ(v8_str("01234"), result); 418} 419 420 421static void AllocGetter(Local<String> name, 422 const v8::PropertyCallbackInfo<v8::Value>& info) { 423 ApiTestFuzzer::Fuzz(); 424 info.GetReturnValue().Set(v8::Array::New(info.GetIsolate(), 1000)); 425} 426 427 428THREADED_TEST(Gc) { 429 LocalContext env; 430 v8::Isolate* isolate = env->GetIsolate(); 431 v8::HandleScope scope(isolate); 432 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate); 433 obj->SetAccessor(v8_str("xxx"), AllocGetter); 434 env->Global()->Set(v8_str("obj"), obj->NewInstance()); 435 Script::Compile(String::NewFromUtf8( 436 isolate, 437 "var last = [];" 438 "for (var i = 0; i < 2048; i++) {" 439 " var result = obj.xxx;" 440 " result[0] = last;" 441 " last = result;" 442 "}"))->Run(); 443} 444 445 446static void StackCheck(Local<String> name, 447 const v8::PropertyCallbackInfo<v8::Value>& info) { 448 i::StackFrameIterator iter(reinterpret_cast<i::Isolate*>(info.GetIsolate())); 449 for (int i = 0; !iter.done(); i++) { 450 i::StackFrame* frame = iter.frame(); 451 CHECK(i != 0 || (frame->type() == i::StackFrame::EXIT)); 452 i::Code* code = frame->LookupCode(); 453 CHECK(code->IsCode()); 454 i::Address pc = frame->pc(); 455 CHECK(code->contains(pc)); 456 iter.Advance(); 457 } 458} 459 460 461THREADED_TEST(StackIteration) { 462 LocalContext env; 463 v8::Isolate* isolate = env->GetIsolate(); 464 v8::HandleScope scope(isolate); 465 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate); 466 i::StringStream::ClearMentionedObjectCache( 467 reinterpret_cast<i::Isolate*>(isolate)); 468 obj->SetAccessor(v8_str("xxx"), StackCheck); 469 env->Global()->Set(v8_str("obj"), obj->NewInstance()); 470 Script::Compile(String::NewFromUtf8( 471 isolate, 472 "function foo() {" 473 " return obj.xxx;" 474 "}" 475 "for (var i = 0; i < 100; i++) {" 476 " foo();" 477 "}"))->Run(); 478} 479 480 481static void AllocateHandles(Local<String> name, 482 const v8::PropertyCallbackInfo<v8::Value>& info) { 483 for (int i = 0; i < i::kHandleBlockSize + 1; i++) { 484 v8::Local<v8::Value>::New(info.GetIsolate(), name); 485 } 486 info.GetReturnValue().Set(v8::Integer::New(info.GetIsolate(), 100)); 487} 488 489 490THREADED_TEST(HandleScopeSegment) { 491 // Check that we can return values past popping of handle scope 492 // segments. 493 LocalContext env; 494 v8::Isolate* isolate = env->GetIsolate(); 495 v8::HandleScope scope(isolate); 496 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate); 497 obj->SetAccessor(v8_str("xxx"), AllocateHandles); 498 env->Global()->Set(v8_str("obj"), obj->NewInstance()); 499 v8::Handle<v8::Value> result = Script::Compile(String::NewFromUtf8( 500 isolate, 501 "var result;" 502 "for (var i = 0; i < 4; i++)" 503 " result = obj.xxx;" 504 "result;"))->Run(); 505 CHECK_EQ(100, result->Int32Value()); 506} 507 508 509void JSONStringifyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info) { 510 v8::Handle<v8::Array> array = v8::Array::New(info.GetIsolate(), 1); 511 array->Set(0, v8_str("regress")); 512 info.GetReturnValue().Set(array); 513} 514 515 516void JSONStringifyGetter(Local<String> name, 517 const v8::PropertyCallbackInfo<v8::Value>& info) { 518 info.GetReturnValue().Set(v8_str("crbug-161028")); 519} 520 521 522THREADED_TEST(JSONStringifyNamedInterceptorObject) { 523 LocalContext env; 524 v8::Isolate* isolate = env->GetIsolate(); 525 v8::HandleScope scope(isolate); 526 527 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate); 528 obj->SetNamedPropertyHandler( 529 JSONStringifyGetter, NULL, NULL, NULL, JSONStringifyEnumerator); 530 env->Global()->Set(v8_str("obj"), obj->NewInstance()); 531 v8::Handle<v8::String> expected = v8_str("{\"regress\":\"crbug-161028\"}"); 532 CHECK(CompileRun("JSON.stringify(obj)")->Equals(expected)); 533} 534 535 536static v8::Local<v8::Context> expected_current_context; 537static v8::Local<v8::Context> expected_calling_context; 538 539 540static void check_contexts(const v8::FunctionCallbackInfo<v8::Value>& info) { 541 ApiTestFuzzer::Fuzz(); 542 CHECK(expected_current_context == info.GetIsolate()->GetCurrentContext()); 543 CHECK(expected_calling_context == info.GetIsolate()->GetCallingContext()); 544} 545 546 547THREADED_TEST(AccessorPropertyCrossContext) { 548 LocalContext env; 549 v8::Isolate* isolate = env->GetIsolate(); 550 v8::HandleScope scope(isolate); 551 v8::Handle<v8::Function> fun = v8::Function::New(isolate, check_contexts); 552 LocalContext switch_context; 553 switch_context->Global()->Set(v8_str("fun"), fun); 554 v8::TryCatch try_catch; 555 expected_current_context = env.local(); 556 expected_calling_context = switch_context.local(); 557 CompileRun( 558 "var o = Object.create(null, { n: { get:fun } });" 559 "for (var i = 0; i < 10; i++) o.n;"); 560 CHECK(!try_catch.HasCaught()); 561} 562 563 564THREADED_TEST(GlobalObjectAccessor) { 565 LocalContext env; 566 v8::Isolate* isolate = env->GetIsolate(); 567 v8::HandleScope scope(isolate); 568 CompileRun( 569 "var set_value = 1;" 570 "Object.defineProperty(this.__proto__, 'x', {" 571 " get : function() { return this; }," 572 " set : function() { set_value = this; }" 573 "});" 574 "function getter() { return x; }" 575 "function setter() { x = 1; }" 576 "for (var i = 0; i < 4; i++) { getter(); setter(); }"); 577 CHECK(v8::Utils::OpenHandle(*CompileRun("getter()"))->IsJSGlobalProxy()); 578 CHECK(v8::Utils::OpenHandle(*CompileRun("set_value"))->IsJSGlobalProxy()); 579} 580