1304
// Helper functions for Interceptor/Accessor interaction tests
1306
Handle<Value> SimpleAccessorGetter(Local<String> name,
1307
const AccessorInfo& info) {
1308
Handle<Object> self = info.This();
1309
return self->Get(String::Concat(v8_str("accessor_"), name));
1312
void SimpleAccessorSetter(Local<String> name, Local<Value> value,
1313
const AccessorInfo& info) {
1314
Handle<Object> self = info.This();
1315
self->Set(String::Concat(v8_str("accessor_"), name), value);
1318
Handle<Value> EmptyInterceptorGetter(Local<String> name,
1319
const AccessorInfo& info) {
1320
return Handle<Value>();
1323
Handle<Value> EmptyInterceptorSetter(Local<String> name,
1325
const AccessorInfo& info) {
1326
return Handle<Value>();
1329
Handle<Value> InterceptorGetter(Local<String> name,
1330
const AccessorInfo& info) {
1331
// Intercept names that start with 'interceptor_'.
1332
String::AsciiValue ascii(name);
1333
char* name_str = *ascii;
1334
char prefix[] = "interceptor_";
1336
for (i = 0; name_str[i] && prefix[i]; ++i) {
1337
if (name_str[i] != prefix[i]) return Handle<Value>();
1339
Handle<Object> self = info.This();
1340
return self->GetHiddenValue(v8_str(name_str + i));
1343
Handle<Value> InterceptorSetter(Local<String> name,
1345
const AccessorInfo& info) {
1346
// Intercept accesses that set certain integer values.
1347
if (value->IsInt32() && value->Int32Value() < 10000) {
1348
Handle<Object> self = info.This();
1349
self->SetHiddenValue(name, value);
1352
return Handle<Value>();
1355
void AddAccessor(Handle<FunctionTemplate> templ,
1356
Handle<String> name,
1357
v8::AccessorGetter getter,
1358
v8::AccessorSetter setter) {
1359
templ->PrototypeTemplate()->SetAccessor(name, getter, setter);
1362
void AddInterceptor(Handle<FunctionTemplate> templ,
1363
v8::NamedPropertyGetter getter,
1364
v8::NamedPropertySetter setter) {
1365
templ->InstanceTemplate()->SetNamedPropertyHandler(getter, setter);
1368
THREADED_TEST(EmptyInterceptorDoesNotShadowAccessors) {
1369
v8::HandleScope scope;
1370
Handle<FunctionTemplate> parent = FunctionTemplate::New();
1371
Handle<FunctionTemplate> child = FunctionTemplate::New();
1372
child->Inherit(parent);
1373
AddAccessor(parent, v8_str("age"),
1374
SimpleAccessorGetter, SimpleAccessorSetter);
1375
AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
1377
env->Global()->Set(v8_str("Child"), child->GetFunction());
1378
CompileRun("var child = new Child;"
1380
ExpectBoolean("child.hasOwnProperty('age')", false);
1381
ExpectInt32("child.age", 10);
1382
ExpectInt32("child.accessor_age", 10);
1385
THREADED_TEST(EmptyInterceptorDoesNotShadowJSAccessors) {
1386
v8::HandleScope scope;
1387
Handle<FunctionTemplate> parent = FunctionTemplate::New();
1388
Handle<FunctionTemplate> child = FunctionTemplate::New();
1389
child->Inherit(parent);
1390
AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
1392
env->Global()->Set(v8_str("Child"), child->GetFunction());
1393
CompileRun("var child = new Child;"
1394
"var parent = child.__proto__;"
1395
"Object.defineProperty(parent, 'age', "
1396
" {get: function(){ return this.accessor_age; }, "
1397
" set: function(v){ this.accessor_age = v; }, "
1398
" enumerable: true, configurable: true});"
1400
ExpectBoolean("child.hasOwnProperty('age')", false);
1401
ExpectInt32("child.age", 10);
1402
ExpectInt32("child.accessor_age", 10);
1405
THREADED_TEST(EmptyInterceptorDoesNotAffectJSProperties) {
1406
v8::HandleScope scope;
1407
Handle<FunctionTemplate> parent = FunctionTemplate::New();
1408
Handle<FunctionTemplate> child = FunctionTemplate::New();
1409
child->Inherit(parent);
1410
AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
1412
env->Global()->Set(v8_str("Child"), child->GetFunction());
1413
CompileRun("var child = new Child;"
1414
"var parent = child.__proto__;"
1415
"parent.name = 'Alice';");
1416
ExpectBoolean("child.hasOwnProperty('name')", false);
1417
ExpectString("child.name", "Alice");
1418
CompileRun("child.name = 'Bob';");
1419
ExpectString("child.name", "Bob");
1420
ExpectBoolean("child.hasOwnProperty('name')", true);
1421
ExpectString("parent.name", "Alice");
1424
THREADED_TEST(SwitchFromInterceptorToAccessor) {
1425
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"),
1430
SimpleAccessorGetter, SimpleAccessorSetter);
1431
AddInterceptor(child, InterceptorGetter, InterceptorSetter);
1433
env->Global()->Set(v8_str("Child"), child->GetFunction());
1434
CompileRun("var child = new Child;"
1435
"function setAge(i){ child.age = i; };"
1436
"for(var i = 0; i <= 10000; i++) setAge(i);");
1437
// All i < 10000 go to the interceptor.
1438
ExpectInt32("child.interceptor_age", 9999);
1439
// The last i goes to the accessor.
1440
ExpectInt32("child.accessor_age", 10000);
1443
THREADED_TEST(SwitchFromAccessorToInterceptor) {
1444
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);
1462
THREADED_TEST(SwitchFromInterceptorToProperty) {
1463
v8::HandleScope scope;
1464
Handle<FunctionTemplate> parent = FunctionTemplate::New();
1465
Handle<FunctionTemplate> child = FunctionTemplate::New();
1466
child->Inherit(parent);
1467
AddInterceptor(child, InterceptorGetter, InterceptorSetter);
1469
env->Global()->Set(v8_str("Child"), child->GetFunction());
1470
CompileRun("var child = new Child;"
1471
"function setAge(i){ child.age = i; };"
1472
"for(var i = 0; i <= 10000; i++) setAge(i);");
1473
// All i < 10000 go to the interceptor.
1474
ExpectInt32("child.interceptor_age", 9999);
1475
// The last i goes to child's own property.
1476
ExpectInt32("child.age", 10000);
1479
THREADED_TEST(SwitchFromPropertyToInterceptor) {
1480
v8::HandleScope scope;
1481
Handle<FunctionTemplate> parent = FunctionTemplate::New();
1482
Handle<FunctionTemplate> child = FunctionTemplate::New();
1483
child->Inherit(parent);
1484
AddInterceptor(child, InterceptorGetter, InterceptorSetter);
1486
env->Global()->Set(v8_str("Child"), child->GetFunction());
1487
CompileRun("var child = new Child;"
1488
"function setAge(i){ child.age = i; };"
1489
"for(var i = 20000; i >= 9999; i--) setAge(i);");
1490
// All i >= 10000 go to child's own property.
1491
ExpectInt32("child.age", 10000);
1492
// The last i goes to the interceptor.
1493
ExpectInt32("child.interceptor_age", 9999);
1298
1496
THREADED_TEST(NamedPropertyHandlerGetter) {
1299
1497
echo_named_call_count = 0;
4520
static const char* kEmbeddedExtensionSource =
4521
"function Ret54321(){return 54321;}~~@@$"
4522
"$%% THIS IS A SERIES OF NON-NULL-TERMINATED STRINGS.";
4523
static const int kEmbeddedExtensionSourceValidLen = 34;
4526
THREADED_TEST(ExtensionMissingSourceLength) {
4527
v8::HandleScope handle_scope;
4528
v8::RegisterExtension(new Extension("srclentest_fail",
4529
kEmbeddedExtensionSource));
4530
const char* extension_names[] = { "srclentest_fail" };
4531
v8::ExtensionConfiguration extensions(1, extension_names);
4532
v8::Handle<Context> context = Context::New(&extensions);
4533
CHECK_EQ(0, *context);
4537
THREADED_TEST(ExtensionWithSourceLength) {
4538
for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
4539
source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
4540
v8::HandleScope handle_scope;
4541
i::ScopedVector<char> extension_name(32);
4542
i::OS::SNPrintF(extension_name, "ext #%d", source_len);
4543
v8::RegisterExtension(new Extension(extension_name.start(),
4544
kEmbeddedExtensionSource, 0, 0,
4546
const char* extension_names[1] = { extension_name.start() };
4547
v8::ExtensionConfiguration extensions(1, extension_names);
4548
v8::Handle<Context> context = Context::New(&extensions);
4549
if (source_len == kEmbeddedExtensionSourceValidLen) {
4550
Context::Scope lock(context);
4551
v8::Handle<Value> result = Script::Compile(v8_str("Ret54321()"))->Run();
4552
CHECK_EQ(v8::Integer::New(54321), result);
4554
// Anything but exactly the right length should fail to compile.
4555
CHECK_EQ(0, *context);
4308
4561
static const char* kEvalExtensionSource1 =
4309
4562
"function UseEval1() {"
5187
5440
THREADED_TEST(StringWrite) {
5441
LocalContext context;
5188
5442
v8::HandleScope scope;
5189
5443
v8::Handle<String> str = v8_str("abcde");
5190
5444
// abc<Icelandic eth><Unicode snowman>.
5191
5445
v8::Handle<String> str2 = v8_str("abc\303\260\342\230\203");
5446
const int kStride = 4; // Must match stride in for loops in JS below.
5449
"for (var i = 0; i < 0xd800; i += 4) {"
5450
" left = left + String.fromCharCode(i);"
5454
"for (var i = 0; i < 0xd800; i += 4) {"
5455
" right = String.fromCharCode(i) + right;"
5457
v8::Handle<v8::Object> global = Context::GetCurrent()->Global();
5458
Handle<String> left_tree = global->Get(v8_str("left")).As<String>();
5459
Handle<String> right_tree = global->Get(v8_str("right")).As<String>();
5193
5461
CHECK_EQ(5, str2->Length());
5462
CHECK_EQ(0xd800 / kStride, left_tree->Length());
5463
CHECK_EQ(0xd800 / kStride, right_tree->Length());
5466
char utf8buf[0xd800 * 3];
5197
5467
uint16_t wbuf[100];
5201
memset(utf8buf, 0x1, sizeof(utf8buf));
5471
memset(utf8buf, 0x1, 1000);
5202
5472
len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
5203
5473
CHECK_EQ(9, len);
5204
5474
CHECK_EQ(5, charlen);
5205
5475
CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
5207
memset(utf8buf, 0x1, sizeof(utf8buf));
5477
memset(utf8buf, 0x1, 1000);
5208
5478
len = str2->WriteUtf8(utf8buf, 8, &charlen);
5209
5479
CHECK_EQ(8, len);
5210
5480
CHECK_EQ(5, charlen);
5211
5481
CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203\1", 9));
5213
memset(utf8buf, 0x1, sizeof(utf8buf));
5483
memset(utf8buf, 0x1, 1000);
5214
5484
len = str2->WriteUtf8(utf8buf, 7, &charlen);
5215
5485
CHECK_EQ(5, len);
5216
5486
CHECK_EQ(4, charlen);
5217
5487
CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
5219
memset(utf8buf, 0x1, sizeof(utf8buf));
5489
memset(utf8buf, 0x1, 1000);
5220
5490
len = str2->WriteUtf8(utf8buf, 6, &charlen);
5221
5491
CHECK_EQ(5, len);
5222
5492
CHECK_EQ(4, charlen);
5223
5493
CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
5225
memset(utf8buf, 0x1, sizeof(utf8buf));
5495
memset(utf8buf, 0x1, 1000);
5226
5496
len = str2->WriteUtf8(utf8buf, 5, &charlen);
5227
5497
CHECK_EQ(5, len);
5228
5498
CHECK_EQ(4, charlen);
5229
5499
CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
5231
memset(utf8buf, 0x1, sizeof(utf8buf));
5501
memset(utf8buf, 0x1, 1000);
5232
5502
len = str2->WriteUtf8(utf8buf, 4, &charlen);
5233
5503
CHECK_EQ(3, len);
5234
5504
CHECK_EQ(3, charlen);
5235
5505
CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
5237
memset(utf8buf, 0x1, sizeof(utf8buf));
5507
memset(utf8buf, 0x1, 1000);
5238
5508
len = str2->WriteUtf8(utf8buf, 3, &charlen);
5239
5509
CHECK_EQ(3, len);
5240
5510
CHECK_EQ(3, charlen);
5241
5511
CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
5243
memset(utf8buf, 0x1, sizeof(utf8buf));
5513
memset(utf8buf, 0x1, 1000);
5244
5514
len = str2->WriteUtf8(utf8buf, 2, &charlen);
5245
5515
CHECK_EQ(2, len);
5246
5516
CHECK_EQ(2, charlen);
5247
5517
CHECK_EQ(0, strncmp(utf8buf, "ab\1", 3));
5519
memset(utf8buf, 0x1, sizeof(utf8buf));
5520
len = left_tree->Utf8Length();
5522
(0x80 + (0x800 - 0x80) * 2 + (0xd800 - 0x800) * 3) / kStride;
5523
CHECK_EQ(utf8_expected, len);
5524
len = left_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
5525
CHECK_EQ(utf8_expected, len);
5526
CHECK_EQ(0xd800 / kStride, charlen);
5527
CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[utf8_expected - 3]));
5528
CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[utf8_expected - 2]));
5529
CHECK_EQ(0xc0 - kStride,
5530
static_cast<unsigned char>(utf8buf[utf8_expected - 1]));
5531
CHECK_EQ(1, utf8buf[utf8_expected]);
5533
memset(utf8buf, 0x1, sizeof(utf8buf));
5534
len = right_tree->Utf8Length();
5535
CHECK_EQ(utf8_expected, len);
5536
len = right_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
5537
CHECK_EQ(utf8_expected, len);
5538
CHECK_EQ(0xd800 / kStride, charlen);
5539
CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[0]));
5540
CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[1]));
5541
CHECK_EQ(0xc0 - kStride, static_cast<unsigned char>(utf8buf[2]));
5542
CHECK_EQ(1, utf8buf[utf8_expected]);
5249
5544
memset(buf, 0x1, sizeof(buf));
5250
5545
memset(wbuf, 0x1, sizeof(wbuf));
5251
5546
len = str->WriteAscii(buf);
7456
// Getting property names of an object with a prototype chain that
7457
// triggers dictionary elements in GetLocalPropertyNames() shouldn't
7458
// crash the runtime.
7459
THREADED_TEST(Regress91517) {
7460
i::FLAG_allow_natives_syntax = true;
7461
v8::HandleScope handle_scope;
7462
LocalContext context;
7464
Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
7465
t1->SetHiddenPrototype(true);
7466
t1->InstanceTemplate()->Set(v8_str("foo"), v8_num(1));
7467
Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
7468
t2->SetHiddenPrototype(true);
7469
t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2));
7470
t2->InstanceTemplate()->Set(v8_str("objects"), v8::Object::New());
7471
t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2));
7472
Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New();
7473
t3->SetHiddenPrototype(true);
7474
t3->InstanceTemplate()->Set(v8_str("boo"), v8_num(3));
7475
Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New();
7476
t4->InstanceTemplate()->Set(v8_str("baz"), v8_num(4));
7478
// Force dictionary-based properties.
7479
i::ScopedVector<char> name_buf(1024);
7480
for (int i = 1; i <= 1000; i++) {
7481
i::OS::SNPrintF(name_buf, "sdf%d", i);
7482
t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2));
7485
Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
7486
Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
7487
Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
7488
Local<v8::Object> o4 = t4->GetFunction()->NewInstance();
7490
// Create prototype chain of hidden prototypes.
7491
CHECK(o4->SetPrototype(o3));
7492
CHECK(o3->SetPrototype(o2));
7493
CHECK(o2->SetPrototype(o1));
7495
// Call the runtime version of GetLocalPropertyNames() on the natively
7496
// created object through JavaScript.
7497
context->Global()->Set(v8_str("obj"), o4);
7498
CompileRun("var names = %GetLocalPropertyNames(obj);");
7500
ExpectInt32("names.length", 1006);
7501
ExpectTrue("names.indexOf(\"baz\") >= 0");
7502
ExpectTrue("names.indexOf(\"boo\") >= 0");
7503
ExpectTrue("names.indexOf(\"foo\") >= 0");
7504
ExpectTrue("names.indexOf(\"fuz1\") >= 0");
7505
ExpectTrue("names.indexOf(\"fuz2\") >= 0");
7506
ExpectFalse("names[1005] == undefined");
7161
7510
THREADED_TEST(FunctionReadOnlyPrototype) {
7162
7511
v8::HandleScope handle_scope;
7163
7512
LocalContext context;
13817
THREADED_TEST(ScriptColumnNumber) {
13818
v8::HandleScope scope;
13820
v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"),
13821
v8::Integer::New(3), v8::Integer::New(2));
13822
v8::Handle<v8::String> script = v8::String::New(
13823
"function foo() {}\n\n function bar() {}");
13824
v8::Script::Compile(script, &origin)->Run();
13825
v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
13826
env->Global()->Get(v8::String::New("foo")));
13827
v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
13828
env->Global()->Get(v8::String::New("bar")));
13829
CHECK_EQ(14, foo->GetScriptColumnNumber());
13830
CHECK_EQ(17, bar->GetScriptColumnNumber());
13834
THREADED_TEST(FunctionGetScriptId) {
13835
v8::HandleScope scope;
13837
v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"),
13838
v8::Integer::New(3), v8::Integer::New(2));
13839
v8::Handle<v8::String> scriptSource = v8::String::New(
13840
"function foo() {}\n\n function bar() {}");
13841
v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin));
13843
v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
13844
env->Global()->Get(v8::String::New("foo")));
13845
v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
13846
env->Global()->Get(v8::String::New("bar")));
13847
CHECK_EQ(script->Id(), foo->GetScriptId());
13848
CHECK_EQ(script->Id(), bar->GetScriptId());
13437
13852
static v8::Handle<Value> GetterWhichReturns42(Local<String> name,
13438
13853
const AccessorInfo& info) {
13439
13854
return v8_num(42);
13604
14019
v8::V8::AddGCEpilogueCallback(EpilogueCallback);
13605
14020
CHECK_EQ(0, prologue_call_count);
13606
14021
CHECK_EQ(0, epilogue_call_count);
13607
HEAP->CollectAllGarbage(false);
14022
HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
13608
14023
CHECK_EQ(1, prologue_call_count);
13609
14024
CHECK_EQ(1, epilogue_call_count);
13610
14025
v8::V8::AddGCPrologueCallback(PrologueCallbackSecond);
13611
14026
v8::V8::AddGCEpilogueCallback(EpilogueCallbackSecond);
13612
HEAP->CollectAllGarbage(false);
14027
HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
13613
14028
CHECK_EQ(2, prologue_call_count);
13614
14029
CHECK_EQ(2, epilogue_call_count);
13615
14030
CHECK_EQ(1, prologue_call_count_second);
13616
14031
CHECK_EQ(1, epilogue_call_count_second);
13617
14032
v8::V8::RemoveGCPrologueCallback(PrologueCallback);
13618
14033
v8::V8::RemoveGCEpilogueCallback(EpilogueCallback);
13619
HEAP->CollectAllGarbage(false);
14034
HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
13620
14035
CHECK_EQ(2, prologue_call_count);
13621
14036
CHECK_EQ(2, epilogue_call_count);
13622
14037
CHECK_EQ(2, prologue_call_count_second);
13623
14038
CHECK_EQ(2, epilogue_call_count_second);
13624
14039
v8::V8::RemoveGCPrologueCallback(PrologueCallbackSecond);
13625
14040
v8::V8::RemoveGCEpilogueCallback(EpilogueCallbackSecond);
13626
HEAP->CollectAllGarbage(false);
14041
HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
13627
14042
CHECK_EQ(2, prologue_call_count);
13628
14043
CHECK_EQ(2, epilogue_call_count);
13629
14044
CHECK_EQ(2, prologue_call_count_second);