1424
1423
THREADED_TEST(SwitchFromInterceptorToAccessor) {
1425
1424
v8::HandleScope scope;
1426
Handle<FunctionTemplate> parent = FunctionTemplate::New();
1427
Handle<FunctionTemplate> child = FunctionTemplate::New();
1428
child->Inherit(parent);
1429
AddAccessor(parent, v8_str("age"),
1425
Handle<FunctionTemplate> templ = FunctionTemplate::New();
1426
AddAccessor(templ, v8_str("age"),
1430
1427
SimpleAccessorGetter, SimpleAccessorSetter);
1431
AddInterceptor(child, InterceptorGetter, InterceptorSetter);
1428
AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
1432
1429
LocalContext env;
1433
env->Global()->Set(v8_str("Child"), child->GetFunction());
1434
CompileRun("var child = new Child;"
1435
"function setAge(i){ child.age = i; };"
1430
env->Global()->Set(v8_str("Obj"), templ->GetFunction());
1431
CompileRun("var obj = new Obj;"
1432
"function setAge(i){ obj.age = i; };"
1436
1433
"for(var i = 0; i <= 10000; i++) setAge(i);");
1437
1434
// All i < 10000 go to the interceptor.
1438
ExpectInt32("child.interceptor_age", 9999);
1435
ExpectInt32("obj.interceptor_age", 9999);
1439
1436
// The last i goes to the accessor.
1440
ExpectInt32("child.accessor_age", 10000);
1437
ExpectInt32("obj.accessor_age", 10000);
1443
1440
THREADED_TEST(SwitchFromAccessorToInterceptor) {
1444
1441
v8::HandleScope scope;
1445
Handle<FunctionTemplate> parent = FunctionTemplate::New();
1446
Handle<FunctionTemplate> child = FunctionTemplate::New();
1447
child->Inherit(parent);
1448
AddAccessor(parent, v8_str("age"),
1449
SimpleAccessorGetter, SimpleAccessorSetter);
1450
AddInterceptor(child, InterceptorGetter, InterceptorSetter);
1452
env->Global()->Set(v8_str("Child"), child->GetFunction());
1453
CompileRun("var child = new Child;"
1454
"function setAge(i){ child.age = i; };"
1455
"for(var i = 20000; i >= 9999; i--) setAge(i);");
1456
// All i >= 10000 go to the accessor.
1457
ExpectInt32("child.accessor_age", 10000);
1458
// The last i goes to the interceptor.
1459
ExpectInt32("child.interceptor_age", 9999);
1442
Handle<FunctionTemplate> templ = FunctionTemplate::New();
1443
AddAccessor(templ, v8_str("age"),
1444
SimpleAccessorGetter, SimpleAccessorSetter);
1445
AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
1447
env->Global()->Set(v8_str("Obj"), templ->GetFunction());
1448
CompileRun("var obj = new Obj;"
1449
"function setAge(i){ obj.age = i; };"
1450
"for(var i = 20000; i >= 9999; i--) setAge(i);");
1451
// All i >= 10000 go to the accessor.
1452
ExpectInt32("obj.accessor_age", 10000);
1453
// The last i goes to the interceptor.
1454
ExpectInt32("obj.interceptor_age", 9999);
1457
THREADED_TEST(SwitchFromInterceptorToAccessorWithInheritance) {
1458
v8::HandleScope scope;
1459
Handle<FunctionTemplate> parent = FunctionTemplate::New();
1460
Handle<FunctionTemplate> child = FunctionTemplate::New();
1461
child->Inherit(parent);
1462
AddAccessor(parent, v8_str("age"),
1463
SimpleAccessorGetter, SimpleAccessorSetter);
1464
AddInterceptor(child, InterceptorGetter, InterceptorSetter);
1466
env->Global()->Set(v8_str("Child"), child->GetFunction());
1467
CompileRun("var child = new Child;"
1468
"function setAge(i){ child.age = i; };"
1469
"for(var i = 0; i <= 10000; i++) setAge(i);");
1470
// All i < 10000 go to the interceptor.
1471
ExpectInt32("child.interceptor_age", 9999);
1472
// The last i goes to the accessor.
1473
ExpectInt32("child.accessor_age", 10000);
1476
THREADED_TEST(SwitchFromAccessorToInterceptorWithInheritance) {
1477
v8::HandleScope scope;
1478
Handle<FunctionTemplate> parent = FunctionTemplate::New();
1479
Handle<FunctionTemplate> child = FunctionTemplate::New();
1480
child->Inherit(parent);
1481
AddAccessor(parent, v8_str("age"),
1482
SimpleAccessorGetter, SimpleAccessorSetter);
1483
AddInterceptor(child, InterceptorGetter, InterceptorSetter);
1485
env->Global()->Set(v8_str("Child"), child->GetFunction());
1486
CompileRun("var child = new Child;"
1487
"function setAge(i){ child.age = i; };"
1488
"for(var i = 20000; i >= 9999; i--) setAge(i);");
1489
// All i >= 10000 go to the accessor.
1490
ExpectInt32("child.accessor_age", 10000);
1491
// The last i goes to the interceptor.
1492
ExpectInt32("child.interceptor_age", 9999);
1495
THREADED_TEST(SwitchFromInterceptorToJSAccessor) {
1496
v8::HandleScope scope;
1497
Handle<FunctionTemplate> templ = FunctionTemplate::New();
1498
AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
1500
env->Global()->Set(v8_str("Obj"), templ->GetFunction());
1501
CompileRun("var obj = new Obj;"
1502
"function setter(i) { this.accessor_age = i; };"
1503
"function getter() { return this.accessor_age; };"
1504
"function setAge(i) { obj.age = i; };"
1505
"Object.defineProperty(obj, 'age', { get:getter, set:setter });"
1506
"for(var i = 0; i <= 10000; i++) setAge(i);");
1507
// All i < 10000 go to the interceptor.
1508
ExpectInt32("obj.interceptor_age", 9999);
1509
// The last i goes to the JavaScript accessor.
1510
ExpectInt32("obj.accessor_age", 10000);
1511
// The installed JavaScript getter is still intact.
1512
// This last part is a regression test for issue 1651 and relies on the fact
1513
// that both interceptor and accessor are being installed on the same object.
1514
ExpectInt32("obj.age", 10000);
1515
ExpectBoolean("obj.hasOwnProperty('age')", true);
1516
ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
1519
THREADED_TEST(SwitchFromJSAccessorToInterceptor) {
1520
v8::HandleScope scope;
1521
Handle<FunctionTemplate> templ = FunctionTemplate::New();
1522
AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
1524
env->Global()->Set(v8_str("Obj"), templ->GetFunction());
1525
CompileRun("var obj = new Obj;"
1526
"function setter(i) { this.accessor_age = i; };"
1527
"function getter() { return this.accessor_age; };"
1528
"function setAge(i) { obj.age = i; };"
1529
"Object.defineProperty(obj, 'age', { get:getter, set:setter });"
1530
"for(var i = 20000; i >= 9999; i--) setAge(i);");
1531
// All i >= 10000 go to the accessor.
1532
ExpectInt32("obj.accessor_age", 10000);
1533
// The last i goes to the interceptor.
1534
ExpectInt32("obj.interceptor_age", 9999);
1535
// The installed JavaScript getter is still intact.
1536
// This last part is a regression test for issue 1651 and relies on the fact
1537
// that both interceptor and accessor are being installed on the same object.
1538
ExpectInt32("obj.age", 10000);
1539
ExpectBoolean("obj.hasOwnProperty('age')", true);
1540
ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
1462
1543
THREADED_TEST(SwitchFromInterceptorToProperty) {
13726
class VisitorImpl : public v8::ExternalResourceVisitor {
13728
VisitorImpl(TestResource* r1, TestResource* r2)
13731
found_resource1_(false),
13732
found_resource2_(false) {}
13733
virtual ~VisitorImpl() {}
13734
virtual void VisitExternalString(v8::Handle<v8::String> string) {
13735
if (!string->IsExternal()) {
13736
CHECK(string->IsExternalAscii());
13739
v8::String::ExternalStringResource* resource =
13740
string->GetExternalStringResource();
13742
if (resource1_ == resource) {
13743
CHECK(!found_resource1_);
13744
found_resource1_ = true;
13746
if (resource2_ == resource) {
13747
CHECK(!found_resource2_);
13748
found_resource2_ = true;
13751
void CheckVisitedResources() {
13752
CHECK(found_resource1_);
13753
CHECK(found_resource2_);
13757
v8::String::ExternalStringResource* resource1_;
13758
v8::String::ExternalStringResource* resource2_;
13759
bool found_resource1_;
13760
bool found_resource2_;
13763
TEST(VisitExternalStrings) {
13764
v8::HandleScope scope;
13766
const char* string = "Some string";
13767
uint16_t* two_byte_string = AsciiToTwoByteString(string);
13768
TestResource* resource1 = new TestResource(two_byte_string);
13769
v8::Local<v8::String> string1 = v8::String::NewExternal(resource1);
13770
TestResource* resource2 = new TestResource(two_byte_string);
13771
v8::Local<v8::String> string2 = v8::String::NewExternal(resource2);
13773
// We need to add usages for string1 and string2 to avoid warnings in GCC 4.7
13774
CHECK(string1->IsExternal());
13775
CHECK(string2->IsExternal());
13777
VisitorImpl visitor(resource1, resource2);
13778
v8::V8::VisitExternalResources(&visitor);
13779
visitor.CheckVisitedResources();
13539
13783
static double DoubleFromBits(uint64_t value) {
13540
13784
double target;
13541
13785
memcpy(&target, &value, sizeof(target));
15598
15854
foreign_context.Dispose();
15858
uint8_t callback_fired = 0;
15861
void CallCompletedCallback1() {
15862
i::OS::Print("Firing callback 1.\n");
15863
callback_fired ^= 1; // Toggle first bit.
15867
void CallCompletedCallback2() {
15868
i::OS::Print("Firing callback 2.\n");
15869
callback_fired ^= 2; // Toggle second bit.
15873
Handle<Value> RecursiveCall(const Arguments& args) {
15874
int32_t level = args[0]->Int32Value();
15877
i::OS::Print("Entering recursion level %d.\n", level);
15879
i::Vector<char> script_vector(script, sizeof(script));
15880
i::OS::SNPrintF(script_vector, "recursion(%d)", level);
15881
CompileRun(script_vector.start());
15882
i::OS::Print("Leaving recursion level %d.\n", level);
15883
CHECK_EQ(0, callback_fired);
15885
i::OS::Print("Recursion ends.\n");
15886
CHECK_EQ(0, callback_fired);
15888
return Undefined();
15892
TEST(CallCompletedCallback) {
15893
v8::HandleScope scope;
15895
v8::Handle<v8::FunctionTemplate> recursive_runtime =
15896
v8::FunctionTemplate::New(RecursiveCall);
15897
env->Global()->Set(v8_str("recursion"),
15898
recursive_runtime->GetFunction());
15899
// Adding the same callback a second time has no effect.
15900
v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
15901
v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
15902
v8::V8::AddCallCompletedCallback(CallCompletedCallback2);
15903
i::OS::Print("--- Script (1) ---\n");
15904
Local<Script> script =
15905
v8::Script::Compile(v8::String::New("recursion(0)"));
15907
CHECK_EQ(3, callback_fired);
15909
i::OS::Print("\n--- Script (2) ---\n");
15910
callback_fired = 0;
15911
v8::V8::RemoveCallCompletedCallback(CallCompletedCallback1);
15913
CHECK_EQ(2, callback_fired);
15915
i::OS::Print("\n--- Function ---\n");
15916
callback_fired = 0;
15917
Local<Function> recursive_function =
15918
Local<Function>::Cast(env->Global()->Get(v8_str("recursion")));
15919
v8::Handle<Value> args[] = { v8_num(0) };
15920
recursive_function->Call(env->Global(), 1, args);
15921
CHECK_EQ(2, callback_fired);
15925
void CallCompletedCallbackNoException() {
15926
v8::HandleScope scope;
15927
CompileRun("1+1;");
15931
void CallCompletedCallbackException() {
15932
v8::HandleScope scope;
15933
CompileRun("throw 'second exception';");
15937
TEST(CallCompletedCallbackOneException) {
15938
v8::HandleScope scope;
15940
v8::V8::AddCallCompletedCallback(CallCompletedCallbackNoException);
15941
CompileRun("throw 'exception';");
15945
TEST(CallCompletedCallbackTwoExceptions) {
15946
v8::HandleScope scope;
15948
v8::V8::AddCallCompletedCallback(CallCompletedCallbackException);
15949
CompileRun("throw 'first exception';");