summaryrefslogtreecommitdiff
path: root/deps/v8/test/cctest/test-api.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/test/cctest/test-api.cc')
-rw-r--r--deps/v8/test/cctest/test-api.cc971
1 files changed, 777 insertions, 194 deletions
diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc
index 9ddc9db71d..0330ac892f 100644
--- a/deps/v8/test/cctest/test-api.cc
+++ b/deps/v8/test/cctest/test-api.cc
@@ -63,6 +63,7 @@ using ::v8::FunctionTemplate;
using ::v8::Handle;
using ::v8::HandleScope;
using ::v8::Local;
+using ::v8::Name;
using ::v8::Message;
using ::v8::MessageCallback;
using ::v8::Object;
@@ -71,6 +72,7 @@ using ::v8::Persistent;
using ::v8::Script;
using ::v8::StackTrace;
using ::v8::String;
+using ::v8::Symbol;
using ::v8::TryCatch;
using ::v8::Undefined;
using ::v8::UniqueId;
@@ -128,19 +130,18 @@ static void SignatureCallback(
// Tests that call v8::V8::Dispose() cannot be threaded.
-TEST(InitializeAndDisposeOnce) {
+UNINITIALIZED_TEST(InitializeAndDisposeOnce) {
CHECK(v8::V8::Initialize());
CHECK(v8::V8::Dispose());
}
// Tests that call v8::V8::Dispose() cannot be threaded.
-TEST(InitializeAndDisposeMultiple) {
+UNINITIALIZED_TEST(InitializeAndDisposeMultiple) {
for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
- // TODO(mstarzinger): This should fail gracefully instead of asserting.
- // for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
+ for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
}
@@ -261,7 +262,7 @@ THREADED_TEST(ReceiverSignature) {
const char* test_objects[] = {
"fun_instance", "sub_fun_instance", "obj", "unrel" };
unsigned bad_signature_start_offset = 2;
- for (unsigned i = 0; i < ARRAY_SIZE(test_objects); i++) {
+ for (unsigned i = 0; i < arraysize(test_objects); i++) {
i::ScopedVector<char> source(200);
i::SNPrintF(
source, "var test_object = %s; test_object", test_objects[i]);
@@ -436,16 +437,16 @@ class TestResource: public String::ExternalStringResource {
};
-class TestAsciiResource: public String::ExternalAsciiStringResource {
+class TestOneByteResource : public String::ExternalOneByteStringResource {
public:
- explicit TestAsciiResource(const char* data, int* counter = NULL,
- size_t offset = 0)
+ explicit TestOneByteResource(const char* data, int* counter = NULL,
+ size_t offset = 0)
: orig_data_(data),
data_(data + offset),
length_(strlen(data) - offset),
counter_(counter) {}
- ~TestAsciiResource() {
+ ~TestOneByteResource() {
i::DeleteArray(orig_data_);
if (counter_ != NULL) ++*counter_;
}
@@ -495,22 +496,22 @@ THREADED_TEST(ScriptUsingStringResource) {
}
-THREADED_TEST(ScriptUsingAsciiStringResource) {
+THREADED_TEST(ScriptUsingOneByteStringResource) {
int dispose_count = 0;
const char* c_source = "1 + 2 * 3";
{
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
- TestAsciiResource* resource = new TestAsciiResource(i::StrDup(c_source),
- &dispose_count);
+ TestOneByteResource* resource =
+ new TestOneByteResource(i::StrDup(c_source), &dispose_count);
Local<String> source = String::NewExternal(env->GetIsolate(), resource);
- CHECK(source->IsExternalAscii());
+ CHECK(source->IsExternalOneByte());
CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
- source->GetExternalAsciiStringResource());
+ source->GetExternalOneByteStringResource());
String::Encoding encoding = String::UNKNOWN_ENCODING;
CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
source->GetExternalStringResourceBase(&encoding));
- CHECK_EQ(String::ASCII_ENCODING, encoding);
+ CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
Local<Script> script = v8_compile(source);
Local<Value> value = script->Run();
CHECK(value->IsNumber());
@@ -536,10 +537,10 @@ THREADED_TEST(ScriptMakingExternalString) {
CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
CHECK_EQ(source->IsExternal(), false);
- CHECK_EQ(source->IsExternalAscii(), false);
+ CHECK_EQ(source->IsExternalOneByte(), false);
String::Encoding encoding = String::UNKNOWN_ENCODING;
CHECK_EQ(NULL, source->GetExternalStringResourceBase(&encoding));
- CHECK_EQ(String::ASCII_ENCODING, encoding);
+ CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
bool success = source->MakeExternal(new TestResource(two_byte_source,
&dispose_count));
CHECK(success);
@@ -556,7 +557,7 @@ THREADED_TEST(ScriptMakingExternalString) {
}
-THREADED_TEST(ScriptMakingExternalAsciiString) {
+THREADED_TEST(ScriptMakingExternalOneByteString) {
int dispose_count = 0;
const char* c_source = "1 + 2 * 3";
{
@@ -567,7 +568,7 @@ THREADED_TEST(ScriptMakingExternalAsciiString) {
CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
bool success = source->MakeExternal(
- new TestAsciiResource(i::StrDup(c_source), &dispose_count));
+ new TestOneByteResource(i::StrDup(c_source), &dispose_count));
CHECK(success);
Local<Script> script = v8_compile(source);
Local<Value> value = script->Run();
@@ -630,7 +631,7 @@ TEST(MakingExternalStringConditions) {
}
-TEST(MakingExternalAsciiStringConditions) {
+TEST(MakingExternalOneByteStringConditions) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
@@ -667,7 +668,7 @@ TEST(MakingExternalAsciiStringConditions) {
}
-TEST(MakingExternalUnalignedAsciiString) {
+TEST(MakingExternalUnalignedOneByteString) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
@@ -687,12 +688,12 @@ TEST(MakingExternalUnalignedAsciiString) {
// Turn into external string with unaligned resource data.
const char* c_cons = "_abcdefghijklmnopqrstuvwxyz";
- bool success = cons->MakeExternal(
- new TestAsciiResource(i::StrDup(c_cons), NULL, 1));
+ bool success =
+ cons->MakeExternal(new TestOneByteResource(i::StrDup(c_cons), NULL, 1));
CHECK(success);
const char* c_slice = "_bcdefghijklmnopqrstuvwxyz";
- success = slice->MakeExternal(
- new TestAsciiResource(i::StrDup(c_slice), NULL, 1));
+ success =
+ slice->MakeExternal(new TestOneByteResource(i::StrDup(c_slice), NULL, 1));
CHECK(success);
// Trigger GCs and force evacuation.
@@ -721,13 +722,13 @@ THREADED_TEST(UsingExternalString) {
}
-THREADED_TEST(UsingExternalAsciiString) {
+THREADED_TEST(UsingExternalOneByteString) {
i::Factory* factory = CcTest::i_isolate()->factory();
{
v8::HandleScope scope(CcTest::isolate());
const char* one_byte_string = "test string";
Local<String> string = String::NewExternal(
- CcTest::isolate(), new TestAsciiResource(i::StrDup(one_byte_string)));
+ CcTest::isolate(), new TestOneByteResource(i::StrDup(one_byte_string)));
i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
// Trigger GCs so that the newly allocated string moves to old gen.
CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
@@ -741,6 +742,53 @@ THREADED_TEST(UsingExternalAsciiString) {
}
+class DummyResource : public v8::String::ExternalStringResource {
+ public:
+ virtual const uint16_t* data() const { return string_; }
+ virtual size_t length() const { return 1 << 30; }
+
+ private:
+ uint16_t string_[10];
+};
+
+
+class DummyOneByteResource : public v8::String::ExternalOneByteStringResource {
+ public:
+ virtual const char* data() const { return string_; }
+ virtual size_t length() const { return 1 << 30; }
+
+ private:
+ char string_[10];
+};
+
+
+THREADED_TEST(NewExternalForVeryLongString) {
+ {
+ LocalContext env;
+ v8::HandleScope scope(env->GetIsolate());
+ v8::TryCatch try_catch;
+ DummyOneByteResource r;
+ v8::Local<v8::String> str = v8::String::NewExternal(CcTest::isolate(), &r);
+ CHECK(str.IsEmpty());
+ CHECK(try_catch.HasCaught());
+ String::Utf8Value exception_value(try_catch.Exception());
+ CHECK_EQ("RangeError: Invalid string length", *exception_value);
+ }
+
+ {
+ LocalContext env;
+ v8::HandleScope scope(env->GetIsolate());
+ v8::TryCatch try_catch;
+ DummyResource r;
+ v8::Local<v8::String> str = v8::String::NewExternal(CcTest::isolate(), &r);
+ CHECK(str.IsEmpty());
+ CHECK(try_catch.HasCaught());
+ String::Utf8Value exception_value(try_catch.Exception());
+ CHECK_EQ("RangeError: Invalid string length", *exception_value);
+ }
+}
+
+
THREADED_TEST(ScavengeExternalString) {
i::FLAG_stress_compaction = false;
i::FLAG_gc_global = false;
@@ -763,7 +811,7 @@ THREADED_TEST(ScavengeExternalString) {
}
-THREADED_TEST(ScavengeExternalAsciiString) {
+THREADED_TEST(ScavengeExternalOneByteString) {
i::FLAG_stress_compaction = false;
i::FLAG_gc_global = false;
int dispose_count = 0;
@@ -773,7 +821,7 @@ THREADED_TEST(ScavengeExternalAsciiString) {
const char* one_byte_string = "test string";
Local<String> string = String::NewExternal(
CcTest::isolate(),
- new TestAsciiResource(i::StrDup(one_byte_string), &dispose_count));
+ new TestOneByteResource(i::StrDup(one_byte_string), &dispose_count));
i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
CcTest::heap()->CollectGarbage(i::NEW_SPACE);
in_new_space = CcTest::heap()->InNewSpace(*istring);
@@ -786,15 +834,14 @@ THREADED_TEST(ScavengeExternalAsciiString) {
}
-class TestAsciiResourceWithDisposeControl: public TestAsciiResource {
+class TestOneByteResourceWithDisposeControl : public TestOneByteResource {
public:
// Only used by non-threaded tests, so it can use static fields.
static int dispose_calls;
static int dispose_count;
- TestAsciiResourceWithDisposeControl(const char* data, bool dispose)
- : TestAsciiResource(data, &dispose_count),
- dispose_(dispose) { }
+ TestOneByteResourceWithDisposeControl(const char* data, bool dispose)
+ : TestOneByteResource(data, &dispose_count), dispose_(dispose) {}
void Dispose() {
++dispose_calls;
@@ -805,17 +852,17 @@ class TestAsciiResourceWithDisposeControl: public TestAsciiResource {
};
-int TestAsciiResourceWithDisposeControl::dispose_count = 0;
-int TestAsciiResourceWithDisposeControl::dispose_calls = 0;
+int TestOneByteResourceWithDisposeControl::dispose_count = 0;
+int TestOneByteResourceWithDisposeControl::dispose_calls = 0;
TEST(ExternalStringWithDisposeHandling) {
const char* c_source = "1 + 2 * 3";
// Use a stack allocated external string resource allocated object.
- TestAsciiResourceWithDisposeControl::dispose_count = 0;
- TestAsciiResourceWithDisposeControl::dispose_calls = 0;
- TestAsciiResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
+ TestOneByteResourceWithDisposeControl::dispose_count = 0;
+ TestOneByteResourceWithDisposeControl::dispose_calls = 0;
+ TestOneByteResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
{
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
@@ -825,18 +872,18 @@ TEST(ExternalStringWithDisposeHandling) {
CHECK(value->IsNumber());
CHECK_EQ(7, value->Int32Value());
CcTest::heap()->CollectAllAvailableGarbage();
- CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
+ CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
}
CcTest::i_isolate()->compilation_cache()->Clear();
CcTest::heap()->CollectAllAvailableGarbage();
- CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
- CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
+ CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
+ CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
// Use a heap allocated external string resource allocated object.
- TestAsciiResourceWithDisposeControl::dispose_count = 0;
- TestAsciiResourceWithDisposeControl::dispose_calls = 0;
- TestAsciiResource* res_heap =
- new TestAsciiResourceWithDisposeControl(i::StrDup(c_source), true);
+ TestOneByteResourceWithDisposeControl::dispose_count = 0;
+ TestOneByteResourceWithDisposeControl::dispose_calls = 0;
+ TestOneByteResource* res_heap =
+ new TestOneByteResourceWithDisposeControl(i::StrDup(c_source), true);
{
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
@@ -846,12 +893,12 @@ TEST(ExternalStringWithDisposeHandling) {
CHECK(value->IsNumber());
CHECK_EQ(7, value->Int32Value());
CcTest::heap()->CollectAllAvailableGarbage();
- CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
+ CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
}
CcTest::i_isolate()->compilation_cache()->Clear();
CcTest::heap()->CollectAllAvailableGarbage();
- CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
- CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_count);
+ CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
+ CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_count);
}
@@ -875,7 +922,8 @@ THREADED_TEST(StringConcat) {
Local<String> source = String::Concat(left, right);
right = String::NewExternal(
- env->GetIsolate(), new TestAsciiResource(i::StrDup(one_byte_extern_1)));
+ env->GetIsolate(),
+ new TestOneByteResource(i::StrDup(one_byte_extern_1)));
source = String::Concat(source, right);
right = String::NewExternal(
env->GetIsolate(),
@@ -1187,7 +1235,7 @@ THREADED_PROFILED_TEST(FastReturnValues) {
0, 234, -723,
i::Smi::kMinValue, i::Smi::kMaxValue
};
- for (size_t i = 0; i < ARRAY_SIZE(int_values); i++) {
+ for (size_t i = 0; i < arraysize(int_values); i++) {
for (int modifier = -1; modifier <= 1; modifier++) {
int int_value = int_values[i] + modifier;
// check int32_t
@@ -1219,7 +1267,7 @@ THREADED_PROFILED_TEST(FastReturnValues) {
kUndefinedReturnValue,
kEmptyStringReturnValue
};
- for (size_t i = 0; i < ARRAY_SIZE(oddballs); i++) {
+ for (size_t i = 0; i < arraysize(oddballs); i++) {
fast_return_value_void = oddballs[i];
value = TestFastReturnValues<void>();
switch (fast_return_value_void) {
@@ -1541,6 +1589,83 @@ THREADED_TEST(IsNativeError) {
}
+THREADED_TEST(IsGeneratorFunctionOrObject) {
+ LocalContext env;
+ v8::HandleScope scope(env->GetIsolate());
+
+ CompileRun("function *gen() { yield 1; }\nfunction func() {}");
+ v8::Handle<Value> gen = CompileRun("gen");
+ v8::Handle<Value> genObj = CompileRun("gen()");
+ v8::Handle<Value> object = CompileRun("{a:42}");
+ v8::Handle<Value> func = CompileRun("func");
+
+ CHECK(gen->IsGeneratorFunction());
+ CHECK(gen->IsFunction());
+ CHECK(!gen->IsGeneratorObject());
+
+ CHECK(!genObj->IsGeneratorFunction());
+ CHECK(!genObj->IsFunction());
+ CHECK(genObj->IsGeneratorObject());
+
+ CHECK(!object->IsGeneratorFunction());
+ CHECK(!object->IsFunction());
+ CHECK(!object->IsGeneratorObject());
+
+ CHECK(!func->IsGeneratorFunction());
+ CHECK(func->IsFunction());
+ CHECK(!func->IsGeneratorObject());
+}
+
+
+THREADED_TEST(ArgumentsObject) {
+ LocalContext env;
+ v8::HandleScope scope(env->GetIsolate());
+ v8::Handle<Value> arguments_object =
+ CompileRun("var out = 0; (function(){ out = arguments; })(1,2,3); out;");
+ CHECK(arguments_object->IsArgumentsObject());
+ v8::Handle<Value> array = CompileRun("[1,2,3]");
+ CHECK(!array->IsArgumentsObject());
+ v8::Handle<Value> object = CompileRun("{a:42}");
+ CHECK(!object->IsArgumentsObject());
+}
+
+
+THREADED_TEST(IsMapOrSet) {
+ LocalContext env;
+ v8::HandleScope scope(env->GetIsolate());
+ v8::Handle<Value> map = CompileRun("new Map()");
+ v8::Handle<Value> set = CompileRun("new Set()");
+ v8::Handle<Value> weak_map = CompileRun("new WeakMap()");
+ v8::Handle<Value> weak_set = CompileRun("new WeakSet()");
+ CHECK(map->IsMap());
+ CHECK(set->IsSet());
+ CHECK(weak_map->IsWeakMap());
+ CHECK(weak_set->IsWeakSet());
+
+ CHECK(!map->IsSet());
+ CHECK(!map->IsWeakMap());
+ CHECK(!map->IsWeakSet());
+
+ CHECK(!set->IsMap());
+ CHECK(!set->IsWeakMap());
+ CHECK(!set->IsWeakSet());
+
+ CHECK(!weak_map->IsMap());
+ CHECK(!weak_map->IsSet());
+ CHECK(!weak_map->IsWeakSet());
+
+ CHECK(!weak_set->IsMap());
+ CHECK(!weak_set->IsSet());
+ CHECK(!weak_set->IsWeakMap());
+
+ v8::Handle<Value> object = CompileRun("{a:42}");
+ CHECK(!object->IsMap());
+ CHECK(!object->IsSet());
+ CHECK(!object->IsWeakMap());
+ CHECK(!object->IsWeakSet());
+}
+
+
THREADED_TEST(StringObject) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
@@ -1878,6 +2003,24 @@ void SimpleAccessorSetter(Local<String> name, Local<Value> value,
self->Set(String::Concat(v8_str("accessor_"), name), value);
}
+void SymbolAccessorGetter(Local<Name> name,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ CHECK(name->IsSymbol());
+ Local<Symbol> sym = Local<Symbol>::Cast(name);
+ if (sym->Name()->IsUndefined())
+ return;
+ SimpleAccessorGetter(Local<String>::Cast(sym->Name()), info);
+}
+
+void SymbolAccessorSetter(Local<Name> name, Local<Value> value,
+ const v8::PropertyCallbackInfo<void>& info) {
+ CHECK(name->IsSymbol());
+ Local<Symbol> sym = Local<Symbol>::Cast(name);
+ if (sym->Name()->IsUndefined())
+ return;
+ SimpleAccessorSetter(Local<String>::Cast(sym->Name()), value, info);
+}
+
void EmptyInterceptorGetter(Local<String> name,
const v8::PropertyCallbackInfo<v8::Value>& info) {
}
@@ -1936,6 +2079,14 @@ void AddInterceptor(Handle<FunctionTemplate> templ,
}
+void AddAccessor(Handle<FunctionTemplate> templ,
+ Handle<Name> name,
+ v8::AccessorNameGetterCallback getter,
+ v8::AccessorNameSetterCallback setter) {
+ templ->PrototypeTemplate()->SetAccessor(name, getter, setter);
+}
+
+
THREADED_TEST(EmptyInterceptorDoesNotShadowAccessors) {
v8::HandleScope scope(CcTest::isolate());
Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
@@ -1968,10 +2119,9 @@ THREADED_TEST(ExecutableAccessorIsPreservedOnAttributeChange) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
i::LookupResult lookup(i_isolate);
i::Handle<i::String> name(v8::Utils::OpenHandle(*v8_str("length")));
- a->LookupOwnRealNamedProperty(name, &lookup);
- CHECK(lookup.IsPropertyCallbacks());
- i::Handle<i::Object> callback(lookup.GetCallbackObject(), i_isolate);
- CHECK(callback->IsExecutableAccessorInfo());
+ i::LookupIterator it(a, name, i::LookupIterator::OWN_SKIP_INTERCEPTOR);
+ CHECK_EQ(i::LookupIterator::ACCESSOR, it.state());
+ CHECK(it.GetAccessors()->IsExecutableAccessorInfo());
}
@@ -2747,6 +2897,8 @@ THREADED_TEST(SymbolProperties) {
v8::Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
v8::Local<v8::Symbol> sym2 =
v8::Symbol::New(isolate, v8_str("my-symbol"));
+ v8::Local<v8::Symbol> sym3 =
+ v8::Symbol::New(isolate, v8_str("sym3"));
CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
@@ -2802,31 +2954,62 @@ THREADED_TEST(SymbolProperties) {
CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CHECK(obj->SetAccessor(sym3, SymbolAccessorGetter, SymbolAccessorSetter));
+ CHECK(obj->Get(sym3)->IsUndefined());
+ CHECK(obj->Set(sym3, v8::Integer::New(isolate, 42)));
+ CHECK(obj->Get(sym3)->Equals(v8::Integer::New(isolate, 42)));
+ CHECK(obj->Get(v8::String::NewFromUtf8(isolate, "accessor_sym3"))->Equals(
+ v8::Integer::New(isolate, 42)));
+
// Add another property and delete it afterwards to force the object in
// slow case.
CHECK(obj->Set(sym2, v8::Integer::New(isolate, 2008)));
CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
CHECK_EQ(2008, obj->Get(sym2)->Int32Value());
CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
- CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
+ CHECK_EQ(2, obj->GetOwnPropertyNames()->Length());
CHECK(obj->Has(sym1));
CHECK(obj->Has(sym2));
+ CHECK(obj->Has(sym3));
+ CHECK(obj->Has(v8::String::NewFromUtf8(isolate, "accessor_sym3")));
CHECK(obj->Delete(sym2));
CHECK(obj->Has(sym1));
CHECK(!obj->Has(sym2));
+ CHECK(obj->Has(sym3));
+ CHECK(obj->Has(v8::String::NewFromUtf8(isolate, "accessor_sym3")));
CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
- CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
+ CHECK(obj->Get(sym3)->Equals(v8::Integer::New(isolate, 42)));
+ CHECK(obj->Get(v8::String::NewFromUtf8(isolate, "accessor_sym3"))->Equals(
+ v8::Integer::New(isolate, 42)));
+ CHECK_EQ(2, obj->GetOwnPropertyNames()->Length());
// Symbol properties are inherited.
v8::Local<v8::Object> child = v8::Object::New(isolate);
child->SetPrototype(obj);
CHECK(child->Has(sym1));
CHECK_EQ(2002, child->Get(sym1)->Int32Value());
+ CHECK(obj->Get(sym3)->Equals(v8::Integer::New(isolate, 42)));
+ CHECK(obj->Get(v8::String::NewFromUtf8(isolate, "accessor_sym3"))->Equals(
+ v8::Integer::New(isolate, 42)));
CHECK_EQ(0, child->GetOwnPropertyNames()->Length());
}
+THREADED_TEST(SymbolTemplateProperties) {
+ LocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope scope(isolate);
+ v8::Local<v8::FunctionTemplate> foo = v8::FunctionTemplate::New(isolate);
+ v8::Local<v8::Name> name = v8::Symbol::New(isolate);
+ CHECK(!name.IsEmpty());
+ foo->PrototypeTemplate()->Set(name, v8::FunctionTemplate::New(isolate));
+ v8::Local<v8::Object> new_instance = foo->InstanceTemplate()->NewInstance();
+ CHECK(!new_instance.IsEmpty());
+ CHECK(new_instance->Has(name));
+}
+
+
THREADED_TEST(PrivateProperties) {
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
@@ -2911,6 +3094,29 @@ THREADED_TEST(GlobalSymbols) {
}
+static void CheckWellKnownSymbol(v8::Local<v8::Symbol>(*getter)(v8::Isolate*),
+ const char* name) {
+ LocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope scope(isolate);
+
+ v8::Local<v8::Symbol> symbol = getter(isolate);
+ std::string script = std::string("var sym = ") + name;
+ CompileRun(script.c_str());
+ v8::Local<Value> value = env->Global()->Get(v8_str("sym"));
+
+ CHECK(!value.IsEmpty());
+ CHECK(!symbol.IsEmpty());
+ CHECK(value->SameValue(symbol));
+}
+
+
+THREADED_TEST(WellKnownSymbols) {
+ CheckWellKnownSymbol(v8::Symbol::GetIterator, "Symbol.iterator");
+ CheckWellKnownSymbol(v8::Symbol::GetUnscopables, "Symbol.unscopables");
+}
+
+
THREADED_TEST(GlobalPrivates) {
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
@@ -9412,18 +9618,14 @@ TEST(AccessControlES5) {
}
-static bool GetOwnPropertyNamesNamedBlocker(Local<v8::Object> global,
- Local<Value> name,
- v8::AccessType type,
- Local<Value> data) {
+static bool BlockEverythingNamed(Local<v8::Object> object, Local<Value> name,
+ v8::AccessType type, Local<Value> data) {
return false;
}
-static bool GetOwnPropertyNamesIndexedBlocker(Local<v8::Object> global,
- uint32_t key,
- v8::AccessType type,
- Local<Value> data) {
+static bool BlockEverythingIndexed(Local<v8::Object> object, uint32_t key,
+ v8::AccessType type, Local<Value> data) {
return false;
}
@@ -9435,8 +9637,8 @@ THREADED_TEST(AccessControlGetOwnPropertyNames) {
v8::ObjectTemplate::New(isolate);
obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
- obj_template->SetAccessCheckCallbacks(GetOwnPropertyNamesNamedBlocker,
- GetOwnPropertyNamesIndexedBlocker);
+ obj_template->SetAccessCheckCallbacks(BlockEverythingNamed,
+ BlockEverythingIndexed);
// Create an environment
v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
@@ -9471,6 +9673,50 @@ THREADED_TEST(AccessControlGetOwnPropertyNames) {
}
+TEST(SuperAccessControl) {
+ i::FLAG_harmony_classes = true;
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope handle_scope(isolate);
+ v8::Handle<v8::ObjectTemplate> obj_template =
+ v8::ObjectTemplate::New(isolate);
+ obj_template->SetAccessCheckCallbacks(BlockEverythingNamed,
+ BlockEverythingIndexed);
+ LocalContext env;
+ env->Global()->Set(v8_str("prohibited"), obj_template->NewInstance());
+
+ {
+ v8::TryCatch try_catch;
+ CompileRun(
+ "function f() { return super.hasOwnProperty; };"
+ "var m = f.toMethod(prohibited);"
+ "m();");
+ CHECK(try_catch.HasCaught());
+ }
+
+ {
+ v8::TryCatch try_catch;
+ CompileRun(
+ "function f() { super.hasOwnProperty = function () {}; };"
+ "var m = f.toMethod(prohibited);"
+ "m();");
+ CHECK(try_catch.HasCaught());
+ }
+
+ {
+ v8::TryCatch try_catch;
+ CompileRun(
+ "Object.defineProperty(Object.prototype, 'x', { set : function(){}});"
+ "function f() { "
+ " 'use strict';"
+ " super.x = function () {}; "
+ "};"
+ "var m = f.toMethod(prohibited);"
+ "m();");
+ CHECK(try_catch.HasCaught());
+ }
+}
+
+
static void IndexedPropertyEnumerator(
const v8::PropertyCallbackInfo<v8::Array>& info) {
v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 2);
@@ -14040,19 +14286,14 @@ void SetFunctionEntryHookTest::RunLoopInNewEnv(v8::Isolate* isolate) {
void SetFunctionEntryHookTest::RunTest() {
// Work in a new isolate throughout.
- v8::Isolate* isolate = v8::Isolate::New();
-
- // Test setting the entry hook on the new isolate.
- CHECK(v8::V8::SetFunctionEntryHook(isolate, EntryHook));
-
- // Replacing the hook, once set should fail.
- CHECK_EQ(false, v8::V8::SetFunctionEntryHook(isolate, EntryHook));
+ v8::Isolate::CreateParams create_params;
+ create_params.entry_hook = EntryHook;
+ create_params.code_event_handler = JitEvent;
+ v8::Isolate* isolate = v8::Isolate::New(create_params);
{
v8::Isolate::Scope scope(isolate);
- v8::V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, JitEvent);
-
RunLoopInNewEnv(isolate);
// Check the exepected invocation counts.
@@ -14080,9 +14321,6 @@ void SetFunctionEntryHookTest::RunTest() {
// We should record no invocations in this isolate.
CHECK_EQ(0, static_cast<int>(invocations_.size()));
}
- // Since the isolate has been used, we shouldn't be able to set an entry
- // hook anymore.
- CHECK_EQ(false, v8::V8::SetFunctionEntryHook(isolate, EntryHook));
isolate->Dispose();
}
@@ -14276,7 +14514,7 @@ UNINITIALIZED_TEST(SetJitCodeEventHandler) {
saw_bar = 0;
move_events = 0;
- V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
+ isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
// Generate new code objects sparsely distributed across several
// different fragmented code-space pages.
@@ -14300,7 +14538,7 @@ UNINITIALIZED_TEST(SetJitCodeEventHandler) {
// Force code movement.
heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler");
- V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
+ isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
CHECK_LE(kIterations, saw_bar);
CHECK_LT(0, move_events);
@@ -14330,8 +14568,9 @@ UNINITIALIZED_TEST(SetJitCodeEventHandler) {
i::HashMap lineinfo(MatchPointers);
jitcode_line_info = &lineinfo;
- V8::SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting, event_handler);
- V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
+ isolate->SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting,
+ event_handler);
+ isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
jitcode_line_info = NULL;
// We expect that we got some events. Note that if we could get code removal
@@ -15003,11 +15242,11 @@ TEST(ObjectClone) {
}
-class AsciiVectorResource : public v8::String::ExternalAsciiStringResource {
+class OneByteVectorResource : public v8::String::ExternalOneByteStringResource {
public:
- explicit AsciiVectorResource(i::Vector<const char> vector)
+ explicit OneByteVectorResource(i::Vector<const char> vector)
: data_(vector) {}
- virtual ~AsciiVectorResource() {}
+ virtual ~OneByteVectorResource() {}
virtual size_t length() const { return data_.length(); }
virtual const char* data() const { return data_.start(); }
private:
@@ -15028,12 +15267,12 @@ class UC16VectorResource : public v8::String::ExternalStringResource {
static void MorphAString(i::String* string,
- AsciiVectorResource* ascii_resource,
+ OneByteVectorResource* one_byte_resource,
UC16VectorResource* uc16_resource) {
CHECK(i::StringShape(string).IsExternal());
if (string->IsOneByteRepresentation()) {
// Check old map is not internalized or long.
- CHECK(string->map() == CcTest::heap()->external_ascii_string_map());
+ CHECK(string->map() == CcTest::heap()->external_one_byte_string_map());
// Morph external string to be TwoByte string.
string->set_map(CcTest::heap()->external_string_map());
i::ExternalTwoByteString* morphed =
@@ -15042,11 +15281,10 @@ static void MorphAString(i::String* string,
} else {
// Check old map is not internalized or long.
CHECK(string->map() == CcTest::heap()->external_string_map());
- // Morph external string to be ASCII string.
- string->set_map(CcTest::heap()->external_ascii_string_map());
- i::ExternalAsciiString* morphed =
- i::ExternalAsciiString::cast(string);
- morphed->set_resource(ascii_resource);
+ // Morph external string to be one-byte string.
+ string->set_map(CcTest::heap()->external_one_byte_string_map());
+ i::ExternalOneByteString* morphed = i::ExternalOneByteString::cast(string);
+ morphed->set_resource(one_byte_resource);
}
}
@@ -15062,18 +15300,18 @@ THREADED_TEST(MorphCompositeStringTest) {
LocalContext env;
i::Factory* factory = CcTest::i_isolate()->factory();
v8::HandleScope scope(env->GetIsolate());
- AsciiVectorResource ascii_resource(
+ OneByteVectorResource one_byte_resource(
i::Vector<const char>(c_string, i::StrLength(c_string)));
UC16VectorResource uc16_resource(
i::Vector<const uint16_t>(two_byte_string,
i::StrLength(c_string)));
- Local<String> lhs(v8::Utils::ToLocal(
- factory->NewExternalStringFromAscii(&ascii_resource)
- .ToHandleChecked()));
- Local<String> rhs(v8::Utils::ToLocal(
- factory->NewExternalStringFromAscii(&ascii_resource)
- .ToHandleChecked()));
+ Local<String> lhs(
+ v8::Utils::ToLocal(factory->NewExternalStringFromOneByte(
+ &one_byte_resource).ToHandleChecked()));
+ Local<String> rhs(
+ v8::Utils::ToLocal(factory->NewExternalStringFromOneByte(
+ &one_byte_resource).ToHandleChecked()));
env->Global()->Set(v8_str("lhs"), lhs);
env->Global()->Set(v8_str("rhs"), rhs);
@@ -15086,8 +15324,10 @@ THREADED_TEST(MorphCompositeStringTest) {
CHECK(lhs->IsOneByte());
CHECK(rhs->IsOneByte());
- MorphAString(*v8::Utils::OpenHandle(*lhs), &ascii_resource, &uc16_resource);
- MorphAString(*v8::Utils::OpenHandle(*rhs), &ascii_resource, &uc16_resource);
+ MorphAString(*v8::Utils::OpenHandle(*lhs), &one_byte_resource,
+ &uc16_resource);
+ MorphAString(*v8::Utils::OpenHandle(*rhs), &one_byte_resource,
+ &uc16_resource);
// This should UTF-8 without flattening, since everything is ASCII.
Handle<String> cons = v8_compile("cons")->Run().As<String>();
@@ -15130,16 +15370,15 @@ TEST(CompileExternalTwoByteSource) {
// This is a very short list of sources, which currently is to check for a
// regression caused by r2703.
- const char* ascii_sources[] = {
- "0.5",
- "-0.5", // This mainly testes PushBack in the Scanner.
- "--0.5", // This mainly testes PushBack in the Scanner.
- NULL
- };
+ const char* one_byte_sources[] = {
+ "0.5",
+ "-0.5", // This mainly testes PushBack in the Scanner.
+ "--0.5", // This mainly testes PushBack in the Scanner.
+ NULL};
// Compile the sources as external two byte strings.
- for (int i = 0; ascii_sources[i] != NULL; i++) {
- uint16_t* two_byte_string = AsciiToTwoByteString(ascii_sources[i]);
+ for (int i = 0; one_byte_sources[i] != NULL; i++) {
+ uint16_t* two_byte_string = AsciiToTwoByteString(one_byte_sources[i]);
TestResource* uc16_resource = new TestResource(two_byte_string);
v8::Local<v8::String> source =
v8::String::NewExternal(context->GetIsolate(), uc16_resource);
@@ -15198,14 +15437,14 @@ TEST(RegExpInterruption) {
RegExpInterruptionThread timeout_thread(CcTest::isolate());
v8::V8::AddGCPrologueCallback(RunBeforeGC);
- static const char* ascii_content = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
- i::uc16* uc16_content = AsciiToTwoByteString(ascii_content);
- v8::Local<v8::String> string = v8_str(ascii_content);
+ static const char* one_byte_content = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+ i::uc16* uc16_content = AsciiToTwoByteString(one_byte_content);
+ v8::Local<v8::String> string = v8_str(one_byte_content);
CcTest::global()->Set(v8_str("a"), string);
regexp_interruption_data.string.Reset(CcTest::isolate(), string);
regexp_interruption_data.string_resource = new UC16VectorResource(
- i::Vector<const i::uc16>(uc16_content, i::StrLength(ascii_content)));
+ i::Vector<const i::uc16>(uc16_content, i::StrLength(one_byte_content)));
v8::TryCatch try_catch;
timeout_thread.Start();
@@ -17697,14 +17936,13 @@ TEST(IdleNotificationWithLargeHint) {
TEST(Regress2107) {
const intptr_t MB = 1024 * 1024;
- const int kShortIdlePauseInMs = 100;
- const int kLongIdlePauseInMs = 1000;
+ const int kIdlePauseInMs = 1000;
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
v8::HandleScope scope(env->GetIsolate());
intptr_t initial_size = CcTest::heap()->SizeOfObjects();
// Send idle notification to start a round of incremental GCs.
- env->GetIsolate()->IdleNotification(kShortIdlePauseInMs);
+ env->GetIsolate()->IdleNotification(kIdlePauseInMs);
// Emulate 7 page reloads.
for (int i = 0; i < 7; i++) {
{
@@ -17715,7 +17953,7 @@ TEST(Regress2107) {
ctx->Exit();
}
env->GetIsolate()->ContextDisposedNotification();
- env->GetIsolate()->IdleNotification(kLongIdlePauseInMs);
+ env->GetIsolate()->IdleNotification(kIdlePauseInMs);
}
// Create garbage and check that idle notification still collects it.
CreateGarbageInOldSpace();
@@ -17723,7 +17961,7 @@ TEST(Regress2107) {
CHECK_GT(size_with_garbage, initial_size + MB);
bool finished = false;
for (int i = 0; i < 200 && !finished; i++) {
- finished = env->GetIsolate()->IdleNotification(kShortIdlePauseInMs);
+ finished = env->GetIsolate()->IdleNotification(kIdlePauseInMs);
}
intptr_t final_size = CcTest::heap()->SizeOfObjects();
CHECK_LT(final_size, initial_size + 1);
@@ -17764,13 +18002,11 @@ static uint32_t* ComputeStackLimit(uint32_t size) {
static const int stack_breathing_room = 256 * i::KB;
-TEST(SetResourceConstraints) {
+TEST(SetStackLimit) {
uint32_t* set_limit = ComputeStackLimit(stack_breathing_room);
// Set stack limit.
- v8::ResourceConstraints constraints;
- constraints.set_stack_limit(set_limit);
- CHECK(v8::SetResourceConstraints(CcTest::isolate(), &constraints));
+ CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
// Execute a script.
LocalContext env;
@@ -17785,16 +18021,14 @@ TEST(SetResourceConstraints) {
}
-TEST(SetResourceConstraintsInThread) {
+TEST(SetStackLimitInThread) {
uint32_t* set_limit;
{
v8::Locker locker(CcTest::isolate());
set_limit = ComputeStackLimit(stack_breathing_room);
// Set stack limit.
- v8::ResourceConstraints constraints;
- constraints.set_stack_limit(set_limit);
- CHECK(v8::SetResourceConstraints(CcTest::isolate(), &constraints));
+ CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
// Execute a script.
v8::HandleScope scope(CcTest::isolate());
@@ -17837,7 +18071,7 @@ class VisitorImpl : public v8::ExternalResourceVisitor {
virtual ~VisitorImpl() {}
virtual void VisitExternalString(v8::Handle<v8::String> string) {
if (!string->IsExternal()) {
- CHECK(string->IsExternalAscii());
+ CHECK(string->IsExternalOneByte());
return;
}
v8::String::ExternalStringResource* resource =
@@ -17894,12 +18128,12 @@ TEST(ExternalizeOldSpaceOneByteCons) {
CHECK(CcTest::heap()->old_pointer_space()->Contains(
*v8::Utils::OpenHandle(*cons)));
- TestAsciiResource* resource =
- new TestAsciiResource(i::StrDup("Romeo Montague Juliet Capulet"));
+ TestOneByteResource* resource =
+ new TestOneByteResource(i::StrDup("Romeo Montague Juliet Capulet"));
cons->MakeExternal(resource);
- CHECK(cons->IsExternalAscii());
- CHECK_EQ(resource, cons->GetExternalAsciiStringResource());
+ CHECK(cons->IsExternalOneByte());
+ CHECK_EQ(resource, cons->GetExternalOneByteStringResource());
String::Encoding encoding;
CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
@@ -17954,8 +18188,8 @@ TEST(ExternalStringCollectedAtTearDown) {
{ v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope handle_scope(isolate);
const char* s = "One string to test them all, one string to find them.";
- TestAsciiResource* inscription =
- new TestAsciiResource(i::StrDup(s), &destroyed);
+ TestOneByteResource* inscription =
+ new TestOneByteResource(i::StrDup(s), &destroyed);
v8::Local<v8::String> ring = v8::String::NewExternal(isolate, inscription);
// Ring is still alive. Orcs are roaming freely across our lands.
CHECK_EQ(0, destroyed);
@@ -17976,8 +18210,8 @@ TEST(ExternalInternalizedStringCollectedAtTearDown) {
v8::HandleScope handle_scope(isolate);
CompileRun("var ring = 'One string to test them all';");
const char* s = "One string to test them all";
- TestAsciiResource* inscription =
- new TestAsciiResource(i::StrDup(s), &destroyed);
+ TestOneByteResource* inscription =
+ new TestOneByteResource(i::StrDup(s), &destroyed);
v8::Local<v8::String> ring = CompileRun("ring")->ToString();
CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
ring->MakeExternal(inscription);
@@ -17998,8 +18232,8 @@ TEST(ExternalInternalizedStringCollectedAtGC) {
v8::HandleScope handle_scope(env->GetIsolate());
CompileRun("var ring = 'One string to test them all';");
const char* s = "One string to test them all";
- TestAsciiResource* inscription =
- new TestAsciiResource(i::StrDup(s), &destroyed);
+ TestOneByteResource* inscription =
+ new TestOneByteResource(i::StrDup(s), &destroyed);
v8::Local<v8::String> ring = CompileRun("ring")->ToString();
CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
ring->MakeExternal(inscription);
@@ -18942,7 +19176,7 @@ THREADED_TEST(TestEviction) {
}
-THREADED_TEST(TwoByteStringInAsciiCons) {
+THREADED_TEST(TwoByteStringInOneByteCons) {
// See Chromium issue 47824.
LocalContext context;
v8::HandleScope scope(context->GetIsolate());
@@ -18980,10 +19214,10 @@ THREADED_TEST(TwoByteStringInAsciiCons) {
// If the cons string has been short-circuited, skip the following checks.
if (!string.is_identical_to(flat_string)) {
- // At this point, we should have a Cons string which is flat and ASCII,
+ // At this point, we should have a Cons string which is flat and one-byte,
// with a first half that is a two-byte string (although it only contains
- // ASCII characters). This is a valid sequence of steps, and it can happen
- // in real pages.
+ // one-byte characters). This is a valid sequence of steps, and it can
+ // happen in real pages.
CHECK(string->IsOneByteRepresentation());
i::ConsString* cons = i::ConsString::cast(*string);
CHECK_EQ(0, cons->second()->length());
@@ -19071,7 +19305,7 @@ TEST(ContainsOnlyOneByte) {
String::NewExternal(isolate,
new TestResource(string_contents, NULL, false));
USE(two_byte); USE(cons_strings);
- for (size_t i = 0; i < ARRAY_SIZE(cons_strings); i++) {
+ for (size_t i = 0; i < arraysize(cons_strings); i++) {
// Base assumptions.
string = cons_strings[i];
CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
@@ -19367,31 +19601,26 @@ static int CalcFibonacci(v8::Isolate* isolate, int limit) {
class IsolateThread : public v8::base::Thread {
public:
- IsolateThread(v8::Isolate* isolate, int fib_limit)
- : Thread(Options("IsolateThread")),
- isolate_(isolate),
- fib_limit_(fib_limit),
- result_(0) {}
+ explicit IsolateThread(int fib_limit)
+ : Thread(Options("IsolateThread")), fib_limit_(fib_limit), result_(0) {}
void Run() {
- result_ = CalcFibonacci(isolate_, fib_limit_);
+ v8::Isolate* isolate = v8::Isolate::New();
+ result_ = CalcFibonacci(isolate, fib_limit_);
+ isolate->Dispose();
}
int result() { return result_; }
private:
- v8::Isolate* isolate_;
int fib_limit_;
int result_;
};
TEST(MultipleIsolatesOnIndividualThreads) {
- v8::Isolate* isolate1 = v8::Isolate::New();
- v8::Isolate* isolate2 = v8::Isolate::New();
-
- IsolateThread thread1(isolate1, 21);
- IsolateThread thread2(isolate2, 12);
+ IsolateThread thread1(21);
+ IsolateThread thread2(12);
// Compute some fibonacci numbers on 3 threads in 3 isolates.
thread1.Start();
@@ -19409,9 +19638,6 @@ TEST(MultipleIsolatesOnIndividualThreads) {
CHECK_EQ(result2, 144);
CHECK_EQ(result1, thread1.result());
CHECK_EQ(result2, thread2.result());
-
- isolate1->Dispose();
- isolate2->Dispose();
}
@@ -19455,16 +19681,22 @@ class InitDefaultIsolateThread : public v8::base::Thread {
result_(false) {}
void Run() {
- v8::Isolate* isolate = v8::Isolate::New();
- isolate->Enter();
+ v8::Isolate::CreateParams create_params;
switch (testCase_) {
case SetResourceConstraints: {
- v8::ResourceConstraints constraints;
- constraints.set_max_semi_space_size(1);
- constraints.set_max_old_space_size(4);
- v8::SetResourceConstraints(CcTest::isolate(), &constraints);
+ create_params.constraints.set_max_semi_space_size(1);
+ create_params.constraints.set_max_old_space_size(4);
break;
}
+ default:
+ break;
+ }
+ v8::Isolate* isolate = v8::Isolate::New(create_params);
+ isolate->Enter();
+ switch (testCase_) {
+ case SetResourceConstraints:
+ // Already handled in pre-Isolate-creation block.
+ break;
case SetFatalHandler:
v8::V8::SetFatalErrorHandler(NULL);
@@ -21490,7 +21722,7 @@ THREADED_TEST(JSONParseNumber) {
}
-#if V8_OS_POSIX
+#if V8_OS_POSIX && !V8_OS_NACL
class ThreadInterruptTest {
public:
ThreadInterruptTest() : sem_(0), sem_value_(0) { }
@@ -21689,7 +21921,6 @@ TEST(AccessCheckThrows) {
// Create a context and set an x property on it's global object.
LocalContext context0(NULL, global_template);
- context0->Global()->Set(v8_str("x"), v8_num(42));
v8::Handle<v8::Object> global0 = context0->Global();
// Create a context with a different security token so that the
@@ -22287,12 +22518,12 @@ class ApiCallOptimizationChecker {
void RunAll() {
SignatureType signature_types[] =
{kNoSignature, kSignatureOnReceiver, kSignatureOnPrototype};
- for (unsigned i = 0; i < ARRAY_SIZE(signature_types); i++) {
+ for (unsigned i = 0; i < arraysize(signature_types); i++) {
SignatureType signature_type = signature_types[i];
for (int j = 0; j < 2; j++) {
bool global = j == 0;
int key = signature_type +
- ARRAY_SIZE(signature_types) * (global ? 1 : 0);
+ arraysize(signature_types) * (global ? 1 : 0);
Run(signature_type, global, key);
}
}
@@ -22736,32 +22967,6 @@ TEST(ScriptNameAndLineNumber) {
}
-Local<v8::Context> call_eval_context;
-Local<v8::Function> call_eval_bound_function;
-static void CallEval(const v8::FunctionCallbackInfo<v8::Value>& args) {
- v8::Context::Scope scope(call_eval_context);
- args.GetReturnValue().Set(
- call_eval_bound_function->Call(call_eval_context->Global(), 0, NULL));
-}
-
-
-TEST(CrossActivationEval) {
- LocalContext env;
- v8::Isolate* isolate = env->GetIsolate();
- v8::HandleScope scope(isolate);
- {
- call_eval_context = v8::Context::New(isolate);
- v8::Context::Scope scope(call_eval_context);
- call_eval_bound_function =
- Local<Function>::Cast(CompileRun("eval.bind(this, '1')"));
- }
- env->Global()->Set(v8_str("CallEval"),
- v8::FunctionTemplate::New(isolate, CallEval)->GetFunction());
- Local<Value> result = CompileRun("CallEval();");
- CHECK_EQ(result, v8::Integer::New(isolate, 1));
-}
-
-
void SourceURLHelper(const char* source, const char* expected_source_url,
const char* expected_source_mapping_url) {
Local<Script> script = v8_compile(source);
@@ -22870,3 +23075,381 @@ TEST(GetOwnPropertyDescriptor) {
set->Call(x, 1, args);
CHECK_EQ(v8_num(14), get->Call(x, 0, NULL));
}
+
+
+TEST(Regress411877) {
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope handle_scope(isolate);
+ v8::Handle<v8::ObjectTemplate> object_template =
+ v8::ObjectTemplate::New(isolate);
+ object_template->SetAccessCheckCallbacks(NamedAccessCounter,
+ IndexedAccessCounter);
+
+ v8::Handle<Context> context = Context::New(isolate);
+ v8::Context::Scope context_scope(context);
+
+ context->Global()->Set(v8_str("o"), object_template->NewInstance());
+ CompileRun("Object.getOwnPropertyNames(o)");
+}
+
+
+TEST(GetHiddenPropertyTableAfterAccessCheck) {
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope handle_scope(isolate);
+ v8::Handle<v8::ObjectTemplate> object_template =
+ v8::ObjectTemplate::New(isolate);
+ object_template->SetAccessCheckCallbacks(NamedAccessCounter,
+ IndexedAccessCounter);
+
+ v8::Handle<Context> context = Context::New(isolate);
+ v8::Context::Scope context_scope(context);
+
+ v8::Handle<v8::Object> obj = object_template->NewInstance();
+ obj->Set(v8_str("key"), v8_str("value"));
+ obj->Delete(v8_str("key"));
+
+ obj->SetHiddenValue(v8_str("hidden key 2"), v8_str("hidden value 2"));
+}
+
+
+TEST(Regress411793) {
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope handle_scope(isolate);
+ v8::Handle<v8::ObjectTemplate> object_template =
+ v8::ObjectTemplate::New(isolate);
+ object_template->SetAccessCheckCallbacks(NamedAccessCounter,
+ IndexedAccessCounter);
+
+ v8::Handle<Context> context = Context::New(isolate);
+ v8::Context::Scope context_scope(context);
+
+ context->Global()->Set(v8_str("o"), object_template->NewInstance());
+ CompileRun(
+ "Object.defineProperty(o, 'key', "
+ " { get: function() {}, set: function() {} });");
+}
+
+class TestSourceStream : public v8::ScriptCompiler::ExternalSourceStream {
+ public:
+ explicit TestSourceStream(const char** chunks) : chunks_(chunks), index_(0) {}
+
+ virtual size_t GetMoreData(const uint8_t** src) {
+ // Unlike in real use cases, this function will never block.
+ if (chunks_[index_] == NULL) {
+ return 0;
+ }
+ // Copy the data, since the caller takes ownership of it.
+ size_t len = strlen(chunks_[index_]);
+ // We don't need to zero-terminate since we return the length.
+ uint8_t* copy = new uint8_t[len];
+ memcpy(copy, chunks_[index_], len);
+ *src = copy;
+ ++index_;
+ return len;
+ }
+
+ // Helper for constructing a string from chunks (the compilation needs it
+ // too).
+ static char* FullSourceString(const char** chunks) {
+ size_t total_len = 0;
+ for (size_t i = 0; chunks[i] != NULL; ++i) {
+ total_len += strlen(chunks[i]);
+ }
+ char* full_string = new char[total_len + 1];
+ size_t offset = 0;
+ for (size_t i = 0; chunks[i] != NULL; ++i) {
+ size_t len = strlen(chunks[i]);
+ memcpy(full_string + offset, chunks[i], len);
+ offset += len;
+ }
+ full_string[total_len] = 0;
+ return full_string;
+ }
+
+ private:
+ const char** chunks_;
+ unsigned index_;
+};
+
+
+// Helper function for running streaming tests.
+void RunStreamingTest(const char** chunks,
+ v8::ScriptCompiler::StreamedSource::Encoding encoding =
+ v8::ScriptCompiler::StreamedSource::ONE_BYTE,
+ bool expected_success = true) {
+ LocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope scope(isolate);
+ v8::TryCatch try_catch;
+
+ v8::ScriptCompiler::StreamedSource source(new TestSourceStream(chunks),
+ encoding);
+ v8::ScriptCompiler::ScriptStreamingTask* task =
+ v8::ScriptCompiler::StartStreamingScript(isolate, &source);
+
+ // TestSourceStream::GetMoreData won't block, so it's OK to just run the
+ // task here in the main thread.
+ task->Run();
+ delete task;
+
+ v8::ScriptOrigin origin(v8_str("http://foo.com"));
+ char* full_source = TestSourceStream::FullSourceString(chunks);
+
+ // The possible errors are only produced while compiling.
+ CHECK_EQ(false, try_catch.HasCaught());
+
+ v8::Handle<Script> script = v8::ScriptCompiler::Compile(
+ isolate, &source, v8_str(full_source), origin);
+ if (expected_success) {
+ CHECK(!script.IsEmpty());
+ v8::Handle<Value> result(script->Run());
+ // All scripts are supposed to return the fixed value 13 when ran.
+ CHECK_EQ(13, result->Int32Value());
+ } else {
+ CHECK(script.IsEmpty());
+ CHECK(try_catch.HasCaught());
+ }
+ delete[] full_source;
+}
+
+
+TEST(StreamingSimpleScript) {
+ // This script is unrealistically small, since no one chunk is enough to fill
+ // the backing buffer of Scanner, let alone overflow it.
+ const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
+ NULL};
+ RunStreamingTest(chunks);
+}
+
+
+TEST(StreamingBiggerScript) {
+ const char* chunk1 =
+ "function foo() {\n"
+ " // Make this chunk sufficiently long so that it will overflow the\n"
+ " // backing buffer of the Scanner.\n"
+ " var i = 0;\n"
+ " var result = 0;\n"
+ " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
+ " result = 0;\n"
+ " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
+ " result = 0;\n"
+ " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
+ " result = 0;\n"
+ " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
+ " return result;\n"
+ "}\n";
+ const char* chunks[] = {chunk1, "foo(); ", NULL};
+ RunStreamingTest(chunks);
+}
+
+
+TEST(StreamingScriptWithParseError) {
+ // Test that parse errors from streamed scripts are propagated correctly.
+ {
+ char chunk1[] =
+ " // This will result in a parse error.\n"
+ " var if else then foo";
+ char chunk2[] = " 13\n";
+ const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
+
+ RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::ONE_BYTE,
+ false);
+ }
+ // Test that the next script succeeds normally.
+ {
+ char chunk1[] =
+ " // This will be parsed successfully.\n"
+ " function foo() { return ";
+ char chunk2[] = " 13; }\n";
+ const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
+
+ RunStreamingTest(chunks);
+ }
+}
+
+
+TEST(StreamingUtf8Script) {
+ // We'd want to write \uc481 instead of \xeb\x91\x80, but Windows compilers
+ // don't like it.
+ const char* chunk1 =
+ "function foo() {\n"
+ " // This function will contain an UTF-8 character which is not in\n"
+ " // ASCII.\n"
+ " var foob\xeb\x91\x80r = 13;\n"
+ " return foob\xeb\x91\x80r;\n"
+ "}\n";
+ const char* chunks[] = {chunk1, "foo(); ", NULL};
+ RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
+}
+
+
+TEST(StreamingUtf8ScriptWithSplitCharactersSanityCheck) {
+ // A sanity check to prove that the approach of splitting UTF-8
+ // characters is correct. Here is an UTF-8 character which will take three
+ // bytes.
+ const char* reference = "\xeb\x91\x80";
+ CHECK(3u == strlen(reference)); // NOLINT - no CHECK_EQ for unsigned.
+
+ char chunk1[] =
+ "function foo() {\n"
+ " // This function will contain an UTF-8 character which is not in\n"
+ " // ASCII.\n"
+ " var foob";
+ char chunk2[] =
+ "XXXr = 13;\n"
+ " return foob\xeb\x91\x80r;\n"
+ "}\n";
+ for (int i = 0; i < 3; ++i) {
+ chunk2[i] = reference[i];
+ }
+ const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
+ RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
+}
+
+
+TEST(StreamingUtf8ScriptWithSplitCharacters) {
+ // Stream data where a multi-byte UTF-8 character is split between two data
+ // chunks.
+ const char* reference = "\xeb\x91\x80";
+ char chunk1[] =
+ "function foo() {\n"
+ " // This function will contain an UTF-8 character which is not in\n"
+ " // ASCII.\n"
+ " var foobX";
+ char chunk2[] =
+ "XXr = 13;\n"
+ " return foob\xeb\x91\x80r;\n"
+ "}\n";
+ chunk1[strlen(chunk1) - 1] = reference[0];
+ chunk2[0] = reference[1];
+ chunk2[1] = reference[2];
+ const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
+ RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
+}
+
+
+TEST(StreamingUtf8ScriptWithSplitCharactersValidEdgeCases) {
+ // Tests edge cases which should still be decoded correctly.
+
+ // Case 1: a chunk contains only bytes for a split character (and no other
+ // data). This kind of a chunk would be exceptionally small, but we should
+ // still decode it correctly.
+ const char* reference = "\xeb\x91\x80";
+ // The small chunk is at the beginning of the split character
+ {
+ char chunk1[] =
+ "function foo() {\n"
+ " // This function will contain an UTF-8 character which is not in\n"
+ " // ASCII.\n"
+ " var foob";
+ char chunk2[] = "XX";
+ char chunk3[] =
+ "Xr = 13;\n"
+ " return foob\xeb\x91\x80r;\n"
+ "}\n";
+ chunk2[0] = reference[0];
+ chunk2[1] = reference[1];
+ chunk3[0] = reference[2];
+ const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
+ RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
+ }
+ // The small chunk is at the end of a character
+ {
+ char chunk1[] =
+ "function foo() {\n"
+ " // This function will contain an UTF-8 character which is not in\n"
+ " // ASCII.\n"
+ " var foobX";
+ char chunk2[] = "XX";
+ char chunk3[] =
+ "r = 13;\n"
+ " return foob\xeb\x91\x80r;\n"
+ "}\n";
+ chunk1[strlen(chunk1) - 1] = reference[0];
+ chunk2[0] = reference[1];
+ chunk2[1] = reference[2];
+ const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
+ RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
+ }
+ // Case 2: the script ends with a multi-byte character. Make sure that it's
+ // decoded correctly and not just ignored.
+ {
+ char chunk1[] =
+ "var foob\xeb\x91\x80 = 13;\n"
+ "foob\xeb\x91\x80";
+ const char* chunks[] = {chunk1, NULL};
+ RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
+ }
+}
+
+
+TEST(StreamingUtf8ScriptWithSplitCharactersInvalidEdgeCases) {
+ // Test cases where a UTF-8 character is split over several chunks. Those
+ // cases are not supported (the embedder should give the data in big enough
+ // chunks), but we shouldn't crash, just produce a parse error.
+ const char* reference = "\xeb\x91\x80";
+ char chunk1[] =
+ "function foo() {\n"
+ " // This function will contain an UTF-8 character which is not in\n"
+ " // ASCII.\n"
+ " var foobX";
+ char chunk2[] = "X";
+ char chunk3[] =
+ "Xr = 13;\n"
+ " return foob\xeb\x91\x80r;\n"
+ "}\n";
+ chunk1[strlen(chunk1) - 1] = reference[0];
+ chunk2[0] = reference[1];
+ chunk3[0] = reference[2];
+ const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
+
+ RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
+}
+
+
+TEST(StreamingProducesParserCache) {
+ i::FLAG_min_preparse_length = 0;
+ const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
+ NULL};
+
+ LocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope scope(isolate);
+
+ v8::ScriptCompiler::StreamedSource source(
+ new TestSourceStream(chunks),
+ v8::ScriptCompiler::StreamedSource::ONE_BYTE);
+ v8::ScriptCompiler::ScriptStreamingTask* task =
+ v8::ScriptCompiler::StartStreamingScript(
+ isolate, &source, v8::ScriptCompiler::kProduceParserCache);
+
+ // TestSourceStream::GetMoreData won't block, so it's OK to just run the
+ // task here in the main thread.
+ task->Run();
+ delete task;
+
+ const v8::ScriptCompiler::CachedData* cached_data = source.GetCachedData();
+ CHECK(cached_data != NULL);
+ CHECK(cached_data->data != NULL);
+ CHECK_GT(cached_data->length, 0);
+}
+
+
+TEST(StreamingScriptWithInvalidUtf8) {
+ // Regression test for a crash: test that invalid UTF-8 bytes in the end of a
+ // chunk don't produce a crash.
+ const char* reference = "\xeb\x91\x80\x80\x80";
+ char chunk1[] =
+ "function foo() {\n"
+ " // This function will contain an UTF-8 character which is not in\n"
+ " // ASCII.\n"
+ " var foobXXXXX"; // Too many bytes which look like incomplete chars!
+ char chunk2[] =
+ "r = 13;\n"
+ " return foob\xeb\x91\x80\x80\x80r;\n"
+ "}\n";
+ for (int i = 0; i < 5; ++i) chunk1[strlen(chunk1) - 5 + i] = reference[i];
+
+ const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
+ RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
+}