#include "src/arguments.h"
#include "src/base/platform/platform.h"
#include "src/compilation-cache.h"
+#include "src/debug.h"
#include "src/execution.h"
#include "src/objects.h"
#include "src/parser.h"
signature_callback_count = 0;
signature_expected_receiver = receiver;
bool expected_to_throw = receiver.IsEmpty();
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
CompileRun(source.start());
CHECK_EQ(expected_to_throw, try_catch.HasCaught());
if (!expected_to_throw) {
CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
source->GetExternalStringResourceBase(&encoding));
CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
CHECK_EQ(0, dispose_count);
}
CcTest::i_isolate()->compilation_cache()->Clear();
Local<Value> value = script->Run();
CHECK(value->IsNumber());
CHECK_EQ(7, value->Int32Value());
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
CHECK_EQ(0, dispose_count);
}
CcTest::i_isolate()->compilation_cache()->Clear();
Local<Value> value = script->Run();
CHECK(value->IsNumber());
CHECK_EQ(7, value->Int32Value());
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
CHECK_EQ(0, dispose_count);
}
CcTest::i_isolate()->compilation_cache()->Clear();
- CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+ CcTest::heap()->CollectAllGarbage();
CHECK_EQ(1, dispose_count);
}
Local<Value> value = script->Run();
CHECK(value->IsNumber());
CHECK_EQ(7, value->Int32Value());
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
CHECK_EQ(0, dispose_count);
}
CcTest::i_isolate()->compilation_cache()->Clear();
- CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+ CcTest::heap()->CollectAllGarbage();
CHECK_EQ(1, dispose_count);
}
"slice('abcdefghijklmnopqrstuvwxyz');"));
// Trigger GCs so that the newly allocated string moves to old gen.
- SimulateFullSpace(CcTest::heap()->old_pointer_space());
+ SimulateFullSpace(CcTest::heap()->old_space());
CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
CHECK(success);
// Trigger GCs and force evacuation.
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
CcTest::heap()->CollectAllGarbage(i::Heap::kReduceMemoryFootprintMask);
}
factory->InternalizeString(istring);
CHECK(isymbol->IsInternalizedString());
}
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
+ CcTest::heap()->CollectAllGarbage();
}
factory->InternalizeString(istring);
CHECK(isymbol->IsInternalizedString());
}
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
+ CcTest::heap()->CollectAllGarbage();
}
auto isolate = CcTest::isolate();
{
v8::HandleScope scope(isolate);
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
RandomLengthOneByteResource r(1 << 30);
v8::Local<v8::String> str = v8::String::NewExternal(isolate, &r);
CHECK(str.IsEmpty());
{
v8::HandleScope scope(isolate);
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
RandomLengthResource r(1 << 30);
v8::Local<v8::String> str = v8::String::NewExternal(isolate, &r);
CHECK(str.IsEmpty());
i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
CcTest::heap()->CollectGarbage(i::NEW_SPACE);
in_new_space = CcTest::heap()->InNewSpace(*istring);
- CHECK(in_new_space || CcTest::heap()->old_data_space()->Contains(*istring));
+ CHECK(in_new_space || CcTest::heap()->old_space()->Contains(*istring));
CHECK_EQ(0, dispose_count);
}
- CcTest::heap()->CollectGarbage(in_new_space ? i::NEW_SPACE
- : i::OLD_DATA_SPACE);
+ CcTest::heap()->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_SPACE);
CHECK_EQ(1, dispose_count);
}
i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
CcTest::heap()->CollectGarbage(i::NEW_SPACE);
in_new_space = CcTest::heap()->InNewSpace(*istring);
- CHECK(in_new_space || CcTest::heap()->old_data_space()->Contains(*istring));
+ CHECK(in_new_space || CcTest::heap()->old_space()->Contains(*istring));
CHECK_EQ(0, dispose_count);
}
- CcTest::heap()->CollectGarbage(in_new_space ? i::NEW_SPACE
- : i::OLD_DATA_SPACE);
+ CcTest::heap()->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_SPACE);
CHECK_EQ(1, dispose_count);
}
CHECK_EQ(68, value->Int32Value());
}
CcTest::i_isolate()->compilation_cache()->Clear();
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
+ CcTest::heap()->CollectAllGarbage();
}
}
+TEST(StringObjectDelete) {
+ LocalContext context;
+ v8::HandleScope scope(context->GetIsolate());
+ v8::Handle<Value> boxed_string = CompileRun("new String(\"test\")");
+ CHECK(boxed_string->IsStringObject());
+ v8::Handle<v8::Object> str_obj = boxed_string.As<v8::Object>();
+ CHECK(!str_obj->Delete(2));
+ CHECK(!str_obj->Delete(v8_num(2)));
+}
+
+
THREADED_TEST(NumberObject) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
THREADED_TEST(ObjectTemplate) {
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope scope(isolate);
- Local<ObjectTemplate> templ1 = ObjectTemplate::New(isolate);
+ Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
+ v8::Local<v8::String> class_name =
+ v8::String::NewFromUtf8(isolate, "the_class_name");
+ fun->SetClassName(class_name);
+ Local<ObjectTemplate> templ1 = ObjectTemplate::New(isolate, fun);
templ1->Set(isolate, "x", v8_num(10));
templ1->Set(isolate, "y", v8_num(13));
LocalContext env;
Local<v8::Object> instance1 = templ1->NewInstance();
+ CHECK(class_name->StrictEquals(instance1->GetConstructorName()));
env->Global()->Set(v8_str("p"), instance1);
CHECK(v8_compile("(p.x == 10)")->Run()->BooleanValue());
CHECK(v8_compile("(p.y == 13)")->Run()->BooleanValue());
- Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
- fun->PrototypeTemplate()->Set(isolate, "nirk", v8_num(123));
- Local<ObjectTemplate> templ2 = fun->InstanceTemplate();
+ Local<v8::FunctionTemplate> fun2 = v8::FunctionTemplate::New(isolate);
+ fun2->PrototypeTemplate()->Set(isolate, "nirk", v8_num(123));
+ Local<ObjectTemplate> templ2 = fun2->InstanceTemplate();
templ2->Set(isolate, "a", v8_num(12));
templ2->Set(isolate, "b", templ1);
Local<v8::Object> instance2 = templ2->NewInstance();
void* value) {
CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
obj->SetAlignedPointerInInternalField(0, value);
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
CHECK_EQ(value, obj->GetAlignedPointerFromInternalField(0));
}
void* value) {
CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
(*env)->SetAlignedPointerInEmbedderData(index, value);
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
CHECK_EQ(value, (*env)->GetAlignedPointerFromEmbedderData(index));
}
for (int i = 0; i < 100; i++) {
env->SetAlignedPointerInEmbedderData(i, AlignedTestPointer(i));
}
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
for (int i = 0; i < 100; i++) {
CHECK_EQ(AlignedTestPointer(i), env->GetAlignedPointerFromEmbedderData(i));
}
// Ensure that the test starts with an fresh heap to test whether the hash
// code is based on the address.
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
Local<v8::Object> obj = v8::Object::New(isolate);
int hash = obj->GetIdentityHash();
int hash1 = obj->GetIdentityHash();
// objects should not be assigned the same hash code. If the test below fails
// the random number generator should be evaluated.
CHECK_NE(hash, hash2);
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
int hash3 = v8::Object::New(isolate)->GetIdentityHash();
// Make sure that the identity hash is not based on the initial address of
// the object alone. If the test below fails the random number generator
}
-THREADED_TEST(GlobalProxyIdentityHash) {
+void GlobalProxyIdentityHash(bool set_in_js) {
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
v8::HandleScope scope(isolate);
Handle<Object> global_proxy = env->Global();
- int hash1 = global_proxy->GetIdentityHash();
+ i::Handle<i::Object> i_global_proxy = v8::Utils::OpenHandle(*global_proxy);
+ env->Global()->Set(v8_str("global"), global_proxy);
+ i::Handle<i::Object> original_hash;
+ if (set_in_js) {
+ CompileRun("var m = new Set(); m.add(global);");
+ original_hash = i::Handle<i::Object>(i_global_proxy->GetHash(), i_isolate);
+ } else {
+ original_hash = i::Handle<i::Object>(
+ i::Object::GetOrCreateHash(i_isolate, i_global_proxy));
+ }
+ CHECK(original_hash->IsSmi());
+ int32_t hash1 = i::Handle<i::Smi>::cast(original_hash)->value();
// Hash should be retained after being detached.
env->DetachGlobal();
int hash2 = global_proxy->GetIdentityHash();
}
+THREADED_TEST(GlobalProxyIdentityHash) {
+ GlobalProxyIdentityHash(true);
+ GlobalProxyIdentityHash(false);
+}
+
+
TEST(SymbolIdentityHash) {
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
int hash = symbol->GetIdentityHash();
int hash1 = symbol->GetIdentityHash();
CHECK_EQ(hash, hash1);
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
int hash3 = symbol->GetIdentityHash();
CHECK_EQ(hash, hash3);
}
int hash = js_symbol->GetIdentityHash();
int hash1 = js_symbol->GetIdentityHash();
CHECK_EQ(hash, hash1);
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
int hash3 = js_symbol->GetIdentityHash();
CHECK_EQ(hash, hash3);
}
int hash = str->GetIdentityHash();
int hash1 = str->GetIdentityHash();
CHECK_EQ(hash, hash1);
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
int hash3 = str->GetIdentityHash();
CHECK_EQ(hash, hash3);
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);
+ CcTest::heap()->CollectAllGarbage();
// Check basic symbol functionality.
CHECK(sym1->IsSymbol());
CHECK_EQ(1u, obj->GetOwnPropertyNames()->Length());
CHECK_EQ(num_props + 1, obj->GetPropertyNames()->Length());
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
CHECK(obj->SetAccessor(sym3, SymbolAccessorGetter, SymbolAccessorSetter));
CHECK(obj->Get(sym3)->IsUndefined());
}
-THREADED_TEST(PrivateProperties) {
- LocalContext env;
- v8::Isolate* isolate = env->GetIsolate();
- v8::HandleScope scope(isolate);
-
- v8::Local<v8::Object> obj = v8::Object::New(isolate);
- v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
- v8::Local<v8::Private> priv2 =
- v8::Private::New(isolate, v8_str("my-private"));
-
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
-
- CHECK(priv2->Name()->Equals(v8::String::NewFromUtf8(isolate, "my-private")));
-
- // Make sure delete of a non-existent private symbol property works.
- CHECK(obj->DeletePrivate(priv1));
- CHECK(!obj->HasPrivate(priv1));
-
- CHECK(obj->SetPrivate(priv1, v8::Integer::New(isolate, 1503)));
- CHECK(obj->HasPrivate(priv1));
- CHECK_EQ(1503, obj->GetPrivate(priv1)->Int32Value());
- CHECK(obj->SetPrivate(priv1, v8::Integer::New(isolate, 2002)));
- CHECK(obj->HasPrivate(priv1));
- CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
-
- CHECK_EQ(0u, obj->GetOwnPropertyNames()->Length());
- unsigned num_props = obj->GetPropertyNames()->Length();
- CHECK(obj->Set(v8::String::NewFromUtf8(isolate, "bla"),
- v8::Integer::New(isolate, 20)));
- CHECK_EQ(1u, obj->GetOwnPropertyNames()->Length());
- CHECK_EQ(num_props + 1, obj->GetPropertyNames()->Length());
-
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
-
- // Add another property and delete it afterwards to force the object in
- // slow case.
- CHECK(obj->SetPrivate(priv2, v8::Integer::New(isolate, 2008)));
- CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
- CHECK_EQ(2008, obj->GetPrivate(priv2)->Int32Value());
- CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
- CHECK_EQ(1u, obj->GetOwnPropertyNames()->Length());
-
- CHECK(obj->HasPrivate(priv1));
- CHECK(obj->HasPrivate(priv2));
- CHECK(obj->DeletePrivate(priv2));
- CHECK(obj->HasPrivate(priv1));
- CHECK(!obj->HasPrivate(priv2));
- CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
- CHECK_EQ(1u, obj->GetOwnPropertyNames()->Length());
-
- // Private properties are inherited (for the time being).
- v8::Local<v8::Object> child = v8::Object::New(isolate);
- child->SetPrototype(obj);
- CHECK(child->HasPrivate(priv1));
- CHECK_EQ(2002, child->GetPrivate(priv1)->Int32Value());
- CHECK_EQ(0u, child->GetOwnPropertyNames()->Length());
-}
-
-
THREADED_TEST(GlobalSymbols) {
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
}
-THREADED_TEST(GlobalPrivates) {
- LocalContext env;
- v8::Isolate* isolate = env->GetIsolate();
- v8::HandleScope scope(isolate);
-
- v8::Local<String> name = v8_str("my-private");
- v8::Local<v8::Private> glob = v8::Private::ForApi(isolate, name);
- v8::Local<v8::Object> obj = v8::Object::New(isolate);
- CHECK(obj->SetPrivate(glob, v8::Integer::New(isolate, 3)));
-
- v8::Local<v8::Private> glob2 = v8::Private::ForApi(isolate, name);
- CHECK(obj->HasPrivate(glob2));
-
- v8::Local<v8::Private> priv = v8::Private::New(isolate, name);
- CHECK(!obj->HasPrivate(priv));
-
- CompileRun("var intern = %CreateGlobalPrivateSymbol('my-private')");
- v8::Local<Value> intern = env->Global()->Get(v8_str("intern"));
- CHECK(!obj->Has(intern));
-}
-
-
class ScopedArrayBufferContents {
public:
explicit ScopedArrayBufferContents(const v8::ArrayBuffer::Contents& contents)
CheckInternalFieldsAreZero(ab);
CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
CHECK(!ab->IsExternal());
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
ScopedArrayBufferContents ab_contents(ab->Externalize());
CHECK(ab->IsExternal());
}
+class ScopedSharedArrayBufferContents {
+ public:
+ explicit ScopedSharedArrayBufferContents(
+ const v8::SharedArrayBuffer::Contents& contents)
+ : contents_(contents) {}
+ ~ScopedSharedArrayBufferContents() { free(contents_.Data()); }
+ void* Data() const { return contents_.Data(); }
+ size_t ByteLength() const { return contents_.ByteLength(); }
+
+ private:
+ const v8::SharedArrayBuffer::Contents contents_;
+};
+
+
+THREADED_TEST(SharedArrayBuffer_ApiInternalToExternal) {
+ i::FLAG_harmony_sharedarraybuffer = true;
+ LocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope handle_scope(isolate);
+
+ Local<v8::SharedArrayBuffer> ab = v8::SharedArrayBuffer::New(isolate, 1024);
+ CheckInternalFieldsAreZero(ab);
+ CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
+ CHECK(!ab->IsExternal());
+ CcTest::heap()->CollectAllGarbage();
+
+ ScopedSharedArrayBufferContents ab_contents(ab->Externalize());
+ CHECK(ab->IsExternal());
+
+ CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
+ uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
+ DCHECK(data != NULL);
+ env->Global()->Set(v8_str("ab"), ab);
+
+ v8::Handle<v8::Value> result = CompileRun("ab.byteLength");
+ CHECK_EQ(1024, result->Int32Value());
+
+ result = CompileRun(
+ "var u8 = new Uint8Array(ab);"
+ "u8[0] = 0xFF;"
+ "u8[1] = 0xAA;"
+ "u8.length");
+ CHECK_EQ(1024, result->Int32Value());
+ CHECK_EQ(0xFF, data[0]);
+ CHECK_EQ(0xAA, data[1]);
+ data[0] = 0xCC;
+ data[1] = 0x11;
+ result = CompileRun("u8[0] + u8[1]");
+ CHECK_EQ(0xDD, result->Int32Value());
+}
+
+
+THREADED_TEST(SharedArrayBuffer_JSInternalToExternal) {
+ i::FLAG_harmony_sharedarraybuffer = true;
+ LocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope handle_scope(isolate);
+
+
+ v8::Local<v8::Value> result = CompileRun(
+ "var ab1 = new SharedArrayBuffer(2);"
+ "var u8_a = new Uint8Array(ab1);"
+ "u8_a[0] = 0xAA;"
+ "u8_a[1] = 0xFF; u8_a.buffer");
+ Local<v8::SharedArrayBuffer> ab1 = Local<v8::SharedArrayBuffer>::Cast(result);
+ CheckInternalFieldsAreZero(ab1);
+ CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
+ CHECK(!ab1->IsExternal());
+ ScopedSharedArrayBufferContents ab1_contents(ab1->Externalize());
+ CHECK(ab1->IsExternal());
+
+ result = CompileRun("ab1.byteLength");
+ CHECK_EQ(2, result->Int32Value());
+ result = CompileRun("u8_a[0]");
+ CHECK_EQ(0xAA, result->Int32Value());
+ result = CompileRun("u8_a[1]");
+ CHECK_EQ(0xFF, result->Int32Value());
+ result = CompileRun(
+ "var u8_b = new Uint8Array(ab1);"
+ "u8_b[0] = 0xBB;"
+ "u8_a[0]");
+ CHECK_EQ(0xBB, result->Int32Value());
+ result = CompileRun("u8_b[1]");
+ CHECK_EQ(0xFF, result->Int32Value());
+
+ CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
+ uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
+ CHECK_EQ(0xBB, ab1_data[0]);
+ CHECK_EQ(0xFF, ab1_data[1]);
+ ab1_data[0] = 0xCC;
+ ab1_data[1] = 0x11;
+ result = CompileRun("u8_a[0] + u8_a[1]");
+ CHECK_EQ(0xDD, result->Int32Value());
+}
+
+
+THREADED_TEST(SharedArrayBuffer_External) {
+ i::FLAG_harmony_sharedarraybuffer = true;
+ LocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope handle_scope(isolate);
+
+ i::ScopedVector<uint8_t> my_data(100);
+ memset(my_data.start(), 0, 100);
+ Local<v8::SharedArrayBuffer> ab3 =
+ v8::SharedArrayBuffer::New(isolate, my_data.start(), 100);
+ CheckInternalFieldsAreZero(ab3);
+ CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
+ CHECK(ab3->IsExternal());
+
+ env->Global()->Set(v8_str("ab3"), ab3);
+
+ v8::Handle<v8::Value> result = CompileRun("ab3.byteLength");
+ CHECK_EQ(100, result->Int32Value());
+
+ result = CompileRun(
+ "var u8_b = new Uint8Array(ab3);"
+ "u8_b[0] = 0xBB;"
+ "u8_b[1] = 0xCC;"
+ "u8_b.length");
+ CHECK_EQ(100, result->Int32Value());
+ CHECK_EQ(0xBB, my_data[0]);
+ CHECK_EQ(0xCC, my_data[1]);
+ my_data[0] = 0xCC;
+ my_data[1] = 0x11;
+ result = CompileRun("u8_b[0] + u8_b[1]");
+ CHECK_EQ(0xDD, result->Int32Value());
+}
+
+
THREADED_TEST(HiddenProperties) {
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
v8::Local<v8::String> empty = v8_str("");
v8::Local<v8::String> prop_name = v8_str("prop_name");
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
// Make sure delete of a non-existent hidden value works
CHECK(obj->DeleteHiddenValue(key));
CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 2002)));
CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
// Make sure we do not find the hidden property.
CHECK(!obj->Has(empty));
CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
CHECK_EQ(2003, obj->Get(empty)->Int32Value());
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
// Add another property and delete it afterwards to force the object in
// slow case.
CHECK(obj->Delete(prop_name));
CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
CHECK(obj->SetHiddenValue(key, Handle<Value>()));
CHECK(obj->GetHiddenValue(key).IsEmpty());
if (!trigger_gc) return;
auto data_2 = new TwoPassCallbackData(data.GetIsolate(), instance_counter);
data_2->SetWeak();
- CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+ CcTest::heap()->CollectAllGarbage();
}
data->SetWeak();
}
CHECK_EQ(static_cast<int>(kLength), instance_counter);
- CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+ CcTest::heap()->CollectAllGarbage();
CHECK_EQ(0, instance_counter);
}
array[10]->MarkTriggerGc();
array[15]->MarkTriggerGc();
CHECK_EQ(static_cast<int>(kLength), instance_counter);
- CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+ CcTest::heap()->CollectAllGarbage();
CHECK_EQ(0, instance_counter);
}
-template <typename K, typename V>
-class WeakStdMapTraits : public v8::StdMapTraits<K, V> {
- public:
- typedef typename v8::PersistentValueMap<K, V, WeakStdMapTraits<K, V>> MapType;
- static const v8::PersistentContainerCallbackType kCallbackType = v8::kWeak;
- struct WeakCallbackDataType {
- MapType* map;
- K key;
- };
- static WeakCallbackDataType* WeakCallbackParameter(MapType* map, const K& key,
- Local<V> value) {
- WeakCallbackDataType* data = new WeakCallbackDataType;
- data->map = map;
- data->key = key;
- return data;
- }
- static MapType* MapFromWeakCallbackData(
- const v8::WeakCallbackData<V, WeakCallbackDataType>& data) {
- return data.GetParameter()->map;
- }
- static K KeyFromWeakCallbackData(
- const v8::WeakCallbackData<V, WeakCallbackDataType>& data) {
- return data.GetParameter()->key;
- }
- static void DisposeCallbackData(WeakCallbackDataType* data) { delete data; }
- static void Dispose(v8::Isolate* isolate, v8::Global<V> value, K key) {}
-};
-
-
-template <typename Map>
-static void TestPersistentValueMap() {
- LocalContext env;
- v8::Isolate* isolate = env->GetIsolate();
- Map map(isolate);
- v8::internal::GlobalHandles* global_handles =
- reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
- int initial_handle_count = global_handles->global_handles_count();
- CHECK_EQ(0, static_cast<int>(map.Size()));
- {
- HandleScope scope(isolate);
- Local<v8::Object> obj = map.Get(7);
- CHECK(obj.IsEmpty());
- Local<v8::Object> expected = v8::Object::New(isolate);
- map.Set(7, expected);
- CHECK_EQ(1, static_cast<int>(map.Size()));
- obj = map.Get(7);
- CHECK(expected->Equals(obj));
- {
- typename Map::PersistentValueReference ref = map.GetReference(7);
- CHECK(expected->Equals(ref.NewLocal(isolate)));
- }
- v8::Global<v8::Object> removed = map.Remove(7);
- CHECK_EQ(0, static_cast<int>(map.Size()));
- CHECK(expected == removed);
- removed = map.Remove(7);
- CHECK(removed.IsEmpty());
- map.Set(8, expected);
- CHECK_EQ(1, static_cast<int>(map.Size()));
- map.Set(8, expected);
- CHECK_EQ(1, static_cast<int>(map.Size()));
- {
- typename Map::PersistentValueReference ref;
- Local<v8::Object> expected2 = v8::Object::New(isolate);
- removed = map.Set(8, v8::Global<v8::Object>(isolate, expected2), &ref);
- CHECK_EQ(1, static_cast<int>(map.Size()));
- CHECK(expected == removed);
- CHECK(expected2->Equals(ref.NewLocal(isolate)));
- }
- }
- CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
- if (map.IsWeak()) {
- reinterpret_cast<v8::internal::Isolate*>(isolate)
- ->heap()
- ->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
- } else {
- map.Clear();
- }
- CHECK_EQ(0, static_cast<int>(map.Size()));
- CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
-}
-
-
-TEST(PersistentValueMap) {
- // Default case, w/o weak callbacks:
- TestPersistentValueMap<v8::StdPersistentValueMap<int, v8::Object>>();
-
- // Custom traits with weak callbacks:
- typedef v8::PersistentValueMap<int, v8::Object,
- WeakStdMapTraits<int, v8::Object>>
- WeakPersistentValueMap;
- TestPersistentValueMap<WeakPersistentValueMap>();
-}
-
-
namespace {
void* IntKeyToVoidPointer(int key) { return reinterpret_cast<void*>(key << 1); }
v8::Object::GetAlignedPointerFromInternalField(value, 0));
}
static void DisposeWeak(
- v8::Isolate* isolate,
- const v8::WeakCallbackInfo<WeakCallbackDataType>& info, K key) {
+ const v8::WeakCallbackInfo<WeakCallbackDataType>& info) {
+ K key = KeyFromWeakCallbackInfo(info);
CHECK_EQ(IntKeyToVoidPointer(key), info.GetInternalField(0));
DisposeCallbackData(info.GetParameter());
}
};
-} // namespace
-
-TEST(GlobalValueMap) {
- typedef v8::GlobalValueMap<int, v8::Object,
- PhantomStdMapTraits<int, v8::Object>> Map;
+template <typename Map>
+void TestGlobalValueMap() {
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
v8::Global<ObjectTemplate> templ;
obj = map.Get(7);
CHECK(expected->Equals(obj));
{
- Map::PersistentValueReference ref = map.GetReference(7);
+ typename Map::PersistentValueReference ref = map.GetReference(7);
CHECK(expected->Equals(ref.NewLocal(isolate)));
}
v8::Global<v8::Object> removed = map.Remove(7);
map.Set(8, expected);
CHECK_EQ(1, static_cast<int>(map.Size()));
{
- Map::PersistentValueReference ref;
+ typename Map::PersistentValueReference ref;
Local<v8::Object> expected2 = NewObjectForIntKey(isolate, templ, 8);
removed = map.Set(8, v8::Global<v8::Object>(isolate, expected2), &ref);
CHECK_EQ(1, static_cast<int>(map.Size()));
}
}
CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
- CcTest::i_isolate()->heap()->CollectAllGarbage(
- i::Heap::kAbortIncrementalMarkingMask);
- CHECK_EQ(0, static_cast<int>(map.Size()));
+ if (map.IsWeak()) {
+ CcTest::i_isolate()->heap()->CollectAllGarbage(
+ i::Heap::kAbortIncrementalMarkingMask);
+ } else {
+ map.Clear();
+ }
+ CHECK_EQ(0, static_cast<int>(map.Size()));
CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
{
HandleScope scope(isolate);
CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
}
+} // namespace
+
+
+TEST(GlobalValueMap) {
+ // Default case, w/o weak callbacks:
+ TestGlobalValueMap<v8::StdGlobalValueMap<int, v8::Object>>();
+
+ // Custom traits with weak callbacks:
+ typedef v8::GlobalValueMap<int, v8::Object,
+ PhantomStdMapTraits<int, v8::Object>> WeakMap;
+ TestGlobalValueMap<WeakMap>();
+}
+
TEST(PersistentValueVector) {
LocalContext env;
template <typename T>
static void WeakPointerCallback(
- const v8::WeakCallbackData<T, WeakCallCounterAndPersistent<T>>& data) {
+ const v8::WeakCallbackInfo<WeakCallCounterAndPersistent<T>>& data) {
CHECK_EQ(1234, data.GetParameter()->counter->id());
data.GetParameter()->counter->increment();
data.GetParameter()->handle.Reset();
g1s1.handle.Reset(iso, Object::New(iso));
g1s2.handle.Reset(iso, Object::New(iso));
g1c1.handle.Reset(iso, Object::New(iso));
- g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
- g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
- g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
+ g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
+ g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
+ g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
g2s1.handle.Reset(iso, Object::New(iso));
g2s2.handle.Reset(iso, Object::New(iso));
g2c1.handle.Reset(iso, Object::New(iso));
- g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
- g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
- g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
+ g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
+ g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
+ g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
}
WeakCallCounterAndPersistent<Value> root(&counter);
// Do a single full GC, ensure incremental marking is stopped.
v8::internal::Heap* heap =
reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
- heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+ heap->CollectAllGarbage();
// All object should be alive.
CHECK_EQ(0, counter.NumberOfWeakCalls());
// Weaken the root.
- root.handle.SetWeak(&root, &WeakPointerCallback);
+ root.handle.SetWeak(&root, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
// But make children strong roots---all the objects (except for children)
// should be collectable now.
g1c1.handle.ClearWeak();
iso->SetReferenceFromGroup(id2, g2c1.handle);
}
- heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+ heap->CollectAllGarbage();
// All objects should be gone. 5 global handles in total.
CHECK_EQ(5, counter.NumberOfWeakCalls());
// And now make children weak again and collect them.
- g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
- g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
+ g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
+ g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
- heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+ heap->CollectAllGarbage();
CHECK_EQ(7, counter.NumberOfWeakCalls());
}
g1s1.handle.Reset(iso, Object::New(iso));
g1s2.handle.Reset(iso, String::NewFromUtf8(iso, "foo1"));
g1c1.handle.Reset(iso, String::NewFromUtf8(iso, "foo2"));
- g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
- g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
- g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
+ g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
+ g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
+ g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
g2s1.handle.Reset(iso, Object::New(iso));
g2s2.handle.Reset(iso, String::NewFromUtf8(iso, "foo3"));
g2c1.handle.Reset(iso, String::NewFromUtf8(iso, "foo4"));
- g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
- g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
- g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
+ g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
+ g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
+ g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
}
WeakCallCounterAndPersistent<Value> root(&counter);
// Do a single full GC, ensure incremental marking is stopped.
v8::internal::Heap* heap =
reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
- heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+ heap->CollectAllGarbage();
// All object should be alive.
CHECK_EQ(0, counter.NumberOfWeakCalls());
// Weaken the root.
- root.handle.SetWeak(&root, &WeakPointerCallback);
+ root.handle.SetWeak(&root, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
// But make children strong roots---all the objects (except for children)
// should be collectable now.
g1c1.handle.ClearWeak();
iso->SetReferenceFromGroup(id2, g2c1.handle);
}
- heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+ heap->CollectAllGarbage();
// All objects should be gone. 5 global handles in total.
CHECK_EQ(5, counter.NumberOfWeakCalls());
// And now make children weak again and collect them.
- g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
- g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
+ g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
+ g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
- heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+ heap->CollectAllGarbage();
CHECK_EQ(7, counter.NumberOfWeakCalls());
}
HandleScope scope(iso);
g1s1.handle.Reset(iso, Object::New(iso));
g1s2.handle.Reset(iso, Object::New(iso));
- g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
- g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
+ g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
+ g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
CHECK(g1s1.handle.IsWeak());
CHECK(g1s2.handle.IsWeak());
g2s1.handle.Reset(iso, Object::New(iso));
g2s2.handle.Reset(iso, Object::New(iso));
- g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
- g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
+ g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
+ g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
CHECK(g2s1.handle.IsWeak());
CHECK(g2s2.handle.IsWeak());
g3s1.handle.Reset(iso, Object::New(iso));
g3s2.handle.Reset(iso, Object::New(iso));
- g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback);
- g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback);
+ g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
+ g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
CHECK(g3s1.handle.IsWeak());
CHECK(g3s2.handle.IsWeak());
g4s1.handle.Reset(iso, Object::New(iso));
g4s2.handle.Reset(iso, Object::New(iso));
- g4s1.handle.SetWeak(&g4s1, &WeakPointerCallback);
- g4s2.handle.SetWeak(&g4s2, &WeakPointerCallback);
+ g4s1.handle.SetWeak(&g4s1, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
+ g4s2.handle.SetWeak(&g4s2, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
CHECK(g4s1.handle.IsWeak());
CHECK(g4s2.handle.IsWeak());
}
// Do a single full GC
v8::internal::Heap* heap =
reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
- heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+ heap->CollectAllGarbage();
// All object should be alive.
CHECK_EQ(0, counter.NumberOfWeakCalls());
// Weaken the root.
- root.handle.SetWeak(&root, &WeakPointerCallback);
+ root.handle.SetWeak(&root, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
// Groups are deleted, rebuild groups.
{
iso->SetReferenceFromGroup(id4, g1s1.handle);
}
- heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+ heap->CollectAllGarbage();
// All objects should be gone. 9 global handles in total.
CHECK_EQ(9, counter.NumberOfWeakCalls());
}
-THREADED_TEST(WeakRootsSurviveTwoRoundsOfGC) {
- LocalContext env;
- v8::Isolate* iso = env->GetIsolate();
- HandleScope scope(iso);
-
- WeakCallCounter counter(1234);
-
- WeakCallCounterAndPersistent<Value> weak_obj(&counter);
-
- // Create a weak object that references a internalized string.
- {
- HandleScope scope(iso);
- weak_obj.handle.Reset(iso, Object::New(iso));
- weak_obj.handle.SetWeak(&weak_obj, &WeakPointerCallback);
- CHECK(weak_obj.handle.IsWeak());
- Local<Object>::New(iso, weak_obj.handle.As<Object>())
- ->Set(v8_str("x"), String::NewFromUtf8(iso, "magic cookie",
- String::kInternalizedString));
- }
- // Do a single full GC
- i::Isolate* i_iso = reinterpret_cast<v8::internal::Isolate*>(iso);
- i::Heap* heap = i_iso->heap();
- heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
-
- // We should have received the weak callback.
- CHECK_EQ(1, counter.NumberOfWeakCalls());
-
- // Check that the string is still alive.
- {
- HandleScope scope(iso);
- i::MaybeHandle<i::String> magic_string =
- i::StringTable::LookupStringIfExists(
- i_iso,
- v8::Utils::OpenHandle(*String::NewFromUtf8(iso, "magic cookie")));
- magic_string.Check();
- }
-}
-
-
// TODO(mstarzinger): This should be a THREADED_TEST but causes failures
// on the buildbots, so was made non-threaded for the time being.
TEST(ApiObjectGroupsCycleForScavenger) {
HandleScope scope(iso);
g1s1.handle.Reset(iso, Object::New(iso));
g1s2.handle.Reset(iso, Object::New(iso));
- g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
- g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
+ g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
+ g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
g2s1.handle.Reset(iso, Object::New(iso));
g2s2.handle.Reset(iso, Object::New(iso));
- g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
- g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
+ g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
+ g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
g3s1.handle.Reset(iso, Object::New(iso));
g3s2.handle.Reset(iso, Object::New(iso));
- g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback);
- g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback);
+ g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
+ g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
}
// Make a root.
v8::internal::Heap* heap =
reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
- heap->CollectAllGarbage(i::Heap::kNoGCFlags);
+ heap->CollectAllGarbage();
// All objects should be alive.
CHECK_EQ(0, counter.NumberOfWeakCalls());
// Weaken the root.
- root.handle.SetWeak(&root, &WeakPointerCallback);
+ root.handle.SetWeak(&root, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
root.handle.MarkPartiallyDependent();
// Groups are deleted, rebuild groups.
->Set(v8_str("x"), Local<Value>::New(iso, g1s1.handle));
}
- heap->CollectAllGarbage(i::Heap::kNoGCFlags);
+ heap->CollectAllGarbage();
// All objects should be gone. 7 global handles in total.
CHECK_EQ(7, counter.NumberOfWeakCalls());
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
Local<Script> script = v8_compile("throw 'panama!';");
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(env->GetIsolate());
Local<Value> result = script->Run();
CHECK(result.IsEmpty());
CHECK(try_catch.HasCaught());
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
v8::HandleScope scope(isolate);
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
CompileRun(
"function CustomError() { this.a = 'b'; }"
"(function f() { throw new CustomError(); })();");
static void check_message_3(v8::Handle<v8::Message> message,
v8::Handle<Value> data) {
CHECK(message->IsSharedCrossOrigin());
- CHECK(message->GetScriptOrigin().ResourceIsSharedCrossOrigin()->Value());
- CHECK(message->GetScriptOrigin().ResourceIsEmbedderDebugScript()->Value());
+ CHECK(message->GetScriptOrigin().Options().IsSharedCrossOrigin());
+ CHECK(message->GetScriptOrigin().Options().IsEmbedderDebugScript());
+ CHECK(message->GetScriptOrigin().Options().IsOpaque());
CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
CHECK_EQ(7.40, message->GetScriptOrigin().SourceMapUrl()->NumberValue());
message_received = true;
v8::ScriptOrigin origin = v8::ScriptOrigin(
v8_str("6.75"), v8::Integer::New(isolate, 1),
v8::Integer::New(isolate, 2), v8::True(isolate), Handle<v8::Integer>(),
- v8::True(isolate), v8_str("7.40"));
+ v8::True(isolate), v8_str("7.40"), v8::True(isolate));
v8::Handle<v8::Script> script =
Script::Compile(v8_str("throw 'error'"), &origin);
script->Run();
CHECK(!message_received);
v8::V8::AddMessageListener(check_message_5a);
LocalContext context;
- v8::ScriptOrigin origin =
+ v8::ScriptOrigin origin1 =
v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
v8::Integer::New(isolate, 2), v8::True(isolate));
v8::Handle<v8::Script> script =
- Script::Compile(v8_str("throw 'error'"), &origin);
+ Script::Compile(v8_str("throw 'error'"), &origin1);
script->Run();
CHECK(message_received);
// clear out the message listener
message_received = false;
v8::V8::AddMessageListener(check_message_5b);
- origin = v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
- v8::Integer::New(isolate, 2), v8::False(isolate));
- script = Script::Compile(v8_str("throw 'error'"), &origin);
+ v8::ScriptOrigin origin2 =
+ v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
+ v8::Integer::New(isolate, 2), v8::False(isolate));
+ script = Script::Compile(v8_str("throw 'error'"), &origin2);
script->Run();
CHECK(message_received);
// clear out the message listener
CHECK(value->Equals(weak_map->Get(obj2)));
CHECK(value->Equals(weak_map->Get(sym1)));
}
- CcTest::heap()->CollectAllGarbage(TestHeap::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
{
HandleScope scope(isolate);
CHECK(value->Equals(weak_map->Get(local1)));
CHECK(value->Equals(weak_map->Get(Local<Value>::New(isolate, s1.handle))));
}
- o1.handle.SetWeak(&o1, &WeakPointerCallback);
- o2.handle.SetWeak(&o2, &WeakPointerCallback);
- s1.handle.SetWeak(&s1, &WeakPointerCallback);
+ o1.handle.SetWeak(&o1, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
+ o2.handle.SetWeak(&o2, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
+ s1.handle.SetWeak(&s1, &WeakPointerCallback,
+ v8::WeakCallbackType::kParameter);
- CcTest::heap()->CollectAllGarbage(TestHeap::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
CHECK_EQ(3, counter.NumberOfWeakCalls());
CHECK(o1.handle.IsEmpty());
Local<Value> fake_prop = v8_num(1);
CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(fake_prop));
// exception
- TryCatch try_catch;
+ TryCatch try_catch(context->GetIsolate());
Local<Value> exception =
CompileRun("({ toString: function() { throw 'exception';} })");
CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(exception));
return;
}
v8::HandleScope scope(args.GetIsolate());
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(args.GetIsolate());
Local<Value> result = CompileRun(args[0]->ToString(args.GetIsolate()));
CHECK(!try_catch.HasCaught() || result.IsEmpty());
args.GetReturnValue().Set(try_catch.HasCaught());
templ->Set(v8_str("ThrowFromC"),
v8::FunctionTemplate::New(isolate, ThrowFromC));
LocalContext context(0, templ);
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
CompileRun("ThrowFromC();");
CHECK(try_catch.HasCaught());
}
}
+static void check_custom_rethrowing_message(v8::Handle<v8::Message> message,
+ v8::Handle<v8::Value> data) {
+ const char* uncaught_error = "Uncaught exception";
+ CHECK(message->Get()->Equals(v8_str(uncaught_error)));
+}
+
+
+TEST(CustomErrorRethrowsOnToString) {
+ LocalContext context;
+ v8::HandleScope scope(context->GetIsolate());
+ v8::V8::AddMessageListener(check_custom_rethrowing_message);
+
+ CompileRun(
+ "var e = { toString: function() { throw e; } };"
+ "try { throw e; } finally {}");
+
+ v8::V8::RemoveMessageListeners(check_custom_rethrowing_message);
+}
+
+
static void receive_message(v8::Handle<v8::Message> message,
v8::Handle<v8::Value> data) {
message->Get();
templ->Set(v8_str("ThrowFromC"),
v8::FunctionTemplate::New(isolate, ThrowFromC));
LocalContext context(0, templ);
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
try_catch.SetVerbose(true);
Local<Value> result = CompileRun("ThrowFromC();");
CHECK(try_catch.HasCaught());
LocalContext context;
v8::HandleScope scope(context->GetIsolate());
v8::V8::AddMessageListener(receive_message);
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(context->GetIsolate());
try_catch.SetVerbose(true);
Local<Value> result = CompileRun("function foo() { foo(); } foo();");
CHECK(try_catch.HasCaught());
v8::FunctionTemplate::New(isolate, ThrowFromC));
LocalContext context(0, templ);
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
Local<Value> result = CompileRun("ThrowFromC(); throw 'panama';");
CHECK(result.IsEmpty());
CHECK(try_catch.HasCaught());
Local<Value> fun = global->Get(v8_str("JSThrowCountDown"));
v8::Handle<Value> argv[] = {v8_num(count - 1), args[1], args[2], args[3]};
if (count % cInterval == 0) {
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(args.GetIsolate());
Local<Value> result = fun.As<Function>()->Call(global, 4, argv);
int expected = args[3]->Int32Value();
if (try_catch.HasCaught()) {
THREADED_TEST(EvalInTryFinally) {
LocalContext context;
v8::HandleScope scope(context->GetIsolate());
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(context->GetIsolate());
CompileRun(
"(function() {"
" try {"
THREADED_TEST(CatchZero) {
LocalContext context;
v8::HandleScope scope(context->GetIsolate());
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(context->GetIsolate());
CHECK(!try_catch.HasCaught());
CompileRun("throw 10");
CHECK(try_catch.HasCaught());
THREADED_TEST(CatchExceptionFromWith) {
LocalContext context;
v8::HandleScope scope(context->GetIsolate());
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(context->GetIsolate());
CHECK(!try_catch.HasCaught());
CompileRun("var o = {}; with (o) { throw 42; }");
CHECK(try_catch.HasCaught());
THREADED_TEST(TryCatchAndFinallyHidingException) {
LocalContext context;
v8::HandleScope scope(context->GetIsolate());
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(context->GetIsolate());
CHECK(!try_catch.HasCaught());
CompileRun("function f(k) { try { this[k]; } finally { return 0; } };");
CompileRun("f({toString: function() { throw 42; }});");
void WithTryCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(args.GetIsolate());
}
context->Global()->Set(
v8_str("native_with_try_catch"),
v8::FunctionTemplate::New(isolate, WithTryCatch)->GetFunction());
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
CHECK(!try_catch.HasCaught());
CompileRun(
"try {\n"
static void TryCatchNested1Helper(int depth) {
if (depth > 0) {
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(CcTest::isolate());
try_catch.SetVerbose(true);
TryCatchNested1Helper(depth - 1);
CHECK(try_catch.HasCaught());
static void TryCatchNested2Helper(int depth) {
if (depth > 0) {
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(CcTest::isolate());
try_catch.SetVerbose(true);
TryCatchNested2Helper(depth - 1);
CHECK(try_catch.HasCaught());
{
// Test nested try-catch with a native throw in the end.
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(context->GetIsolate());
TryCatchNested1Helper(5);
CHECK(try_catch.HasCaught());
CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "E1"));
{
// Test nested try-catch with a JavaScript throw in the end.
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(context->GetIsolate());
TryCatchNested2Helper(5);
CHECK(try_catch.HasCaught());
CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "E2"));
CHECK_EQ(0,
strcmp(*v8::String::Utf8Value(message->Get()), "Uncaught Error: a"));
CHECK_EQ(1, message->GetLineNumber());
- CHECK_EQ(6, message->GetStartColumn());
+ CHECK_EQ(0, message->GetStartColumn());
}
void TryCatchMixedNestingHelper(
const v8::FunctionCallbackInfo<v8::Value>& args) {
ApiTestFuzzer::Fuzz();
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(args.GetIsolate());
CompileRunWithOrigin("throw new Error('a');\n", "inner", 0, 0);
CHECK(try_catch.HasCaught());
TryCatchMixedNestingCheck(&try_catch);
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope scope(isolate);
v8::V8::Initialize();
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
templ->Set(v8_str("TryCatchMixedNestingHelper"),
v8::FunctionTemplate::New(isolate, TryCatchMixedNestingHelper));
void TryCatchNativeHelper(const v8::FunctionCallbackInfo<v8::Value>& args) {
ApiTestFuzzer::Fuzz();
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(args.GetIsolate());
args.GetIsolate()->ThrowException(v8_str("boom"));
CHECK(try_catch.HasCaught());
}
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope scope(isolate);
v8::V8::Initialize();
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
templ->Set(v8_str("TryCatchNativeHelper"),
v8::FunctionTemplate::New(isolate, TryCatchNativeHelper));
void TryCatchNativeResetHelper(
const v8::FunctionCallbackInfo<v8::Value>& args) {
ApiTestFuzzer::Fuzz();
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(args.GetIsolate());
args.GetIsolate()->ThrowException(v8_str("boom"));
CHECK(try_catch.HasCaught());
try_catch.Reset();
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope scope(isolate);
v8::V8::Initialize();
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
templ->Set(v8_str("TryCatchNativeResetHelper"),
v8::FunctionTemplate::New(isolate, TryCatchNativeResetHelper));
CHECK_EQ(result->BooleanValue(), false);
// Make sure that it is not possible to redefine again
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
result = script_define->Run();
CHECK(try_catch.HasCaught());
String::Utf8Value exception_value(try_catch.Exception());
CHECK_EQ(result->BooleanValue(), false);
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
result = script_define->Run();
CHECK(try_catch.HasCaught());
String::Utf8Value exception_value(try_catch.Exception());
->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
{
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
CompileRun(
"Object.defineProperty(obj1, 'x',"
"{get: function() { return 'func'; }})");
0, strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
}
{
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
CompileRun(
"Object.defineProperty(obj2, 'x',"
"{get: function() { return 'func'; }})");
b->Set(v8_str("x"), a);
}
if (global_gc) {
- CcTest::heap()->CollectAllGarbage(TestHeap::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
} else {
CcTest::heap()->CollectGarbage(i::NEW_SPACE);
}
object_b.handle.MarkIndependent();
CHECK(object_b.handle.IsIndependent());
if (global_gc) {
- CcTest::heap()->CollectAllGarbage(TestHeap::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
} else {
CcTest::heap()->CollectGarbage(i::NEW_SPACE);
}
}
-THREADED_TEST(IndependentWeakHandle) {
+TEST(IndependentWeakHandle) {
IndependentWeakHandle(false, false);
IndependentWeakHandle(false, true);
IndependentWeakHandle(true, false);
}
}
if (global_gc) {
- CcTest::heap()->CollectAllGarbage(TestHeap::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
} else {
CcTest::heap()->CollectGarbage(i::NEW_SPACE);
}
static void ResetUseValueAndSetFlag(
- const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
+ const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
// Blink will reset the handle, and then use the other handle, so they
// can't use the same backing slot.
data.GetParameter()->handle.Reset();
- data.GetValue()->IsBoolean(); // Make sure the handle still works.
data.GetParameter()->flag = true;
}
object_a.flag = false;
object_b.flag = false;
- object_a.handle.SetWeak(&object_a, &ResetUseValueAndSetFlag);
- object_b.handle.SetWeak(&object_b, &ResetUseValueAndSetFlag);
+ object_a.handle.SetWeak(&object_a, &ResetUseValueAndSetFlag,
+ v8::WeakCallbackType::kParameter);
+ object_b.handle.SetWeak(&object_b, &ResetUseValueAndSetFlag,
+ v8::WeakCallbackType::kParameter);
if (!global_gc) {
object_a.handle.MarkIndependent();
object_b.handle.MarkIndependent();
static void InvokeScavenge() { CcTest::heap()->CollectGarbage(i::NEW_SPACE); }
-static void InvokeMarkSweep() {
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
-}
+static void InvokeMarkSweep() { CcTest::heap()->CollectAllGarbage(); }
-static void ForceScavenge(
- const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
- data.GetParameter()->handle.Reset();
+static void ForceScavenge2(
+ const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
data.GetParameter()->flag = true;
InvokeScavenge();
}
-
-static void ForceMarkSweep(
- const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
+static void ForceScavenge1(
+ const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
data.GetParameter()->handle.Reset();
+ data.SetSecondPassCallback(ForceScavenge2);
+}
+
+
+static void ForceMarkSweep2(
+ const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
data.GetParameter()->flag = true;
InvokeMarkSweep();
}
+static void ForceMarkSweep1(
+ const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
+ data.GetParameter()->handle.Reset();
+ data.SetSecondPassCallback(ForceMarkSweep2);
+}
+
THREADED_TEST(GCFromWeakCallbacks) {
v8::Isolate* isolate = CcTest::isolate();
Context::Scope context_scope(context);
static const int kNumberOfGCTypes = 2;
- typedef v8::WeakCallbackData<v8::Object, FlagAndPersistent>::Callback
- Callback;
- Callback gc_forcing_callback[kNumberOfGCTypes] =
- {&ForceScavenge, &ForceMarkSweep};
+ typedef v8::WeakCallbackInfo<FlagAndPersistent>::Callback Callback;
+ Callback gc_forcing_callback[kNumberOfGCTypes] = {&ForceScavenge1,
+ &ForceMarkSweep1};
typedef void (*GCInvoker)();
GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep};
object.handle.Reset(isolate, v8::Object::New(isolate));
}
object.flag = false;
- object.handle.SetWeak(&object, gc_forcing_callback[inner_gc]);
+ object.handle.SetWeak(&object, gc_forcing_callback[inner_gc],
+ v8::WeakCallbackType::kParameter);
object.handle.MarkIndependent();
invoke_gc[outer_gc]();
CHECK(object.flag);
}
-static void RevivingCallback(
- const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
- data.GetParameter()->handle.ClearWeak();
- data.GetParameter()->flag = true;
-}
-
-
-THREADED_TEST(IndependentHandleRevival) {
- v8::Isolate* isolate = CcTest::isolate();
- v8::HandleScope scope(isolate);
- v8::Handle<Context> context = Context::New(isolate);
- Context::Scope context_scope(context);
-
- FlagAndPersistent object;
- {
- v8::HandleScope handle_scope(isolate);
- v8::Local<v8::Object> o = v8::Object::New(isolate);
- object.handle.Reset(isolate, o);
- o->Set(v8_str("x"), v8::Integer::New(isolate, 1));
- v8::Local<String> y_str = v8_str("y");
- o->Set(y_str, y_str);
- }
- object.flag = false;
- object.handle.SetWeak(&object, &RevivingCallback);
- object.handle.MarkIndependent();
- CcTest::heap()->CollectGarbage(i::NEW_SPACE);
- CHECK(object.flag);
- CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
- {
- v8::HandleScope handle_scope(isolate);
- v8::Local<v8::Object> o =
- v8::Local<v8::Object>::New(isolate, object.handle);
- v8::Local<String> y_str = v8_str("y");
- CHECK(v8::Integer::New(isolate, 1)->Equals(o->Get(v8_str("x"))));
- CHECK(o->Get(y_str)->Equals(y_str));
- }
-}
-
-
v8::Handle<Function> args_fun;
CHECK(v8::Integer::New(isolate, 3)->Equals(args[2]));
CHECK(v8::Undefined(isolate)->Equals(args[3]));
v8::HandleScope scope(args.GetIsolate());
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
}
}
-static uint16_t StringGet(Handle<String> str, int index) {
- i::Handle<i::String> istring =
- v8::Utils::OpenHandle(String::Cast(*str));
- return istring->Get(index);
-}
-
-
-static void WriteUtf8Helper(
- LocalContext& context, // NOLINT
- const char* name,
- const char* lengths_name,
- int len) {
- Local<v8::Array> b =
- Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
- Local<v8::Array> alens =
- Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
- char buffer[1000];
- char buffer2[1000];
- for (int i = 0; i < len; i++) {
- Local<v8::String> string =
- Local<v8::String>::Cast(b->Get(i));
- Local<v8::Number> expected_len =
- Local<v8::Number>::Cast(alens->Get(i));
- int utf8_length = static_cast<int>(expected_len->Value());
- for (int j = utf8_length + 1; j >= 0; j--) {
- memset(reinterpret_cast<void*>(&buffer), 42, sizeof(buffer));
- memset(reinterpret_cast<void*>(&buffer2), 42, sizeof(buffer2));
- int nchars;
- int utf8_written =
- string->WriteUtf8(buffer, j, &nchars, String::NO_OPTIONS);
- int utf8_written2 =
- string->WriteUtf8(buffer2, j, &nchars, String::NO_NULL_TERMINATION);
- CHECK_GE(utf8_length + 1, utf8_written);
- CHECK_GE(utf8_length, utf8_written2);
- for (int k = 0; k < utf8_written2; k++) {
- CHECK_EQ(buffer[k], buffer2[k]);
- }
- CHECK(nchars * 3 >= utf8_written - 1);
- CHECK(nchars <= utf8_written);
- if (j == utf8_length + 1) {
- CHECK_EQ(utf8_written2, utf8_length);
- CHECK_EQ(utf8_written2 + 1, utf8_written);
- }
- CHECK_EQ(buffer[utf8_written], 42);
- if (j > utf8_length) {
- if (utf8_written != 0) CHECK_EQ(buffer[utf8_written - 1], 0);
- if (utf8_written > 1) CHECK_NE(buffer[utf8_written - 2], 42);
- Handle<String> roundtrip = v8_str(buffer);
- CHECK(roundtrip->Equals(string));
- } else {
- if (utf8_written != 0) CHECK_NE(buffer[utf8_written - 1], 42);
- }
- if (utf8_written2 != 0) CHECK_NE(buffer[utf8_written - 1], 42);
- if (nchars >= 2) {
- uint16_t trail = StringGet(string, nchars - 1);
- uint16_t lead = StringGet(string, nchars - 2);
- if (((lead & 0xfc00) == 0xd800) &&
- ((trail & 0xfc00) == 0xdc00)) {
- unsigned u1 = buffer2[utf8_written2 - 4];
- unsigned u2 = buffer2[utf8_written2 - 3];
- unsigned u3 = buffer2[utf8_written2 - 2];
- unsigned u4 = buffer2[utf8_written2 - 1];
- CHECK_EQ((u1 & 0xf8), 0xf0u);
- CHECK_EQ((u2 & 0xc0), 0x80u);
- CHECK_EQ((u3 & 0xc0), 0x80u);
- CHECK_EQ((u4 & 0xc0), 0x80u);
- uint32_t c = 0x10000 + ((lead & 0x3ff) << 10) + (trail & 0x3ff);
- CHECK_EQ((u4 & 0x3f), (c & 0x3f));
- CHECK_EQ((u3 & 0x3f), ((c >> 6) & 0x3f));
- CHECK_EQ((u2 & 0x3f), ((c >> 12) & 0x3f));
- CHECK_EQ((u1 & 0x3), c >> 18);
- }
- }
- }
- }
-}
-
-
THREADED_TEST(Utf16) {
LocalContext context;
v8::HandleScope scope(context->GetIsolate());
"}");
Utf16Helper(context, "a", "alens", 9);
Utf16Helper(context, "a2", "a2lens", 81);
- WriteUtf8Helper(context, "b", "alens", 9);
- WriteUtf8Helper(context, "b2", "a2lens", 81);
- WriteUtf8Helper(context, "c2", "a2lens", 81);
}
return *is1 == *is2;
}
-static void SameSymbolHelper(v8::Isolate* isolate, const char* a,
- const char* b) {
- Handle<String> symbol1 =
- v8::String::NewFromUtf8(isolate, a, v8::String::kInternalizedString);
- Handle<String> symbol2 =
- v8::String::NewFromUtf8(isolate, b, v8::String::kInternalizedString);
- CHECK(SameSymbol(symbol1, symbol2));
-}
-
THREADED_TEST(Utf16Symbol) {
LocalContext context;
context->GetIsolate(), "abc", v8::String::kInternalizedString);
CHECK(SameSymbol(symbol1, symbol2));
- SameSymbolHelper(context->GetIsolate(),
- "\360\220\220\205", // 4 byte encoding.
- "\355\240\201\355\260\205"); // 2 3-byte surrogates.
- SameSymbolHelper(context->GetIsolate(),
- "\355\240\201\355\260\206", // 2 3-byte surrogates.
- "\360\220\220\206"); // 4 byte encoding.
- SameSymbolHelper(context->GetIsolate(),
- "x\360\220\220\205", // 4 byte encoding.
- "x\355\240\201\355\260\205"); // 2 3-byte surrogates.
- SameSymbolHelper(context->GetIsolate(),
- "x\355\240\201\355\260\206", // 2 3-byte surrogates.
- "x\360\220\220\206"); // 4 byte encoding.
CompileRun(
"var sym0 = 'benedictus';"
"var sym0b = 'S\303\270ren';"
}
+THREADED_TEST(Utf16MissingTrailing) {
+ LocalContext context;
+ v8::HandleScope scope(context->GetIsolate());
+
+ // Make sure it will go past the buffer, so it will call `WriteUtf16Slow`
+ int size = 1024 * 64;
+ uint8_t* buffer = new uint8_t[size];
+ for (int i = 0; i < size; i += 4) {
+ buffer[i] = 0xf0;
+ buffer[i + 1] = 0x9d;
+ buffer[i + 2] = 0x80;
+ buffer[i + 3] = 0x9e;
+ }
+
+ // Now invoke the decoder without last 3 bytes
+ v8::Local<v8::String> str =
+ v8::String::NewFromUtf8(
+ context->GetIsolate(), reinterpret_cast<char*>(buffer),
+ v8::NewStringType::kNormal, size - 3).ToLocalChecked();
+ USE(str);
+ delete[] buffer;
+}
+
+
+THREADED_TEST(Utf16Trailing3Byte) {
+ LocalContext context;
+ v8::HandleScope scope(context->GetIsolate());
+
+ // Make sure it will go past the buffer, so it will call `WriteUtf16Slow`
+ int size = 1024 * 63;
+ uint8_t* buffer = new uint8_t[size];
+ for (int i = 0; i < size; i += 3) {
+ buffer[i] = 0xe2;
+ buffer[i + 1] = 0x80;
+ buffer[i + 2] = 0xa6;
+ }
+
+ // Now invoke the decoder without last 3 bytes
+ v8::Local<v8::String> str =
+ v8::String::NewFromUtf8(
+ context->GetIsolate(), reinterpret_cast<char*>(buffer),
+ v8::NewStringType::kNormal, size).ToLocalChecked();
+
+ v8::String::Value value(str);
+ CHECK_EQ(value.length(), size / 3);
+ CHECK_EQ((*value)[value.length() - 1], 0x2026);
+
+ delete[] buffer;
+}
+
+
THREADED_TEST(ToArrayIndex) {
LocalContext context;
v8::Isolate* isolate = context->GetIsolate();
str = v8_str("-42");
index = str->ToArrayIndex();
CHECK(index.IsEmpty());
- str = v8_str("4294967295");
+ str = v8_str("4294967294");
index = str->ToArrayIndex();
CHECK(!index.IsEmpty());
- CHECK_EQ(4294967295.0, index->Uint32Value());
+ CHECK_EQ(4294967294.0, index->Uint32Value());
v8::Handle<v8::Number> num = v8::Number::New(isolate, 1);
index = num->ToArrayIndex();
CHECK(!index.IsEmpty());
v8::Local<v8::Object> global = context->Global();
global->Set(v8_str("throwV8Exception"), fun->GetFunction());
- TryCatch try_catch;
+ TryCatch try_catch(context->GetIsolate());
CompileRun(
"function f1() {\n"
" throwV8Exception();\n"
}
+THREADED_TEST(ExceptionCreateMessageLength) {
+ LocalContext context;
+ v8::HandleScope scope(context->GetIsolate());
+
+ // Test that the message is not truncated.
+ TryCatch try_catch(context->GetIsolate());
+ CompileRun(
+ "var message = 'm';"
+ "while (message.length < 1000) message += message;"
+ "throw message;");
+ CHECK(try_catch.HasCaught());
+
+ CHECK_LT(1000, try_catch.Message()->Get()->Length());
+}
+
+
static void YGetter(Local<String> name,
const v8::PropertyCallbackInfo<v8::Value>& info) {
ApiTestFuzzer::Fuzz();
TEST(CompilationErrorUsingTryCatchHandler) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(env->GetIsolate());
v8_compile("This doesn't &*&@#$&*^ compile.");
CHECK(*try_catch.Exception());
CHECK(try_catch.HasCaught());
TEST(TryCatchFinallyUsingTryCatchHandler) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(env->GetIsolate());
CompileRun("try { throw ''; } catch (e) {}");
CHECK(!try_catch.HasCaught());
CompileRun("try { throw ''; } finally {}");
templ->Set(v8_str("CEvaluate"),
v8::FunctionTemplate::New(isolate, CEvaluate));
LocalContext context(0, templ);
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
CompileRun("try {"
" CEvaluate('throw 1;');"
"} finally {"
Context::Scope scope_env2(env2);
// Call cross_domain_call, it should throw an exception
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(env1->GetIsolate());
Function::Cast(*spy2)->Call(env2->Global(), 0, NULL);
CHECK(try_catch.HasCaught());
}
static bool SecurityTestCallbackWithGC(Local<v8::Object> global,
Local<v8::Value> name,
v8::AccessType type, Local<Value> data) {
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
security_check_with_gc_called = true;
return true;
}
{
Local<Value> get_prop = global1->Get(v8_str("getProp"));
CHECK(get_prop->IsFunction());
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(env1->GetIsolate());
Local<Value> r = Function::Cast(*get_prop)->Call(global1, 0, NULL);
CHECK(!try_catch.HasCaught());
CHECK_EQ(1, r->Int32Value());
}
Local<Object> env2_global = env2->Global();
- env2_global->TurnOnAccessCheck();
env2->DetachGlobal();
Local<Value> result;
TEST(SuperAccessControl) {
i::FLAG_allow_natives_syntax = true;
- i::FLAG_harmony_classes = true;
- i::FLAG_harmony_object_literals = true;
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope handle_scope(isolate);
v8::Handle<v8::ObjectTemplate> obj_template =
env->Global()->Set(v8_str("prohibited"), obj_template->NewInstance());
{
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
CompileRun(
"var f = { m() { return super.hasOwnProperty; } }.m;"
"var m = %ToMethod(f, prohibited);"
}
{
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
CompileRun(
"var f = {m() { return super[42]; } }.m;"
"var m = %ToMethod(f, prohibited);"
}
{
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
CompileRun(
"var f = {m() { super.hasOwnProperty = function () {}; } }.m;"
"var m = %ToMethod(f, prohibited);"
}
{
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
CompileRun(
"Object.defineProperty(Object.prototype, 'x', { set : function(){}});"
"var f = {"
TEST(Regress470113) {
- i::FLAG_harmony_classes = true;
- i::FLAG_harmony_object_literals = true;
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope handle_scope(isolate);
v8::Handle<v8::ObjectTemplate> obj_template =
env->Global()->Set(v8_str("prohibited"), obj_template->NewInstance());
{
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
CompileRun(
"'use strict';\n"
"class C extends Object {\n"
CHECK(o0->SetPrototype(o1));
// If setting the prototype leads to the cycle, SetPrototype should
// return false and keep VM in sane state.
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
CHECK(!o1->SetPrototype(o0));
CHECK(!try_catch.HasCaught());
DCHECK(!CcTest::i_isolate()->has_pending_exception());
context->Global()->Set(v8_str("fun"), fun);
CHECK(!CompileRun("'prototype' in fun")->BooleanValue());
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
CompileRun("new fun()");
CHECK(try_catch.HasCaught());
"x.__defineGetter__('get', Throw);");
Local<v8::Object> x =
Local<v8::Object>::Cast(context->Global()->Get(v8_str("x")));
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
x->Get(v8_str("get"));
x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
instance_template->SetCallAsFunctionHandler(ConstructorCallback);
Local<Object> instance = instance_template->NewInstance();
context->Global()->Set(v8_str("obj"), instance);
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
Local<Value> value;
CHECK(!try_catch.HasCaught());
Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
Local<Object> instance = instance_template->NewInstance();
context->Global()->Set(v8_str("obj2"), instance);
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
Local<Value> value;
CHECK(!try_catch.HasCaught());
instance_template->SetCallAsFunctionHandler(ThrowValue);
Local<Object> instance = instance_template->NewInstance();
context->Global()->Set(v8_str("obj3"), instance);
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
Local<Value> value;
CHECK(!try_catch.HasCaught());
Local<Function> function = function_template->GetFunction();
Local<Object> instance1 = function;
context->Global()->Set(v8_str("obj4"), instance1);
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
Local<Value> value;
CHECK(!try_catch.HasCaught());
CHECK_EQ(0, current->Global()->Get(v8_str("result2"))->Int32Value());
CHECK_EQ(1, current->Global()->Get(v8_str("result3"))->Int32Value());
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(current->GetIsolate());
script = v8_compile(
"function f(x) { "
" var bar = 2;"
// Check that global variables in current context are not visible in other
// context.
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(CcTest::isolate());
script = v8_compile("var bar = 42; other.eval('bar');");
Local<Value> result = script->Run();
CHECK(try_catch.HasCaught());
v8::Handle<v8::Value> x_value = CompileRun("fun('x')");
CHECK_EQ(42, x_value->Int32Value());
context0->DetachGlobal();
- v8::TryCatch catcher;
+ v8::TryCatch catcher(isolate);
x_value = CompileRun("fun('x')");
CHECK_EQ(42, x_value->Int32Value());
context1->Exit();
instance_template->SetCallAsFunctionHandler(call_as_function);
Local<v8::Object> instance = t->GetFunction()->NewInstance();
context->Global()->Set(v8_str("obj"), instance);
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
Local<Value> value;
CHECK(!try_catch.HasCaught());
USE(instance_template);
Local<v8::Object> instance = t->GetFunction()->NewInstance();
context->Global()->Set(v8_str("obj2"), instance);
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
Local<Value> value;
CHECK(!try_catch.HasCaught());
instance_template->SetCallAsFunctionHandler(ThrowValue);
Local<v8::Object> instance = t->GetFunction()->NewInstance();
context->Global()->Set(v8_str("obj3"), instance);
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
Local<Value> value;
CHECK(!try_catch.HasCaught());
Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
instance_template->SetCallAsFunctionHandler(call_as_function);
Local<Object> instance = instance_template->NewInstance();
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
CHECK(instance->IsCallable());
CHECK(!try_catch.HasCaught());
{
Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
Local<Object> instance = instance_template->NewInstance();
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
CHECK(!instance->IsCallable());
CHECK(!try_catch.HasCaught());
FunctionTemplate::New(isolate, call_as_function);
Local<Function> function = function_template->GetFunction();
Local<Object> instance = function;
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
CHECK(instance->IsCallable());
CHECK(!try_catch.HasCaught());
Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate);
Local<Function> function = function_template->GetFunction();
Local<Object> instance = function;
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
CHECK(instance->IsCallable());
CHECK(!try_catch.HasCaught());
reinterpret_cast<int*>(v8::External::Cast(*info.Data())->Value());
++(*call_count);
if ((*call_count) % 20 == 0) {
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
}
}
void DirectApiCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
static int count = 0;
if (count++ % 3 == 0) {
- CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+ CcTest::heap()->CollectAllGarbage();
// This should move the stub
GenerateSomeGarbage(); // This should ensure the old stub memory is flushed
}
static Handle<Value> DoDirectGetter() {
if (++p_getter_count_3 % 3 == 0) {
- CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+ CcTest::heap()->CollectAllGarbage();
GenerateSomeGarbage();
}
return v8_str("Direct Getter Result");
v8::Handle<v8::Function> fun = fun_templ->GetFunction();
GenerateSomeGarbage();
context->Global()->Set(v8_str("o"), fun->NewInstance());
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
CompileRun(
"o.foo = 17;"
"var receiver = {};"
v8::Handle<v8::Function> fun = fun_templ->GetFunction();
GenerateSomeGarbage();
context->Global()->Set(v8_str("o"), fun->NewInstance());
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
CompileRun(
"o.foo = 17;"
"var receiver = {};"
v8::Handle<v8::Function> fun = fun_templ->GetFunction();
GenerateSomeGarbage();
context->Global()->Set(v8_str("o"), fun->NewInstance());
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
CompileRun(
"o.foo = 17;"
"var receiver = {};"
v8::Handle<v8::Function> fun = fun_templ->GetFunction();
GenerateSomeGarbage();
context->Global()->Set(v8_str("o"), fun->NewInstance());
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
CompileRun(
"o.foo = 17;"
"var receiver = {};"
"o\n").As<Object>();
CHECK(!with_js_getter.IsEmpty());
- TryCatch try_catch;
+ TryCatch try_catch(context->GetIsolate());
Local<Value> result = instance->GetRealNamedProperty(v8_str("f"));
CHECK(try_catch.HasCaught());
static void ThrowingCallbackWithTryCatch(
const v8::FunctionCallbackInfo<v8::Value>& args) {
- TryCatch try_catch;
+ TryCatch try_catch(args.GetIsolate());
// Verboseness is important: it triggers message delivery which can call into
// external code.
try_catch.SetVerbose(true);
static void WithTryCatch(Handle<Message> message, Handle<Value> data) {
- TryCatch try_catch;
+ TryCatch try_catch(CcTest::isolate());
}
Local<Value> obj = v8::Object::New(isolate);
obj.As<v8::Object>()->SetAccessor(toStringTag, ThrowingSymbolAccessorGetter);
{
- TryCatch try_catch;
+ TryCatch try_catch(isolate);
value = obj.As<v8::Object>()->ObjectProtoToString();
CHECK(value.IsEmpty());
CHECK(try_catch.HasCaught());
obj.As<v8::Object>()->SetAccessor(
toStringTag, SymbolAccessorGetterReturnsDefault, 0, v8_str("Test"));
{
- TryCatch try_catch;
+ TryCatch try_catch(isolate);
value = obj.As<v8::Object>()->ObjectProtoToString();
CHECK(value->IsString() && value->Equals(v8_str("[object Test]")));
CHECK(!try_catch.HasCaught());
// JS @@toStringTag value
obj = CompileRun("obj = {}; obj[Symbol.toStringTag] = 'Test'; obj");
{
- TryCatch try_catch;
+ TryCatch try_catch(isolate);
value = obj.As<v8::Object>()->ObjectProtoToString();
CHECK(value->IsString() && value->Equals(v8_str("[object Test]")));
CHECK(!try_catch.HasCaught());
" get: function() { throw 'Test'; }"
"}); obj");
{
- TryCatch try_catch;
+ TryCatch try_catch(isolate);
value = obj.As<v8::Object>()->ObjectProtoToString();
CHECK(value.IsEmpty());
CHECK(try_catch.HasCaught());
" get: function() { return 'Test'; }"
"}); obj");
{
- TryCatch try_catch;
+ TryCatch try_catch(isolate);
value = obj.As<v8::Object>()->ObjectProtoToString();
CHECK(value->IsString() && value->Equals(v8_str("[object Test]")));
CHECK(!try_catch.HasCaught());
v8::Isolate* isolate = CcTest::isolate();
LocalContext context;
v8::HandleScope scope(isolate);
- v8_compile("function Parent() {};"
- "function Child() {};"
- "Child.prototype = new Parent();"
- "var outer = { inner: function() { } };"
- "var p = new Parent();"
- "var c = new Child();"
- "var x = new outer.inner();")->Run();
+ v8_compile(
+ "function Parent() {};"
+ "function Child() {};"
+ "Child.prototype = new Parent();"
+ "var outer = { inner: function() { } };"
+ "var p = new Parent();"
+ "var c = new Child();"
+ "var x = new outer.inner();"
+ "var proto = Child.prototype;")->Run();
Local<v8::Value> p = context->Global()->Get(v8_str("p"));
CHECK(p->IsObject() &&
CHECK(x->IsObject() &&
x->ToObject(isolate)->GetConstructorName()->Equals(
v8_str("outer.inner")));
+
+ Local<v8::Value> child_prototype = context->Global()->Get(v8_str("proto"));
+ CHECK(child_prototype->IsObject() &&
+ child_prototype->ToObject(isolate)->GetConstructorName()->Equals(
+ v8_str("Parent")));
}
v8::Locker nested_locker(isolate);
v8::HandleScope scope(isolate);
v8::Handle<Value> exception;
- { v8::TryCatch try_catch;
+ {
+ v8::TryCatch try_catch(isolate);
v8::Handle<Value> value = CompileRun(code);
CHECK(value.IsEmpty());
CHECK(try_catch.HasCaught());
// the first garbage collection but some of the maps have already
// been marked at that point. Therefore some of the maps are not
// collected until the second garbage collection.
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
CcTest::heap()->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
int count = GetGlobalObjectsCount();
#ifdef DEBUG
static void WeakApiCallback(
- const v8::WeakCallbackData<v8::Object, Persistent<v8::Object> >& data) {
- Local<Value> value = data.GetValue()->Get(v8_str("key"));
- CHECK_EQ(231, static_cast<int32_t>(Local<v8::Integer>::Cast(value)->Value()));
+ const v8::WeakCallbackInfo<Persistent<v8::Object>>& data) {
data.GetParameter()->Reset();
delete data.GetParameter();
}
obj->Set(v8_str("key"), v8::Integer::New(isolate, 231));
v8::Persistent<v8::Object>* handle =
new v8::Persistent<v8::Object>(isolate, obj);
- handle->SetWeak<v8::Object, v8::Persistent<v8::Object> >(handle,
- WeakApiCallback);
+ handle->SetWeak<v8::Persistent<v8::Object>>(
+ handle, WeakApiCallback, v8::WeakCallbackType::kParameter);
}
- reinterpret_cast<i::Isolate*>(isolate)->heap()->
- CollectAllGarbage(i::Heap::kNoGCFlags);
+ reinterpret_cast<i::Isolate*>(isolate)->heap()->CollectAllGarbage(
+ i::Heap::kAbortIncrementalMarkingMask);
// Verify disposed.
CHECK_EQ(initial_handles, globals->global_handles_count());
}
v8::Persistent<v8::Object> some_object;
v8::Persistent<v8::Object> bad_handle;
-void NewPersistentHandleCallback(
- const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
+
+void NewPersistentHandleCallback2(
+ const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
v8::HandleScope scope(data.GetIsolate());
bad_handle.Reset(data.GetIsolate(), some_object);
+}
+
+
+void NewPersistentHandleCallback1(
+ const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
data.GetParameter()->Reset();
+ data.SetSecondPassCallback(NewPersistentHandleCallback2);
}
// global handle nodes are processed by PostGarbageCollectionProcessing
// in reverse allocation order, so if second allocated handle is deleted,
// weak callback of the first handle would be able to 'reallocate' it.
- handle1.SetWeak(&handle1, NewPersistentHandleCallback);
+ handle1.SetWeak(&handle1, NewPersistentHandleCallback1,
+ v8::WeakCallbackType::kParameter);
handle2.Reset();
- CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+ CcTest::heap()->CollectAllGarbage();
}
v8::Persistent<v8::Object> to_be_disposed;
-void DisposeAndForceGcCallback(
- const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
+
+void DisposeAndForceGcCallback2(
+ const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
to_be_disposed.Reset();
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
+}
+
+
+void DisposeAndForceGcCallback1(
+ const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
data.GetParameter()->Reset();
+ data.SetSecondPassCallback(DisposeAndForceGcCallback2);
}
handle1.Reset(isolate, v8::Object::New(isolate));
handle2.Reset(isolate, v8::Object::New(isolate));
}
- handle1.SetWeak(&handle1, DisposeAndForceGcCallback);
+ handle1.SetWeak(&handle1, DisposeAndForceGcCallback1,
+ v8::WeakCallbackType::kParameter);
to_be_disposed.Reset(isolate, handle2);
- CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+ CcTest::heap()->CollectAllGarbage();
}
void DisposingCallback(
- const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
+ const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
data.GetParameter()->Reset();
}
-void HandleCreatingCallback(
- const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
+void HandleCreatingCallback2(
+ const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
v8::HandleScope scope(data.GetIsolate());
- v8::Persistent<v8::Object>(data.GetIsolate(),
- v8::Object::New(data.GetIsolate()));
+ v8::Global<v8::Object>(data.GetIsolate(), v8::Object::New(data.GetIsolate()));
+}
+
+
+void HandleCreatingCallback1(
+ const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
data.GetParameter()->Reset();
+ data.SetSecondPassCallback(HandleCreatingCallback2);
}
handle2.Reset(isolate, v8::Object::New(isolate));
handle1.Reset(isolate, v8::Object::New(isolate));
}
- handle2.SetWeak(&handle2, DisposingCallback);
- handle3.SetWeak(&handle3, HandleCreatingCallback);
- CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+ handle2.SetWeak(&handle2, DisposingCallback,
+ v8::WeakCallbackType::kParameter);
+ handle3.SetWeak(&handle3, HandleCreatingCallback1,
+ v8::WeakCallbackType::kParameter);
+ CcTest::heap()->CollectAllGarbage();
}
v8::Isolate::CreateParams create_params;
create_params.entry_hook = EntryHook;
create_params.code_event_handler = JitEvent;
+ create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
v8::Isolate* isolate = v8::Isolate::New(create_params);
{
Reset();
// Make sure a second isolate is unaffected by the previous entry hook.
- isolate = v8::Isolate::New();
+ create_params = v8::Isolate::CreateParams();
+ create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
+ isolate = v8::Isolate::New(create_params);
{
v8::Isolate::Scope scope(isolate);
CHECK(event->code_start != NULL);
CHECK_NE(0, static_cast<int>(event->code_len));
CHECK(event->name.str != NULL);
- i::HashMap::Entry* entry =
- code_map->Lookup(event->code_start,
- i::ComputePointerHash(event->code_start),
- true);
+ i::HashMap::Entry* entry = code_map->LookupOrInsert(
+ event->code_start, i::ComputePointerHash(event->code_start));
entry->value = reinterpret_cast<void*>(event->code_len);
if (FunctionNameIs("bar", event)) {
// Compiler::RecordFunctionCompilation) and the line endings
// calculations can cause a GC, which can move the newly created code
// before its existence can be logged.
- i::HashMap::Entry* entry =
- code_map->Lookup(event->code_start, hash, false);
+ i::HashMap::Entry* entry = code_map->Lookup(event->code_start, hash);
if (entry != NULL) {
++move_events;
CHECK_EQ(reinterpret_cast<void*>(event->code_len), entry->value);
code_map->Remove(event->code_start, hash);
- entry = code_map->Lookup(event->new_code_start,
- i::ComputePointerHash(event->new_code_start),
- true);
- CHECK(entry != NULL);
+ entry = code_map->LookupOrInsert(
+ event->new_code_start,
+ i::ComputePointerHash(event->new_code_start));
entry->value = reinterpret_cast<void*>(event->code_len);
}
}
DummyJitCodeLineInfo* line_info = new DummyJitCodeLineInfo();
v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
temp_event->user_data = line_info;
- i::HashMap::Entry* entry =
- jitcode_line_info->Lookup(line_info,
- i::ComputePointerHash(line_info),
- true);
+ i::HashMap::Entry* entry = jitcode_line_info->LookupOrInsert(
+ line_info, i::ComputePointerHash(line_info));
entry->value = reinterpret_cast<void*>(line_info);
}
break;
CHECK(event->user_data != NULL);
uint32_t hash = i::ComputePointerHash(event->user_data);
i::HashMap::Entry* entry =
- jitcode_line_info->Lookup(event->user_data, hash, false);
+ jitcode_line_info->Lookup(event->user_data, hash);
CHECK(entry != NULL);
delete reinterpret_cast<DummyJitCodeLineInfo*>(event->user_data);
}
CHECK(event->user_data != NULL);
uint32_t hash = i::ComputePointerHash(event->user_data);
i::HashMap::Entry* entry =
- jitcode_line_info->Lookup(event->user_data, hash, false);
+ jitcode_line_info->Lookup(event->user_data, hash);
CHECK(entry != NULL);
}
break;
// Run this test in a new isolate to make sure we don't
// have remnants of state from other code.
- v8::Isolate* isolate = v8::Isolate::New();
+ v8::Isolate::CreateParams create_params;
+ create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
+ v8::Isolate* isolate = v8::Isolate::New(create_params);
isolate->Enter();
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
i::Heap* heap = i_isolate->heap();
isolate->Dispose();
// Do this in a new isolate.
- isolate = v8::Isolate::New();
+ isolate = v8::Isolate::New(create_params);
isolate->Enter();
// Verify that we get callbacks for existing code objects when we
TEST(CatchStackOverflow) {
LocalContext context;
v8::HandleScope scope(context->GetIsolate());
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(context->GetIsolate());
v8::Handle<v8::Value> result = CompileRun(
"function f() {"
" return f();"
const char* resource_name,
int line_offset) {
v8::HandleScope scope(CcTest::isolate());
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(CcTest::isolate());
v8::Handle<v8::Value> result = script->Run();
CHECK(result.IsEmpty());
CHECK(try_catch.HasCaught());
}
+THREADED_TEST(TryCatchSourceInfoForEOSError) {
+ LocalContext context;
+ v8::HandleScope scope(context->GetIsolate());
+ v8::TryCatch try_catch(context->GetIsolate());
+ v8::Script::Compile(v8_str("!\n"));
+ CHECK(try_catch.HasCaught());
+ v8::Handle<v8::Message> message = try_catch.Message();
+ CHECK_EQ(1, message->GetLineNumber());
+ CHECK_EQ(0, message->GetStartColumn());
+}
+
+
THREADED_TEST(CompilationCache) {
LocalContext context;
v8::HandleScope scope(context->GetIsolate());
}
-THREADED_TEST(TurnOnAccessCheck) {
- v8::Isolate* isolate = CcTest::isolate();
- v8::HandleScope handle_scope(isolate);
-
- // Create an environment with access check to the global object disabled by
- // default.
- v8::Handle<v8::ObjectTemplate> global_template =
- v8::ObjectTemplate::New(isolate);
- global_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL,
- v8::Handle<v8::Value>(), false);
- v8::Local<Context> context = Context::New(isolate, NULL, global_template);
- Context::Scope context_scope(context);
-
- // Set up a property and a number of functions.
- context->Global()->Set(v8_str("a"), v8_num(1));
- CompileRun("function f1() {return a;}"
- "function f2() {return a;}"
- "function g1() {return h();}"
- "function g2() {return h();}"
- "function h() {return 1;}");
- Local<Function> f1 =
- Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
- Local<Function> f2 =
- Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
- Local<Function> g1 =
- Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
- Local<Function> g2 =
- Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
- Local<Function> h =
- Local<Function>::Cast(context->Global()->Get(v8_str("h")));
-
- // Get the global object.
- v8::Handle<v8::Object> global = context->Global();
-
- // Call f1 one time and f2 a number of times. This will ensure that f1 still
- // uses the runtime system to retreive property a whereas f2 uses global load
- // inline cache.
- CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
- for (int i = 0; i < 4; i++) {
- CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
- }
-
- // Same for g1 and g2.
- CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
- for (int i = 0; i < 4; i++) {
- CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
- }
-
- // Detach the global and turn on access check.
- Local<Object> hidden_global = Local<Object>::Cast(
- context->Global()->GetPrototype());
- context->DetachGlobal();
- hidden_global->TurnOnAccessCheck();
-
- // Failing access check results in exception.
- CHECK(f1->Call(global, 0, NULL).IsEmpty());
- CHECK(f2->Call(global, 0, NULL).IsEmpty());
- CHECK(g1->Call(global, 0, NULL).IsEmpty());
- CHECK(g2->Call(global, 0, NULL).IsEmpty());
-
- // No failing access check when just returning a constant.
- CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
-}
-
-
// Tests that ScriptData can be serialized and deserialized.
TEST(PreCompileSerialization) {
v8::V8::Initialize();
v8::base::NoBarrier_Load(®exp_interruption_data.loop_count) < 7;
v8::base::NoBarrier_AtomicIncrement(
®exp_interruption_data.loop_count, 1)) {
- v8::base::OS::Sleep(50); // Wait a bit before requesting GC.
+ // Wait a bit before requesting GC.
+ v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
reinterpret_cast<i::Isolate*>(isolate_)->stack_guard()->RequestGC();
}
- v8::base::OS::Sleep(50); // Wait a bit before terminating.
+ // Wait a bit before terminating.
+ v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
v8::V8::TerminateExecution(isolate_);
}
regexp_interruption_data.string_resource = new UC16VectorResource(
i::Vector<const i::uc16>(uc16_content, i::StrLength(one_byte_content)));
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(CcTest::isolate());
timeout_thread.Start();
CompileRun("/((a*)*)*b/.exec(a)");
CHECK_EQ(3, global->Get(access_property)->Int32Value());
CHECK_EQ(1, force_set_set_count);
CHECK_EQ(2, force_set_get_count);
- // Forcing the property to be set should override the accessor without
- // calling it
+ // ForceSet doesn't call the accessors for now.
+ // TODO(verwaest): Update once blink doesn't rely on ForceSet to delete api
+ // accessors.
global->ForceSet(access_property, v8::Int32::New(isolate, 8));
CHECK_EQ(8, global->Get(access_property)->Int32Value());
CHECK_EQ(1, force_set_set_count);
TEST(ForceSetWithInterceptor) {
- force_set_get_count = 0;
- force_set_set_count = 0;
- pass_on_get = false;
-
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope scope(isolate);
v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
ForceSetInterceptGetter, ForceSetInterceptSetter));
+ pass_on_get = true;
LocalContext context(NULL, templ);
v8::Handle<v8::Object> global = context->Global();
+ force_set_get_count = 0;
+ force_set_set_count = 0;
+ pass_on_get = false;
+
v8::Handle<v8::String> some_property =
v8::String::NewFromUtf8(isolate, "a");
CHECK_EQ(0, force_set_set_count);
}
-static v8::Local<Context> calling_context0;
-static v8::Local<Context> calling_context1;
-static v8::Local<Context> calling_context2;
+TEST(CreateDataProperty) {
+ LocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope handle_scope(isolate);
+ CompileRun(
+ "var a = {};"
+ "var b = [];"
+ "Object.defineProperty(a, 'foo', {value: 23});"
+ "Object.defineProperty(a, 'bar', {value: 23, configurable: true});");
-// Check that the call to the callback is initiated in
-// calling_context2, the directly calling context is calling_context1
-// and the callback itself is in calling_context0.
-static void GetCallingContextCallback(
- const v8::FunctionCallbackInfo<v8::Value>& args) {
+ v8::Local<v8::Object> obj =
+ v8::Local<v8::Object>::Cast(env->Global()->Get(v8_str("a")));
+ v8::Local<v8::Array> arr =
+ v8::Local<v8::Array>::Cast(env->Global()->Get(v8_str("b")));
+ {
+ // Can't change a non-configurable properties.
+ v8::TryCatch try_catch(isolate);
+ CHECK(!obj->CreateDataProperty(env.local(), v8_str("foo"),
+ v8::Integer::New(isolate, 42)).FromJust());
+ CHECK(!try_catch.HasCaught());
+ CHECK(obj->CreateDataProperty(env.local(), v8_str("bar"),
+ v8::Integer::New(isolate, 42)).FromJust());
+ CHECK(!try_catch.HasCaught());
+ v8::Local<v8::Value> val =
+ obj->Get(env.local(), v8_str("bar")).ToLocalChecked();
+ CHECK(val->IsNumber());
+ CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
+ }
+
+ {
+ // Set a regular property.
+ v8::TryCatch try_catch(isolate);
+ CHECK(obj->CreateDataProperty(env.local(), v8_str("blub"),
+ v8::Integer::New(isolate, 42)).FromJust());
+ CHECK(!try_catch.HasCaught());
+ v8::Local<v8::Value> val =
+ obj->Get(env.local(), v8_str("blub")).ToLocalChecked();
+ CHECK(val->IsNumber());
+ CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
+ }
+
+ {
+ // Set an indexed property.
+ v8::TryCatch try_catch(isolate);
+ CHECK(obj->CreateDataProperty(env.local(), v8_str("1"),
+ v8::Integer::New(isolate, 42)).FromJust());
+ CHECK(!try_catch.HasCaught());
+ v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
+ CHECK(val->IsNumber());
+ CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
+ }
+
+ {
+ // Special cases for arrays.
+ v8::TryCatch try_catch(isolate);
+ CHECK(!arr->CreateDataProperty(env.local(), v8_str("length"),
+ v8::Integer::New(isolate, 1)).FromJust());
+ CHECK(!try_catch.HasCaught());
+ }
+ {
+ // Special cases for arrays: index exceeds the array's length
+ v8::TryCatch try_catch(isolate);
+ CHECK(arr->CreateDataProperty(env.local(), 1, v8::Integer::New(isolate, 23))
+ .FromJust());
+ CHECK(!try_catch.HasCaught());
+ CHECK_EQ(2U, arr->Length());
+ v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked();
+ CHECK(val->IsNumber());
+ CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
+
+ // Set an existing entry.
+ CHECK(arr->CreateDataProperty(env.local(), 0, v8::Integer::New(isolate, 42))
+ .FromJust());
+ CHECK(!try_catch.HasCaught());
+ val = arr->Get(env.local(), 0).ToLocalChecked();
+ CHECK(val->IsNumber());
+ CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
+ }
+
+ CompileRun("Object.freeze(a);");
+ {
+ // Can't change non-extensible objects.
+ v8::TryCatch try_catch(isolate);
+ CHECK(!obj->CreateDataProperty(env.local(), v8_str("baz"),
+ v8::Integer::New(isolate, 42)).FromJust());
+ CHECK(!try_catch.HasCaught());
+ }
+
+ v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
+ templ->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
+ v8::Local<v8::Object> access_checked =
+ templ->NewInstance(env.local()).ToLocalChecked();
+ {
+ v8::TryCatch try_catch(isolate);
+ CHECK(access_checked->CreateDataProperty(env.local(), v8_str("foo"),
+ v8::Integer::New(isolate, 42))
+ .IsNothing());
+ CHECK(try_catch.HasCaught());
+ }
+}
+
+
+TEST(DefineOwnProperty) {
+ LocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope handle_scope(isolate);
+
+ CompileRun(
+ "var a = {};"
+ "var b = [];"
+ "Object.defineProperty(a, 'foo', {value: 23});"
+ "Object.defineProperty(a, 'bar', {value: 23, configurable: true});");
+
+ v8::Local<v8::Object> obj =
+ v8::Local<v8::Object>::Cast(env->Global()->Get(v8_str("a")));
+ v8::Local<v8::Array> arr =
+ v8::Local<v8::Array>::Cast(env->Global()->Get(v8_str("b")));
+ {
+ // Can't change a non-configurable properties.
+ v8::TryCatch try_catch(isolate);
+ CHECK(!obj->DefineOwnProperty(env.local(), v8_str("foo"),
+ v8::Integer::New(isolate, 42)).FromJust());
+ CHECK(!try_catch.HasCaught());
+ CHECK(obj->DefineOwnProperty(env.local(), v8_str("bar"),
+ v8::Integer::New(isolate, 42)).FromJust());
+ CHECK(!try_catch.HasCaught());
+ v8::Local<v8::Value> val =
+ obj->Get(env.local(), v8_str("bar")).ToLocalChecked();
+ CHECK(val->IsNumber());
+ CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
+ }
+
+ {
+ // Set a regular property.
+ v8::TryCatch try_catch(isolate);
+ CHECK(obj->DefineOwnProperty(env.local(), v8_str("blub"),
+ v8::Integer::New(isolate, 42)).FromJust());
+ CHECK(!try_catch.HasCaught());
+ v8::Local<v8::Value> val =
+ obj->Get(env.local(), v8_str("blub")).ToLocalChecked();
+ CHECK(val->IsNumber());
+ CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
+ }
+
+ {
+ // Set an indexed property.
+ v8::TryCatch try_catch(isolate);
+ CHECK(obj->DefineOwnProperty(env.local(), v8_str("1"),
+ v8::Integer::New(isolate, 42)).FromJust());
+ CHECK(!try_catch.HasCaught());
+ v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
+ CHECK(val->IsNumber());
+ CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
+ }
+
+ {
+ // Special cases for arrays.
+ v8::TryCatch try_catch(isolate);
+ CHECK(!arr->DefineOwnProperty(env.local(), v8_str("length"),
+ v8::Integer::New(isolate, 1)).FromJust());
+ CHECK(!try_catch.HasCaught());
+ }
+ {
+ // Special cases for arrays: index exceeds the array's length
+ v8::TryCatch try_catch(isolate);
+ CHECK(arr->DefineOwnProperty(env.local(), v8_str("1"),
+ v8::Integer::New(isolate, 23)).FromJust());
+ CHECK(!try_catch.HasCaught());
+ CHECK_EQ(2U, arr->Length());
+ v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked();
+ CHECK(val->IsNumber());
+ CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
+
+ // Set an existing entry.
+ CHECK(arr->DefineOwnProperty(env.local(), v8_str("0"),
+ v8::Integer::New(isolate, 42)).FromJust());
+ CHECK(!try_catch.HasCaught());
+ val = arr->Get(env.local(), 0).ToLocalChecked();
+ CHECK(val->IsNumber());
+ CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
+ }
+
+ {
+ // Set a non-writable property.
+ v8::TryCatch try_catch(isolate);
+ CHECK(obj->DefineOwnProperty(env.local(), v8_str("lala"),
+ v8::Integer::New(isolate, 42),
+ v8::ReadOnly).FromJust());
+ CHECK(!try_catch.HasCaught());
+ v8::Local<v8::Value> val =
+ obj->Get(env.local(), v8_str("lala")).ToLocalChecked();
+ CHECK(val->IsNumber());
+ CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
+ CHECK_EQ(v8::ReadOnly, obj->GetPropertyAttributes(
+ env.local(), v8_str("lala")).FromJust());
+ CHECK(!try_catch.HasCaught());
+ }
+
+ CompileRun("Object.freeze(a);");
+ {
+ // Can't change non-extensible objects.
+ v8::TryCatch try_catch(isolate);
+ CHECK(!obj->DefineOwnProperty(env.local(), v8_str("baz"),
+ v8::Integer::New(isolate, 42)).FromJust());
+ CHECK(!try_catch.HasCaught());
+ }
+
+ v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
+ templ->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
+ v8::Local<v8::Object> access_checked =
+ templ->NewInstance(env.local()).ToLocalChecked();
+ {
+ v8::TryCatch try_catch(isolate);
+ CHECK(access_checked->DefineOwnProperty(env.local(), v8_str("foo"),
+ v8::Integer::New(isolate, 42))
+ .IsNothing());
+ CHECK(try_catch.HasCaught());
+ }
+}
+
+
+static v8::Local<Context> calling_context0;
+static v8::Local<Context> calling_context1;
+static v8::Local<Context> calling_context2;
+
+
+// Check that the call to the callback is initiated in
+// calling_context2, the directly calling context is calling_context1
+// and the callback itself is in calling_context0.
+static void GetCallingContextCallback(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
ApiTestFuzzer::Fuzz();
CHECK(args.GetIsolate()->GetCurrentContext() == calling_context0);
CHECK(args.GetIsolate()->GetCallingContext() == calling_context1);
}
-THREADED_TEST(PixelArray) {
- LocalContext context;
- i::Isolate* isolate = CcTest::i_isolate();
- i::Factory* factory = isolate->factory();
- v8::HandleScope scope(context->GetIsolate());
- const int kElementCount = 260;
- uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
- i::Handle<i::ExternalUint8ClampedArray> pixels =
- i::Handle<i::ExternalUint8ClampedArray>::cast(
- factory->NewExternalArray(kElementCount,
- v8::kExternalUint8ClampedArray,
- pixel_data));
- // Force GC to trigger verification.
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
- for (int i = 0; i < kElementCount; i++) {
- pixels->set(i, i % 256);
- }
- // Force GC to trigger verification.
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
- for (int i = 0; i < kElementCount; i++) {
- CHECK_EQ(i % 256, pixels->get_scalar(i));
- CHECK_EQ(i % 256, pixel_data[i]);
- }
-
- v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
- i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
- // Set the elements to be the pixels.
- // jsobj->set_elements(*pixels);
- obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
- CheckElementValue(isolate, 1, jsobj, 1);
- obj->Set(v8_str("field"), v8::Int32::New(CcTest::isolate(), 1503));
- context->Global()->Set(v8_str("pixels"), obj);
- v8::Handle<v8::Value> result = CompileRun("pixels.field");
- CHECK_EQ(1503, result->Int32Value());
- result = CompileRun("pixels[1]");
- CHECK_EQ(1, result->Int32Value());
-
- result = CompileRun("var sum = 0;"
- "for (var i = 0; i < 8; i++) {"
- " sum += pixels[i] = pixels[i] = -i;"
- "}"
- "sum;");
- CHECK_EQ(-28, result->Int32Value());
-
- result = CompileRun("var sum = 0;"
- "for (var i = 0; i < 8; i++) {"
- " sum += pixels[i] = pixels[i] = 0;"
- "}"
- "sum;");
- CHECK_EQ(0, result->Int32Value());
-
- result = CompileRun("var sum = 0;"
- "for (var i = 0; i < 8; i++) {"
- " sum += pixels[i] = pixels[i] = 255;"
- "}"
- "sum;");
- CHECK_EQ(8 * 255, result->Int32Value());
-
- result = CompileRun("var sum = 0;"
- "for (var i = 0; i < 8; i++) {"
- " sum += pixels[i] = pixels[i] = 256 + i;"
- "}"
- "sum;");
- CHECK_EQ(2076, result->Int32Value());
-
- result = CompileRun("var sum = 0;"
- "for (var i = 0; i < 8; i++) {"
- " sum += pixels[i] = pixels[i] = i;"
- "}"
- "sum;");
- CHECK_EQ(28, result->Int32Value());
-
- result = CompileRun("var sum = 0;"
- "for (var i = 0; i < 8; i++) {"
- " sum += pixels[i];"
- "}"
- "sum;");
- CHECK_EQ(28, result->Int32Value());
-
- i::Handle<i::Smi> value(i::Smi::FromInt(2),
- reinterpret_cast<i::Isolate*>(context->GetIsolate()));
- i::Handle<i::Object> no_failure;
- no_failure = i::JSObject::SetElement(
- jsobj, 1, value, NONE, i::SLOPPY).ToHandleChecked();
- DCHECK(!no_failure.is_null());
- USE(no_failure);
- CheckElementValue(isolate, 2, jsobj, 1);
- *value.location() = i::Smi::FromInt(256);
- no_failure = i::JSObject::SetElement(
- jsobj, 1, value, NONE, i::SLOPPY).ToHandleChecked();
- DCHECK(!no_failure.is_null());
- USE(no_failure);
- CheckElementValue(isolate, 255, jsobj, 1);
- *value.location() = i::Smi::FromInt(-1);
- no_failure = i::JSObject::SetElement(
- jsobj, 1, value, NONE, i::SLOPPY).ToHandleChecked();
- DCHECK(!no_failure.is_null());
- USE(no_failure);
- CheckElementValue(isolate, 0, jsobj, 1);
-
- result = CompileRun("for (var i = 0; i < 8; i++) {"
- " pixels[i] = (i * 65) - 109;"
- "}"
- "pixels[1] + pixels[6];");
- CHECK_EQ(255, result->Int32Value());
- CheckElementValue(isolate, 0, jsobj, 0);
- CheckElementValue(isolate, 0, jsobj, 1);
- CheckElementValue(isolate, 21, jsobj, 2);
- CheckElementValue(isolate, 86, jsobj, 3);
- CheckElementValue(isolate, 151, jsobj, 4);
- CheckElementValue(isolate, 216, jsobj, 5);
- CheckElementValue(isolate, 255, jsobj, 6);
- CheckElementValue(isolate, 255, jsobj, 7);
- result = CompileRun("var sum = 0;"
- "for (var i = 0; i < 8; i++) {"
- " sum += pixels[i];"
- "}"
- "sum;");
- CHECK_EQ(984, result->Int32Value());
-
- result = CompileRun("for (var i = 0; i < 8; i++) {"
- " pixels[i] = (i * 1.1);"
- "}"
- "pixels[1] + pixels[6];");
- CHECK_EQ(8, result->Int32Value());
- CheckElementValue(isolate, 0, jsobj, 0);
- CheckElementValue(isolate, 1, jsobj, 1);
- CheckElementValue(isolate, 2, jsobj, 2);
- CheckElementValue(isolate, 3, jsobj, 3);
- CheckElementValue(isolate, 4, jsobj, 4);
- CheckElementValue(isolate, 6, jsobj, 5);
- CheckElementValue(isolate, 7, jsobj, 6);
- CheckElementValue(isolate, 8, jsobj, 7);
-
- result = CompileRun("for (var i = 0; i < 8; i++) {"
- " pixels[7] = undefined;"
- "}"
- "pixels[7];");
- CHECK_EQ(0, result->Int32Value());
- CheckElementValue(isolate, 0, jsobj, 7);
-
- result = CompileRun("for (var i = 0; i < 8; i++) {"
- " pixels[6] = '2.3';"
- "}"
- "pixels[6];");
- CHECK_EQ(2, result->Int32Value());
- CheckElementValue(isolate, 2, jsobj, 6);
-
- result = CompileRun("for (var i = 0; i < 8; i++) {"
- " pixels[5] = NaN;"
- "}"
- "pixels[5];");
- CHECK_EQ(0, result->Int32Value());
- CheckElementValue(isolate, 0, jsobj, 5);
-
- result = CompileRun("for (var i = 0; i < 8; i++) {"
- " pixels[8] = Infinity;"
- "}"
- "pixels[8];");
- CHECK_EQ(255, result->Int32Value());
- CheckElementValue(isolate, 255, jsobj, 8);
-
- result = CompileRun("for (var i = 0; i < 8; i++) {"
- " pixels[9] = -Infinity;"
- "}"
- "pixels[9];");
- CHECK_EQ(0, result->Int32Value());
- CheckElementValue(isolate, 0, jsobj, 9);
-
- result = CompileRun("pixels[3] = 33;"
- "delete pixels[3];"
- "pixels[3];");
- CHECK_EQ(33, result->Int32Value());
-
- result = CompileRun("pixels[0] = 10; pixels[1] = 11;"
- "pixels[2] = 12; pixels[3] = 13;"
- "pixels.__defineGetter__('2',"
- "function() { return 120; });"
- "pixels[2];");
- CHECK_EQ(12, result->Int32Value());
-
- result = CompileRun("var js_array = new Array(40);"
- "js_array[0] = 77;"
- "js_array;");
- CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
-
- result = CompileRun("pixels[1] = 23;"
- "pixels.__proto__ = [];"
- "js_array.__proto__ = pixels;"
- "js_array.concat(pixels);");
- CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
- CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
-
- result = CompileRun("pixels[1] = 23;");
- CHECK_EQ(23, result->Int32Value());
-
- // Test for index greater than 255. Regression test for:
- // http://code.google.com/p/chromium/issues/detail?id=26337.
- result = CompileRun("pixels[256] = 255;");
- CHECK_EQ(255, result->Int32Value());
- result = CompileRun("var i = 0;"
- "for (var j = 0; j < 8; j++) { i = pixels[256]; }"
- "i");
- CHECK_EQ(255, result->Int32Value());
-
- // Make sure that pixel array ICs recognize when a non-pixel array
- // is passed to it.
- result = CompileRun("function pa_load(p) {"
- " var sum = 0;"
- " for (var j = 0; j < 256; j++) { sum += p[j]; }"
- " return sum;"
- "}"
- "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
- "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
- "just_ints = new Object();"
- "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
- "for (var i = 0; i < 10; ++i) {"
- " result = pa_load(just_ints);"
- "}"
- "result");
- CHECK_EQ(32640, result->Int32Value());
-
- // Make sure that pixel array ICs recognize out-of-bound accesses.
- result = CompileRun("function pa_load(p, start) {"
- " var sum = 0;"
- " for (var j = start; j < 256; j++) { sum += p[j]; }"
- " return sum;"
- "}"
- "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
- "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
- "for (var i = 0; i < 10; ++i) {"
- " result = pa_load(pixels,-10);"
- "}"
- "result");
- CHECK_EQ(0, result->Int32Value());
-
- // Make sure that generic ICs properly handles a pixel array.
- result = CompileRun("function pa_load(p) {"
- " var sum = 0;"
- " for (var j = 0; j < 256; j++) { sum += p[j]; }"
- " return sum;"
- "}"
- "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
- "just_ints = new Object();"
- "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
- "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
- "for (var i = 0; i < 10; ++i) {"
- " result = pa_load(pixels);"
- "}"
- "result");
- CHECK_EQ(32640, result->Int32Value());
-
- // Make sure that generic load ICs recognize out-of-bound accesses in
- // pixel arrays.
- result = CompileRun("function pa_load(p, start) {"
- " var sum = 0;"
- " for (var j = start; j < 256; j++) { sum += p[j]; }"
- " return sum;"
- "}"
- "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
- "just_ints = new Object();"
- "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
- "for (var i = 0; i < 10; ++i) { pa_load(just_ints,0); }"
- "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
- "for (var i = 0; i < 10; ++i) {"
- " result = pa_load(pixels,-10);"
- "}"
- "result");
- CHECK_EQ(0, result->Int32Value());
-
- // Make sure that generic ICs properly handles other types than pixel
- // arrays (that the inlined fast pixel array test leaves the right information
- // in the right registers).
- result = CompileRun("function pa_load(p) {"
- " var sum = 0;"
- " for (var j = 0; j < 256; j++) { sum += p[j]; }"
- " return sum;"
- "}"
- "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
- "just_ints = new Object();"
- "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
- "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
- "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
- "sparse_array = new Object();"
- "for (var i = 0; i < 256; ++i) { sparse_array[i] = i; }"
- "sparse_array[1000000] = 3;"
- "for (var i = 0; i < 10; ++i) {"
- " result = pa_load(sparse_array);"
- "}"
- "result");
- CHECK_EQ(32640, result->Int32Value());
-
- // Make sure that pixel array store ICs clamp values correctly.
- result = CompileRun("function pa_store(p) {"
- " for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
- "}"
- "pa_store(pixels);"
- "var sum = 0;"
- "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
- "sum");
- CHECK_EQ(48896, result->Int32Value());
-
- // Make sure that pixel array stores correctly handle accesses outside
- // of the pixel array..
- result = CompileRun("function pa_store(p,start) {"
- " for (var j = 0; j < 256; j++) {"
- " p[j+start] = j * 2;"
- " }"
- "}"
- "pa_store(pixels,0);"
- "pa_store(pixels,-128);"
- "var sum = 0;"
- "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
- "sum");
- CHECK_EQ(65280, result->Int32Value());
-
- // Make sure that the generic store stub correctly handle accesses outside
- // of the pixel array..
- result = CompileRun("function pa_store(p,start) {"
- " for (var j = 0; j < 256; j++) {"
- " p[j+start] = j * 2;"
- " }"
- "}"
- "pa_store(pixels,0);"
- "just_ints = new Object();"
- "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
- "pa_store(just_ints, 0);"
- "pa_store(pixels,-128);"
- "var sum = 0;"
- "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
- "sum");
- CHECK_EQ(65280, result->Int32Value());
-
- // Make sure that the generic keyed store stub clamps pixel array values
- // correctly.
- result = CompileRun("function pa_store(p) {"
- " for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
- "}"
- "pa_store(pixels);"
- "just_ints = new Object();"
- "pa_store(just_ints);"
- "pa_store(pixels);"
- "var sum = 0;"
- "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
- "sum");
- CHECK_EQ(48896, result->Int32Value());
-
- // Make sure that pixel array loads are optimized by crankshaft.
- result = CompileRun("function pa_load(p) {"
- " var sum = 0;"
- " for (var i=0; i<256; ++i) {"
- " sum += p[i];"
- " }"
- " return sum; "
- "}"
- "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
- "for (var i = 0; i < 5000; ++i) {"
- " result = pa_load(pixels);"
- "}"
- "result");
- CHECK_EQ(32640, result->Int32Value());
-
- // Make sure that pixel array stores are optimized by crankshaft.
- result = CompileRun("function pa_init(p) {"
- "for (var i = 0; i < 256; ++i) { p[i] = i; }"
- "}"
- "function pa_load(p) {"
- " var sum = 0;"
- " for (var i=0; i<256; ++i) {"
- " sum += p[i];"
- " }"
- " return sum; "
- "}"
- "for (var i = 0; i < 5000; ++i) {"
- " pa_init(pixels);"
- "}"
- "result = pa_load(pixels);"
- "result");
- CHECK_EQ(32640, result->Int32Value());
-
- free(pixel_data);
-}
-
-
-THREADED_TEST(PixelArrayInfo) {
- LocalContext context;
- v8::HandleScope scope(context->GetIsolate());
- for (int size = 0; size < 100; size += 10) {
- uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(size));
- v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
- obj->SetIndexedPropertiesToPixelData(pixel_data, size);
- CHECK(obj->HasIndexedPropertiesInPixelData());
- CHECK_EQ(pixel_data, obj->GetIndexedPropertiesPixelData());
- CHECK_EQ(size, obj->GetIndexedPropertiesPixelDataLength());
- free(pixel_data);
- }
-}
-
-
-static void NotHandledIndexedPropertyGetter(
- uint32_t index,
- const v8::PropertyCallbackInfo<v8::Value>& info) {
- ApiTestFuzzer::Fuzz();
-}
-
-
-static void NotHandledIndexedPropertySetter(
- uint32_t index,
- Local<Value> value,
- const v8::PropertyCallbackInfo<v8::Value>& info) {
- ApiTestFuzzer::Fuzz();
-}
-
-
-THREADED_TEST(PixelArrayWithInterceptor) {
- LocalContext context;
- i::Factory* factory = CcTest::i_isolate()->factory();
- v8::Isolate* isolate = context->GetIsolate();
- v8::HandleScope scope(isolate);
- const int kElementCount = 260;
- uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
- i::Handle<i::ExternalUint8ClampedArray> pixels =
- i::Handle<i::ExternalUint8ClampedArray>::cast(
- factory->NewExternalArray(kElementCount,
- v8::kExternalUint8ClampedArray,
- pixel_data));
- for (int i = 0; i < kElementCount; i++) {
- pixels->set(i, i % 256);
- }
- v8::Handle<v8::ObjectTemplate> templ =
- v8::ObjectTemplate::New(context->GetIsolate());
- templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
- NotHandledIndexedPropertyGetter, NotHandledIndexedPropertySetter));
- v8::Handle<v8::Object> obj = templ->NewInstance();
- obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
- context->Global()->Set(v8_str("pixels"), obj);
- v8::Handle<v8::Value> result = CompileRun("pixels[1]");
- CHECK_EQ(1, result->Int32Value());
- result = CompileRun("var sum = 0;"
- "for (var i = 0; i < 8; i++) {"
- " sum += pixels[i] = pixels[i] = -i;"
- "}"
- "sum;");
- CHECK_EQ(-28, result->Int32Value());
- result = CompileRun("pixels.hasOwnProperty('1')");
- CHECK(result->BooleanValue());
- free(pixel_data);
-}
-
-
-static int ExternalArrayElementSize(v8::ExternalArrayType array_type) {
- switch (array_type) {
- case v8::kExternalInt8Array:
- case v8::kExternalUint8Array:
- case v8::kExternalUint8ClampedArray:
- return 1;
- break;
- case v8::kExternalInt16Array:
- case v8::kExternalUint16Array:
- return 2;
- break;
- case v8::kExternalInt32Array:
- case v8::kExternalUint32Array:
- case v8::kExternalFloat32Array:
- return 4;
- break;
- case v8::kExternalFloat64Array:
- return 8;
- break;
- default:
- UNREACHABLE();
- return -1;
- }
- UNREACHABLE();
- return -1;
-}
-
-
template <class ExternalArrayClass, class ElementType>
-static void ObjectWithExternalArrayTestHelper(
- Handle<Context> context,
- v8::Handle<Object> obj,
- int element_count,
- v8::ExternalArrayType array_type,
- int64_t low, int64_t high) {
+static void ObjectWithExternalArrayTestHelper(Handle<Context> context,
+ v8::Handle<Object> obj,
+ int element_count,
+ i::ExternalArrayType array_type,
+ int64_t low, int64_t high) {
i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
i::Isolate* isolate = jsobj->GetIsolate();
obj->Set(v8_str("field"),
"}"
"sum;");
// Force GC to trigger verification.
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
CHECK_EQ(28, result->Int32Value());
// Make sure out-of-range loads do not throw.
"}"
"ext_array[7];");
CHECK_EQ(0, result->Int32Value());
- if (array_type == v8::kExternalFloat64Array ||
- array_type == v8::kExternalFloat32Array) {
+ if (array_type == i::kExternalFloat64Array ||
+ array_type == i::kExternalFloat32Array) {
CHECK(std::isnan(
i::Object::GetElement(isolate, jsobj, 7).ToHandleChecked()->Number()));
} else {
i::Object::GetElement(
isolate, jsobj, 6).ToHandleChecked()->Number()));
- if (array_type != v8::kExternalFloat32Array &&
- array_type != v8::kExternalFloat64Array) {
+ if (array_type != i::kExternalFloat32Array &&
+ array_type != i::kExternalFloat64Array) {
// Though the specification doesn't state it, be explicit about
// converting NaNs and +/-Infinity to zero.
result = CompileRun("for (var i = 0; i < 8; i++) {"
"}"
"ext_array[5];");
int expected_value =
- (array_type == v8::kExternalUint8ClampedArray) ? 255 : 0;
+ (array_type == i::kExternalUint8ClampedArray) ? 255 : 0;
CHECK_EQ(expected_value, result->Int32Value());
CheckElementValue(isolate, expected_value, jsobj, 5);
const char* pixel_data =
"var source_data = [0.6, 10.6];"
"var expected_results = [1, 11];";
- bool is_unsigned =
- (array_type == v8::kExternalUint8Array ||
- array_type == v8::kExternalUint16Array ||
- array_type == v8::kExternalUint32Array);
- bool is_pixel_data = array_type == v8::kExternalUint8ClampedArray;
+ bool is_unsigned = (array_type == i::kExternalUint8Array ||
+ array_type == i::kExternalUint16Array ||
+ array_type == i::kExternalUint32Array);
+ bool is_pixel_data = array_type == i::kExternalUint8ClampedArray;
i::SNPrintF(test_buf,
"%s"
}
-template <class FixedTypedArrayClass,
- i::ElementsKind elements_kind,
+template <class FixedTypedArrayClass, i::ElementsKind elements_kind,
class ElementType>
-static void FixedTypedArrayTestHelper(
- v8::ExternalArrayType array_type,
- ElementType low,
- ElementType high) {
+static void FixedTypedArrayTestHelper(i::ExternalArrayType array_type,
+ ElementType low, ElementType high) {
i::FLAG_allow_natives_syntax = true;
LocalContext context;
i::Isolate* isolate = CcTest::i_isolate();
i::Factory* factory = isolate->factory();
v8::HandleScope scope(context->GetIsolate());
const int kElementCount = 260;
- i::Handle<FixedTypedArrayClass> fixed_array =
- i::Handle<FixedTypedArrayClass>::cast(
- factory->NewFixedTypedArray(kElementCount, array_type));
+ i::Handle<i::JSTypedArray> jsobj =
+ factory->NewJSTypedArray(elements_kind, kElementCount);
+ i::Handle<FixedTypedArrayClass> fixed_array(
+ FixedTypedArrayClass::cast(jsobj->elements()));
CHECK_EQ(FixedTypedArrayClass::kInstanceType,
fixed_array->map()->instance_type());
CHECK_EQ(kElementCount, fixed_array->length());
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
for (int i = 0; i < kElementCount; i++) {
fixed_array->set(i, static_cast<ElementType>(i));
}
// Force GC to trigger verification.
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
for (int i = 0; i < kElementCount; i++) {
CHECK_EQ(static_cast<int64_t>(static_cast<ElementType>(i)),
static_cast<int64_t>(fixed_array->get_scalar(i)));
}
- v8::Handle<v8::Object> obj = v8::Object::New(CcTest::isolate());
- i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
- i::Handle<i::Map> fixed_array_map =
- i::JSObject::GetElementsTransitionMap(jsobj, elements_kind);
- jsobj->set_map(*fixed_array_map);
- jsobj->set_elements(*fixed_array);
+ v8::Handle<v8::Object> obj = v8::Utils::ToLocal(jsobj);
ObjectWithExternalArrayTestHelper<FixedTypedArrayClass, ElementType>(
context.local(), obj, kElementCount, array_type,
THREADED_TEST(FixedUint8Array) {
FixedTypedArrayTestHelper<i::FixedUint8Array, i::UINT8_ELEMENTS, uint8_t>(
- v8::kExternalUint8Array,
- 0x0, 0xFF);
+ i::kExternalUint8Array, 0x0, 0xFF);
}
THREADED_TEST(FixedUint8ClampedArray) {
FixedTypedArrayTestHelper<i::FixedUint8ClampedArray,
i::UINT8_CLAMPED_ELEMENTS, uint8_t>(
- v8::kExternalUint8ClampedArray,
- 0x0, 0xFF);
+ i::kExternalUint8ClampedArray, 0x0, 0xFF);
}
THREADED_TEST(FixedInt8Array) {
FixedTypedArrayTestHelper<i::FixedInt8Array, i::INT8_ELEMENTS, int8_t>(
- v8::kExternalInt8Array,
- -0x80, 0x7F);
+ i::kExternalInt8Array, -0x80, 0x7F);
}
THREADED_TEST(FixedUint16Array) {
FixedTypedArrayTestHelper<i::FixedUint16Array, i::UINT16_ELEMENTS, uint16_t>(
- v8::kExternalUint16Array,
- 0x0, 0xFFFF);
+ i::kExternalUint16Array, 0x0, 0xFFFF);
}
THREADED_TEST(FixedInt16Array) {
FixedTypedArrayTestHelper<i::FixedInt16Array, i::INT16_ELEMENTS, int16_t>(
- v8::kExternalInt16Array,
- -0x8000, 0x7FFF);
+ i::kExternalInt16Array, -0x8000, 0x7FFF);
}
THREADED_TEST(FixedUint32Array) {
FixedTypedArrayTestHelper<i::FixedUint32Array, i::UINT32_ELEMENTS, uint32_t>(
- v8::kExternalUint32Array,
- 0x0, UINT_MAX);
+ i::kExternalUint32Array, 0x0, UINT_MAX);
}
THREADED_TEST(FixedInt32Array) {
FixedTypedArrayTestHelper<i::FixedInt32Array, i::INT32_ELEMENTS, int32_t>(
- v8::kExternalInt32Array,
- INT_MIN, INT_MAX);
+ i::kExternalInt32Array, INT_MIN, INT_MAX);
}
THREADED_TEST(FixedFloat32Array) {
FixedTypedArrayTestHelper<i::FixedFloat32Array, i::FLOAT32_ELEMENTS, float>(
- v8::kExternalFloat32Array,
- -500, 500);
+ i::kExternalFloat32Array, -500, 500);
}
THREADED_TEST(FixedFloat64Array) {
FixedTypedArrayTestHelper<i::FixedFloat64Array, i::FLOAT64_ELEMENTS, float>(
- v8::kExternalFloat64Array,
- -500, 500);
+ i::kExternalFloat64Array, -500, 500);
}
-template <class ExternalArrayClass, class ElementType>
-static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
- int64_t low,
- int64_t high) {
- LocalContext context;
- i::Isolate* isolate = CcTest::i_isolate();
- i::Factory* factory = isolate->factory();
- v8::HandleScope scope(context->GetIsolate());
- const int kElementCount = 40;
- int element_size = ExternalArrayElementSize(array_type);
- ElementType* array_data =
- static_cast<ElementType*>(malloc(kElementCount * element_size));
- i::Handle<ExternalArrayClass> array =
- i::Handle<ExternalArrayClass>::cast(
- factory->NewExternalArray(kElementCount, array_type, array_data));
- // Force GC to trigger verification.
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
- for (int i = 0; i < kElementCount; i++) {
- array->set(i, static_cast<ElementType>(i));
- }
- // Force GC to trigger verification.
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
- for (int i = 0; i < kElementCount; i++) {
- CHECK_EQ(static_cast<int64_t>(i),
- static_cast<int64_t>(array->get_scalar(i)));
- CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array_data[i]));
- }
-
- v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
- i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
- // Set the elements to be the external array.
- obj->SetIndexedPropertiesToExternalArrayData(array_data,
- array_type,
- kElementCount);
- CHECK_EQ(1,
- static_cast<int>(
- i::Object::GetElement(
- isolate, jsobj, 1).ToHandleChecked()->Number()));
-
- ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
- context.local(), obj, kElementCount, array_type, low, high);
-
- v8::Handle<v8::Value> result;
+template <typename ElementType, typename TypedArray, class ExternalArrayClass,
+ class ArrayBufferType>
+void TypedArrayTestHelper(i::ExternalArrayType array_type, int64_t low,
+ int64_t high) {
+ const int kElementCount = 50;
- // Test more complex manipulations which cause eax to contain values
- // that won't be completely overwritten by loads from the arrays.
- // This catches bugs in the instructions used for the KeyedLoadIC
- // for byte and word types.
- {
- const int kXSize = 300;
- const int kYSize = 300;
- const int kLargeElementCount = kXSize * kYSize * 4;
- ElementType* large_array_data =
- static_cast<ElementType*>(malloc(kLargeElementCount * element_size));
- v8::Handle<v8::Object> large_obj = v8::Object::New(context->GetIsolate());
- // Set the elements to be the external array.
- large_obj->SetIndexedPropertiesToExternalArrayData(large_array_data,
- array_type,
- kLargeElementCount);
- context->Global()->Set(v8_str("large_array"), large_obj);
- // Initialize contents of a few rows.
- for (int x = 0; x < 300; x++) {
- int row = 0;
- int offset = row * 300 * 4;
- large_array_data[offset + 4 * x + 0] = (ElementType) 127;
- large_array_data[offset + 4 * x + 1] = (ElementType) 0;
- large_array_data[offset + 4 * x + 2] = (ElementType) 0;
- large_array_data[offset + 4 * x + 3] = (ElementType) 127;
- row = 150;
- offset = row * 300 * 4;
- large_array_data[offset + 4 * x + 0] = (ElementType) 127;
- large_array_data[offset + 4 * x + 1] = (ElementType) 0;
- large_array_data[offset + 4 * x + 2] = (ElementType) 0;
- large_array_data[offset + 4 * x + 3] = (ElementType) 127;
- row = 298;
- offset = row * 300 * 4;
- large_array_data[offset + 4 * x + 0] = (ElementType) 127;
- large_array_data[offset + 4 * x + 1] = (ElementType) 0;
- large_array_data[offset + 4 * x + 2] = (ElementType) 0;
- large_array_data[offset + 4 * x + 3] = (ElementType) 127;
- }
- // The goal of the code below is to make "offset" large enough
- // that the computation of the index (which goes into eax) has
- // high bits set which will not be overwritten by a byte or short
- // load.
- result = CompileRun("var failed = false;"
- "var offset = 0;"
- "for (var i = 0; i < 300; i++) {"
- " if (large_array[4 * i] != 127 ||"
- " large_array[4 * i + 1] != 0 ||"
- " large_array[4 * i + 2] != 0 ||"
- " large_array[4 * i + 3] != 127) {"
- " failed = true;"
- " }"
- "}"
- "offset = 150 * 300 * 4;"
- "for (var i = 0; i < 300; i++) {"
- " if (large_array[offset + 4 * i] != 127 ||"
- " large_array[offset + 4 * i + 1] != 0 ||"
- " large_array[offset + 4 * i + 2] != 0 ||"
- " large_array[offset + 4 * i + 3] != 127) {"
- " failed = true;"
- " }"
- "}"
- "offset = 298 * 300 * 4;"
- "for (var i = 0; i < 300; i++) {"
- " if (large_array[offset + 4 * i] != 127 ||"
- " large_array[offset + 4 * i + 1] != 0 ||"
- " large_array[offset + 4 * i + 2] != 0 ||"
- " large_array[offset + 4 * i + 3] != 127) {"
- " failed = true;"
- " }"
- "}"
- "!failed;");
- CHECK_EQ(true, result->BooleanValue());
- free(large_array_data);
- }
+ i::ScopedVector<ElementType> backing_store(kElementCount+2);
- // The "" property descriptor is overloaded to store information about
- // the external array. Ensure that setting and accessing the "" property
- // works (it should overwrite the information cached about the external
- // array in the DescriptorArray) in various situations.
- result = CompileRun("ext_array[''] = 23; ext_array['']");
- CHECK_EQ(23, result->Int32Value());
+ LocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope handle_scope(isolate);
- // Property "" set after the external array is associated with the object.
- {
- v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
- obj2->Set(v8_str("ee_test_field"),
- v8::Int32::New(context->GetIsolate(), 256));
- obj2->Set(v8_str(""), v8::Int32::New(context->GetIsolate(), 1503));
- // Set the elements to be the external array.
- obj2->SetIndexedPropertiesToExternalArrayData(array_data,
- array_type,
- kElementCount);
- context->Global()->Set(v8_str("ext_array"), obj2);
- result = CompileRun("ext_array['']");
- CHECK_EQ(1503, result->Int32Value());
- }
-
- // Property "" set after the external array is associated with the object.
- {
- v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
- obj2->Set(v8_str("ee_test_field_2"),
- v8::Int32::New(context->GetIsolate(), 256));
- // Set the elements to be the external array.
- obj2->SetIndexedPropertiesToExternalArrayData(array_data,
- array_type,
- kElementCount);
- obj2->Set(v8_str(""), v8::Int32::New(context->GetIsolate(), 1503));
- context->Global()->Set(v8_str("ext_array"), obj2);
- result = CompileRun("ext_array['']");
- CHECK_EQ(1503, result->Int32Value());
- }
-
- // Should reuse the map from previous test.
- {
- v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
- obj2->Set(v8_str("ee_test_field_2"),
- v8::Int32::New(context->GetIsolate(), 256));
- // Set the elements to be the external array. Should re-use the map
- // from previous test.
- obj2->SetIndexedPropertiesToExternalArrayData(array_data,
- array_type,
- kElementCount);
- context->Global()->Set(v8_str("ext_array"), obj2);
- result = CompileRun("ext_array['']");
- }
-
- // Property "" is a constant function that shouldn't not be interfered with
- // when an external array is set.
- {
- v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
- // Start
- obj2->Set(v8_str("ee_test_field3"),
- v8::Int32::New(context->GetIsolate(), 256));
-
- // Add a constant function to an object.
- context->Global()->Set(v8_str("ext_array"), obj2);
- result = CompileRun("ext_array[''] = function() {return 1503;};"
- "ext_array['']();");
-
- // Add an external array transition to the same map that
- // has the constant transition.
- v8::Handle<v8::Object> obj3 = v8::Object::New(context->GetIsolate());
- obj3->Set(v8_str("ee_test_field3"),
- v8::Int32::New(context->GetIsolate(), 256));
- obj3->SetIndexedPropertiesToExternalArrayData(array_data,
- array_type,
- kElementCount);
- context->Global()->Set(v8_str("ext_array"), obj3);
- }
-
- // If a external array transition is in the map, it should get clobbered
- // by a constant function.
- {
- // Add an external array transition.
- v8::Handle<v8::Object> obj3 = v8::Object::New(context->GetIsolate());
- obj3->Set(v8_str("ee_test_field4"),
- v8::Int32::New(context->GetIsolate(), 256));
- obj3->SetIndexedPropertiesToExternalArrayData(array_data,
- array_type,
- kElementCount);
+ Local<ArrayBufferType> ab =
+ ArrayBufferType::New(isolate, backing_store.start(),
+ (kElementCount + 2) * sizeof(ElementType));
+ Local<TypedArray> ta =
+ TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
+ CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
+ CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
+ CHECK_EQ(2 * sizeof(ElementType), ta->ByteOffset());
+ CHECK_EQ(kElementCount * sizeof(ElementType), ta->ByteLength());
+ CHECK(ab->Equals(ta->Buffer()));
- // Add a constant function to the same map that just got an external array
- // transition.
- v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
- obj2->Set(v8_str("ee_test_field4"),
- v8::Int32::New(context->GetIsolate(), 256));
- context->Global()->Set(v8_str("ext_array"), obj2);
- result = CompileRun("ext_array[''] = function() {return 1503;};"
- "ext_array['']();");
+ ElementType* data = backing_store.start() + 2;
+ for (int i = 0; i < kElementCount; i++) {
+ data[i] = static_cast<ElementType>(i);
}
- free(array_data);
-}
-
-
-THREADED_TEST(ExternalInt8Array) {
- ExternalArrayTestHelper<i::ExternalInt8Array, int8_t>(
- v8::kExternalInt8Array,
- -128,
- 127);
+ ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
+ env.local(), ta, kElementCount, array_type, low, high);
}
-THREADED_TEST(ExternalUint8Array) {
- ExternalArrayTestHelper<i::ExternalUint8Array, uint8_t>(
- v8::kExternalUint8Array,
- 0,
- 255);
+THREADED_TEST(Uint8Array) {
+ TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::ExternalUint8Array,
+ v8::ArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
}
-THREADED_TEST(ExternalUint8ClampedArray) {
- ExternalArrayTestHelper<i::ExternalUint8ClampedArray, uint8_t>(
- v8::kExternalUint8ClampedArray,
- 0,
- 255);
+THREADED_TEST(Int8Array) {
+ TypedArrayTestHelper<int8_t, v8::Int8Array, i::ExternalInt8Array,
+ v8::ArrayBuffer>(i::kExternalInt8Array, -0x80, 0x7F);
}
-THREADED_TEST(ExternalInt16Array) {
- ExternalArrayTestHelper<i::ExternalInt16Array, int16_t>(
- v8::kExternalInt16Array,
- -32768,
- 32767);
+THREADED_TEST(Uint16Array) {
+ TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::ExternalUint16Array,
+ v8::ArrayBuffer>(i::kExternalUint16Array, 0, 0xFFFF);
}
-THREADED_TEST(ExternalUint16Array) {
- ExternalArrayTestHelper<i::ExternalUint16Array, uint16_t>(
- v8::kExternalUint16Array,
- 0,
- 65535);
+THREADED_TEST(Int16Array) {
+ TypedArrayTestHelper<int16_t, v8::Int16Array, i::ExternalInt16Array,
+ v8::ArrayBuffer>(i::kExternalInt16Array, -0x8000,
+ 0x7FFF);
}
-THREADED_TEST(ExternalInt32Array) {
- ExternalArrayTestHelper<i::ExternalInt32Array, int32_t>(
- v8::kExternalInt32Array,
- INT_MIN, // -2147483648
- INT_MAX); // 2147483647
+THREADED_TEST(Uint32Array) {
+ TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::ExternalUint32Array,
+ v8::ArrayBuffer>(i::kExternalUint32Array, 0, UINT_MAX);
}
-THREADED_TEST(ExternalUint32Array) {
- ExternalArrayTestHelper<i::ExternalUint32Array, uint32_t>(
- v8::kExternalUint32Array,
- 0,
- UINT_MAX); // 4294967295
+THREADED_TEST(Int32Array) {
+ TypedArrayTestHelper<int32_t, v8::Int32Array, i::ExternalInt32Array,
+ v8::ArrayBuffer>(i::kExternalInt32Array, INT_MIN,
+ INT_MAX);
}
-THREADED_TEST(ExternalFloat32Array) {
- ExternalArrayTestHelper<i::ExternalFloat32Array, float>(
- v8::kExternalFloat32Array,
- -500,
- 500);
+THREADED_TEST(Float32Array) {
+ TypedArrayTestHelper<float, v8::Float32Array, i::ExternalFloat32Array,
+ v8::ArrayBuffer>(i::kExternalFloat32Array, -500, 500);
}
-THREADED_TEST(ExternalFloat64Array) {
- ExternalArrayTestHelper<i::ExternalFloat64Array, double>(
- v8::kExternalFloat64Array,
- -500,
- 500);
+THREADED_TEST(Float64Array) {
+ TypedArrayTestHelper<double, v8::Float64Array, i::ExternalFloat64Array,
+ v8::ArrayBuffer>(i::kExternalFloat64Array, -500, 500);
}
-THREADED_TEST(ExternalArrays) {
- TestExternalInt8Array();
- TestExternalUint8Array();
- TestExternalInt16Array();
- TestExternalUint16Array();
- TestExternalInt32Array();
- TestExternalUint32Array();
- TestExternalFloat32Array();
+THREADED_TEST(Uint8ClampedArray) {
+ TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
+ i::ExternalUint8ClampedArray, v8::ArrayBuffer>(
+ i::kExternalUint8ClampedArray, 0, 0xFF);
}
-void ExternalArrayInfoTestHelper(v8::ExternalArrayType array_type) {
- LocalContext context;
- v8::HandleScope scope(context->GetIsolate());
- for (int size = 0; size < 100; size += 10) {
- int element_size = ExternalArrayElementSize(array_type);
- void* external_data = malloc(size * element_size);
- v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
- obj->SetIndexedPropertiesToExternalArrayData(
- external_data, array_type, size);
- CHECK(obj->HasIndexedPropertiesInExternalArrayData());
- CHECK_EQ(external_data, obj->GetIndexedPropertiesExternalArrayData());
- CHECK_EQ(array_type, obj->GetIndexedPropertiesExternalArrayDataType());
- CHECK_EQ(size, obj->GetIndexedPropertiesExternalArrayDataLength());
- free(external_data);
- }
-}
-
+THREADED_TEST(DataView) {
+ const int kSize = 50;
-THREADED_TEST(ExternalArrayInfo) {
- ExternalArrayInfoTestHelper(v8::kExternalInt8Array);
- ExternalArrayInfoTestHelper(v8::kExternalUint8Array);
- ExternalArrayInfoTestHelper(v8::kExternalInt16Array);
- ExternalArrayInfoTestHelper(v8::kExternalUint16Array);
- ExternalArrayInfoTestHelper(v8::kExternalInt32Array);
- ExternalArrayInfoTestHelper(v8::kExternalUint32Array);
- ExternalArrayInfoTestHelper(v8::kExternalFloat32Array);
- ExternalArrayInfoTestHelper(v8::kExternalFloat64Array);
- ExternalArrayInfoTestHelper(v8::kExternalUint8ClampedArray);
-}
+ i::ScopedVector<uint8_t> backing_store(kSize+2);
+ LocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope handle_scope(isolate);
-void ExtArrayLimitsHelper(v8::Isolate* isolate,
- v8::ExternalArrayType array_type,
- int size) {
- v8::Handle<v8::Object> obj = v8::Object::New(isolate);
- v8::V8::SetFatalErrorHandler(StoringErrorCallback);
- last_location = last_message = NULL;
- obj->SetIndexedPropertiesToExternalArrayData(NULL, array_type, size);
- CHECK(!obj->HasIndexedPropertiesInExternalArrayData());
- CHECK(last_location);
- CHECK(last_message);
+ Local<v8::ArrayBuffer> ab =
+ v8::ArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
+ Local<v8::DataView> dv = v8::DataView::New(ab, 2, kSize);
+ CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
+ CHECK_EQ(2u, dv->ByteOffset());
+ CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
+ CHECK(ab->Equals(dv->Buffer()));
}
-TEST(ExternalArrayLimits) {
- LocalContext context;
- v8::Isolate* isolate = context->GetIsolate();
- v8::HandleScope scope(isolate);
- ExtArrayLimitsHelper(isolate, v8::kExternalInt8Array, 0x40000000);
- ExtArrayLimitsHelper(isolate, v8::kExternalInt8Array, 0xffffffff);
- ExtArrayLimitsHelper(isolate, v8::kExternalUint8Array, 0x40000000);
- ExtArrayLimitsHelper(isolate, v8::kExternalUint8Array, 0xffffffff);
- ExtArrayLimitsHelper(isolate, v8::kExternalInt16Array, 0x40000000);
- ExtArrayLimitsHelper(isolate, v8::kExternalInt16Array, 0xffffffff);
- ExtArrayLimitsHelper(isolate, v8::kExternalUint16Array, 0x40000000);
- ExtArrayLimitsHelper(isolate, v8::kExternalUint16Array, 0xffffffff);
- ExtArrayLimitsHelper(isolate, v8::kExternalInt32Array, 0x40000000);
- ExtArrayLimitsHelper(isolate, v8::kExternalInt32Array, 0xffffffff);
- ExtArrayLimitsHelper(isolate, v8::kExternalUint32Array, 0x40000000);
- ExtArrayLimitsHelper(isolate, v8::kExternalUint32Array, 0xffffffff);
- ExtArrayLimitsHelper(isolate, v8::kExternalFloat32Array, 0x40000000);
- ExtArrayLimitsHelper(isolate, v8::kExternalFloat32Array, 0xffffffff);
- ExtArrayLimitsHelper(isolate, v8::kExternalFloat64Array, 0x40000000);
- ExtArrayLimitsHelper(isolate, v8::kExternalFloat64Array, 0xffffffff);
- ExtArrayLimitsHelper(isolate, v8::kExternalUint8ClampedArray, 0x40000000);
- ExtArrayLimitsHelper(isolate, v8::kExternalUint8ClampedArray, 0xffffffff);
-}
-
-
-template <typename ElementType, typename TypedArray,
- class ExternalArrayClass>
-void TypedArrayTestHelper(v8::ExternalArrayType array_type,
- int64_t low, int64_t high) {
- const int kElementCount = 50;
-
- i::ScopedVector<ElementType> backing_store(kElementCount+2);
-
+THREADED_TEST(SkipArrayBufferBackingStoreDuringGC) {
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
v8::HandleScope handle_scope(isolate);
- Local<v8::ArrayBuffer> ab =
- v8::ArrayBuffer::New(isolate, backing_store.start(),
- (kElementCount + 2) * sizeof(ElementType));
- Local<TypedArray> ta =
- TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
- CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
- CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
- CHECK_EQ(2 * sizeof(ElementType), ta->ByteOffset());
- CHECK_EQ(kElementCount * sizeof(ElementType), ta->ByteLength());
- CHECK(ab->Equals(ta->Buffer()));
+ // Make sure the pointer looks like a heap object
+ uint8_t* store_ptr = reinterpret_cast<uint8_t*>(i::kHeapObjectTag);
- ElementType* data = backing_store.start() + 2;
- for (int i = 0; i < kElementCount; i++) {
- data[i] = static_cast<ElementType>(i);
- }
+ // Create ArrayBuffer with pointer-that-cannot-be-visited in the backing store
+ Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, store_ptr, 8);
- ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
- env.local(), ta, kElementCount, array_type, low, high);
+ // Should not crash
+ CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
+ CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
+ CcTest::heap()->CollectAllGarbage();
+ CcTest::heap()->CollectAllGarbage();
+
+ // Should not move the pointer
+ CHECK_EQ(ab->GetContents().Data(), store_ptr);
}
-THREADED_TEST(Uint8Array) {
- TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::ExternalUint8Array>(
- v8::kExternalUint8Array, 0, 0xFF);
+THREADED_TEST(SharedUint8Array) {
+ i::FLAG_harmony_sharedarraybuffer = true;
+ TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::ExternalUint8Array,
+ v8::SharedArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
}
-THREADED_TEST(Int8Array) {
- TypedArrayTestHelper<int8_t, v8::Int8Array, i::ExternalInt8Array>(
- v8::kExternalInt8Array, -0x80, 0x7F);
+THREADED_TEST(SharedInt8Array) {
+ i::FLAG_harmony_sharedarraybuffer = true;
+ TypedArrayTestHelper<int8_t, v8::Int8Array, i::ExternalInt8Array,
+ v8::SharedArrayBuffer>(i::kExternalInt8Array, -0x80,
+ 0x7F);
}
-THREADED_TEST(Uint16Array) {
- TypedArrayTestHelper<uint16_t,
- v8::Uint16Array,
- i::ExternalUint16Array>(
- v8::kExternalUint16Array, 0, 0xFFFF);
+THREADED_TEST(SharedUint16Array) {
+ i::FLAG_harmony_sharedarraybuffer = true;
+ TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::ExternalUint16Array,
+ v8::SharedArrayBuffer>(i::kExternalUint16Array, 0,
+ 0xFFFF);
}
-THREADED_TEST(Int16Array) {
- TypedArrayTestHelper<int16_t, v8::Int16Array, i::ExternalInt16Array>(
- v8::kExternalInt16Array, -0x8000, 0x7FFF);
+THREADED_TEST(SharedInt16Array) {
+ i::FLAG_harmony_sharedarraybuffer = true;
+ TypedArrayTestHelper<int16_t, v8::Int16Array, i::ExternalInt16Array,
+ v8::SharedArrayBuffer>(i::kExternalInt16Array, -0x8000,
+ 0x7FFF);
}
-THREADED_TEST(Uint32Array) {
- TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::ExternalUint32Array>(
- v8::kExternalUint32Array, 0, UINT_MAX);
+THREADED_TEST(SharedUint32Array) {
+ i::FLAG_harmony_sharedarraybuffer = true;
+ TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::ExternalUint32Array,
+ v8::SharedArrayBuffer>(i::kExternalUint32Array, 0,
+ UINT_MAX);
}
-THREADED_TEST(Int32Array) {
- TypedArrayTestHelper<int32_t, v8::Int32Array, i::ExternalInt32Array>(
- v8::kExternalInt32Array, INT_MIN, INT_MAX);
+THREADED_TEST(SharedInt32Array) {
+ i::FLAG_harmony_sharedarraybuffer = true;
+ TypedArrayTestHelper<int32_t, v8::Int32Array, i::ExternalInt32Array,
+ v8::SharedArrayBuffer>(i::kExternalInt32Array, INT_MIN,
+ INT_MAX);
}
-THREADED_TEST(Float32Array) {
- TypedArrayTestHelper<float, v8::Float32Array, i::ExternalFloat32Array>(
- v8::kExternalFloat32Array, -500, 500);
+THREADED_TEST(SharedFloat32Array) {
+ i::FLAG_harmony_sharedarraybuffer = true;
+ TypedArrayTestHelper<float, v8::Float32Array, i::ExternalFloat32Array,
+ v8::SharedArrayBuffer>(i::kExternalFloat32Array, -500,
+ 500);
}
-THREADED_TEST(Float64Array) {
- TypedArrayTestHelper<double, v8::Float64Array, i::ExternalFloat64Array>(
- v8::kExternalFloat64Array, -500, 500);
+THREADED_TEST(SharedFloat64Array) {
+ i::FLAG_harmony_sharedarraybuffer = true;
+ TypedArrayTestHelper<double, v8::Float64Array, i::ExternalFloat64Array,
+ v8::SharedArrayBuffer>(i::kExternalFloat64Array, -500,
+ 500);
}
-THREADED_TEST(Uint8ClampedArray) {
- TypedArrayTestHelper<uint8_t,
- v8::Uint8ClampedArray, i::ExternalUint8ClampedArray>(
- v8::kExternalUint8ClampedArray, 0, 0xFF);
+THREADED_TEST(SharedUint8ClampedArray) {
+ i::FLAG_harmony_sharedarraybuffer = true;
+ TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
+ i::ExternalUint8ClampedArray, v8::SharedArrayBuffer>(
+ i::kExternalUint8ClampedArray, 0, 0xFF);
}
-THREADED_TEST(DataView) {
+THREADED_TEST(SharedDataView) {
+ i::FLAG_harmony_sharedarraybuffer = true;
const int kSize = 50;
- i::ScopedVector<uint8_t> backing_store(kSize+2);
+ i::ScopedVector<uint8_t> backing_store(kSize + 2);
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
v8::HandleScope handle_scope(isolate);
- Local<v8::ArrayBuffer> ab =
- v8::ArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
+ Local<v8::SharedArrayBuffer> ab =
+ v8::SharedArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
Local<v8::DataView> dv =
v8::DataView::New(ab, 2, kSize);
CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
THREADED_TEST(StackTrace) {
LocalContext context;
v8::HandleScope scope(context->GetIsolate());
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(context->GetIsolate());
const char *source = "function foo() { FAIL.FAIL; }; foo();";
v8::Handle<v8::String> src =
v8::String::NewFromUtf8(context->GetIsolate(), source);
checkStackFrame(origin, "foo", 6, 3, false, false,
stackTrace->GetFrame(1));
// This is the source string inside the eval which has the call to foo.
- checkStackFrame(NULL, "", 1, 5, false, false,
- stackTrace->GetFrame(2));
+ checkStackFrame(NULL, "", 1, 1, false, false, stackTrace->GetFrame(2));
// The last frame is an anonymous function which has the initial eval call.
- checkStackFrame(origin, "", 8, 7, false, false,
- stackTrace->GetFrame(3));
+ checkStackFrame(origin, "", 8, 7, false, false, stackTrace->GetFrame(3));
CHECK(stackTrace->AsArray()->IsArray());
} else if (testGroup == kDetailedTest) {
stackTrace->GetFrame(1));
bool is_eval = true;
// This is the source string inside the eval which has the call to baz.
- checkStackFrame(NULL, "", 1, 5, is_eval, false,
- stackTrace->GetFrame(2));
+ checkStackFrame(NULL, "", 1, 1, is_eval, false, stackTrace->GetFrame(2));
// The last frame is an anonymous function which has the initial eval call.
- checkStackFrame(origin, "", 10, 1, false, false,
- stackTrace->GetFrame(3));
+ checkStackFrame(origin, "", 10, 1, false, false, stackTrace->GetFrame(3));
CHECK(stackTrace->AsArray()->IsArray());
}
v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
args.GetIsolate(), 10, v8::StackTrace::kDetailed);
CHECK_EQ(4, stackTrace->GetFrameCount());
- v8::Handle<v8::String> url = v8_str("url");
+ v8::Handle<v8::String> url = v8_str("source_url");
for (int i = 0; i < 3; i++) {
v8::Handle<v8::String> name =
stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
i::ScopedVector<char> code(1024);
i::SNPrintF(code, source, "//# sourceURL=source_url");
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(context->GetIsolate());
CompileRunWithOrigin(code.start(), "", 0, 0);
CHECK(try_catch.HasCaught());
v8::String::Utf8Value stack(try_catch.StackTrace());
"outer();\n"
"//# sourceURL=outer_url";
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(context->GetIsolate());
CompileRun(source);
CHECK(try_catch.HasCaught());
"outer();\n"
"//# sourceURL=outer_url";
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(context->GetIsolate());
CompileRun(source);
CHECK(try_catch.HasCaught());
// Test that idle notification can be handled and eventually collects garbage.
TEST(TestIdleNotification) {
+ if (!i::FLAG_incremental_marking) return;
const intptr_t MB = 1024 * 1024;
const double IdlePauseInSeconds = 1.0;
LocalContext env;
CHECK_GT(size_with_garbage, initial_size + MB);
bool finished = false;
for (int i = 0; i < 200 && !finished; i++) {
+ if (i < 10 && CcTest::heap()->incremental_marking()->IsStopped()) {
+ CcTest::heap()->StartIdleIncrementalMarking();
+ }
finished = env->GetIsolate()->IdleNotificationDeadline(
(v8::base::TimeTicks::HighResolutionNow().ToInternalValue() /
static_cast<double>(v8::base::Time::kMicrosecondsPerSecond)) +
IdlePauseInSeconds);
+ if (CcTest::heap()->mark_compact_collector()->sweeping_in_progress()) {
+ CcTest::heap()->mark_compact_collector()->EnsureSweepingCompleted();
+ }
}
intptr_t final_size = CcTest::heap()->SizeOfObjects();
CHECK(finished);
CompileRun("'Romeo Montague ' + 'Juliet Capulet'")->ToString(isolate);
CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
CcTest::heap()->CollectAllAvailableGarbage();
- CHECK(CcTest::heap()->old_pointer_space()->Contains(
- *v8::Utils::OpenHandle(*cons)));
+ CHECK(CcTest::heap()->old_space()->Contains(*v8::Utils::OpenHandle(*cons)));
TestResource* resource = new TestResource(
AsciiToTwoByteString("Romeo Montague Juliet Capulet"));
CompileRun("'Romeo Montague ' + 'Juliet Capulet'")->ToString(isolate);
CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
CcTest::heap()->CollectAllAvailableGarbage();
- CHECK(CcTest::heap()->old_pointer_space()->Contains(
- *v8::Utils::OpenHandle(*cons)));
+ CHECK(CcTest::heap()->old_space()->Contains(*v8::Utils::OpenHandle(*cons)));
TestOneByteResource* resource =
new TestOneByteResource(i::StrDup("Romeo Montague Juliet Capulet"));
TEST(ExternalStringCollectedAtTearDown) {
int destroyed = 0;
- v8::Isolate* isolate = v8::Isolate::New();
+ v8::Isolate::CreateParams create_params;
+ create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
+ v8::Isolate* isolate = v8::Isolate::New(create_params);
{ 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.";
TEST(ExternalInternalizedStringCollectedAtTearDown) {
int destroyed = 0;
- v8::Isolate* isolate = v8::Isolate::New();
+ v8::Isolate::CreateParams create_params;
+ create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
+ v8::Isolate* isolate = v8::Isolate::New(create_params);
{ v8::Isolate::Scope isolate_scope(isolate);
LocalContext env(isolate);
v8::HandleScope handle_scope(isolate);
TEST(ExternalInternalizedStringCollectedAtGC) {
- // TODO(mvstanton): vector ics need weak support.
- if (i::FLAG_vector_ics) return;
-
int destroyed = 0;
{ LocalContext env;
v8::HandleScope handle_scope(env->GetIsolate());
LocalContext context;
v8::Isolate* isolate = context->GetIsolate();
v8::HandleScope scope(isolate);
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
// Special double values.
double snan = DoubleFromBits(0x7ff00000, 0x00000001);
static void SpaghettiIncident(
const v8::FunctionCallbackInfo<v8::Value>& args) {
v8::HandleScope scope(args.GetIsolate());
- v8::TryCatch tc;
+ v8::TryCatch tc(args.GetIsolate());
v8::Handle<v8::String> str(args[0]->ToString(args.GetIsolate()));
USE(str);
if (tc.HasCaught())
context->Global()->Set(
v8::String::NewFromUtf8(isolate, "s"),
v8::FunctionTemplate::New(isolate, SpaghettiIncident)->GetFunction());
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
CompileRun(
"var i = 0;"
"var o = {"
other_context->Enter();
CompileRun(source_simple);
other_context->Exit();
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
if (GetGlobalObjectsCount() == 1) break;
}
CHECK_GE(2, gc_count);
other_context->Enter();
CompileRun(source_eval);
other_context->Exit();
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
if (GetGlobalObjectsCount() == 1) break;
}
CHECK_GE(2, gc_count);
v8::Local<Context> context = Context::New(isolate);
context->Enter();
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
CompileRun(source_exception);
CHECK(try_catch.HasCaught());
v8::Handle<v8::Message> message = try_catch.Message();
other_context->Enter();
CompileRun(source_exception);
other_context->Exit();
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
if (GetGlobalObjectsCount() == 1) break;
}
CHECK_GE(2, gc_count);
v8::Integer::New(env->GetIsolate(), 1),
v8::Integer::New(env->GetIsolate(), 1), v8::True(env->GetIsolate()),
v8::Handle<v8::Integer>(), v8::True(env->GetIsolate()),
- v8::String::NewFromUtf8(env->GetIsolate(), "http://sourceMapUrl"));
+ v8::String::NewFromUtf8(env->GetIsolate(), "http://sourceMapUrl"),
+ v8::True(env->GetIsolate()));
v8::Handle<v8::String> script = v8::String::NewFromUtf8(
env->GetIsolate(), "function f() {}\n\nfunction g() {}");
v8::Script::Compile(script, &origin)->Run();
CHECK_EQ(0, strcmp("test",
*v8::String::Utf8Value(script_origin_f.ResourceName())));
CHECK_EQ(1, script_origin_f.ResourceLineOffset()->Int32Value());
- CHECK(script_origin_f.ResourceIsSharedCrossOrigin()->Value());
- CHECK(script_origin_f.ResourceIsEmbedderDebugScript()->Value());
+ CHECK(script_origin_f.Options().IsSharedCrossOrigin());
+ CHECK(script_origin_f.Options().IsEmbedderDebugScript());
+ CHECK(script_origin_f.Options().IsOpaque());
printf("is name = %d\n", script_origin_f.SourceMapUrl()->IsUndefined());
CHECK_EQ(0, strcmp("http://sourceMapUrl",
CHECK_EQ(0, strcmp("test",
*v8::String::Utf8Value(script_origin_g.ResourceName())));
CHECK_EQ(1, script_origin_g.ResourceLineOffset()->Int32Value());
- CHECK(script_origin_g.ResourceIsSharedCrossOrigin()->Value());
- CHECK(script_origin_g.ResourceIsEmbedderDebugScript()->Value());
+ CHECK(script_origin_g.Options().IsSharedCrossOrigin());
+ CHECK(script_origin_g.Options().IsEmbedderDebugScript());
+ CHECK(script_origin_g.Options().IsOpaque());
CHECK_EQ(0, strcmp("http://sourceMapUrl",
*v8::String::Utf8Value(script_origin_g.SourceMapUrl())));
}
v8::V8::AddGCEpilogueCallback(EpilogueCallback);
CHECK_EQ(0, prologue_call_count);
CHECK_EQ(0, epilogue_call_count);
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
CHECK_EQ(1, prologue_call_count);
CHECK_EQ(1, epilogue_call_count);
v8::V8::AddGCPrologueCallback(PrologueCallbackSecond);
v8::V8::AddGCEpilogueCallback(EpilogueCallbackSecond);
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
CHECK_EQ(2, prologue_call_count);
CHECK_EQ(2, epilogue_call_count);
CHECK_EQ(1, prologue_call_count_second);
CHECK_EQ(1, epilogue_call_count_second);
v8::V8::RemoveGCPrologueCallback(PrologueCallback);
v8::V8::RemoveGCEpilogueCallback(EpilogueCallback);
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
CHECK_EQ(2, prologue_call_count);
CHECK_EQ(2, epilogue_call_count);
CHECK_EQ(2, prologue_call_count_second);
CHECK_EQ(2, epilogue_call_count_second);
v8::V8::RemoveGCPrologueCallback(PrologueCallbackSecond);
v8::V8::RemoveGCEpilogueCallback(EpilogueCallbackSecond);
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
CHECK_EQ(2, prologue_call_count);
CHECK_EQ(2, epilogue_call_count);
CHECK_EQ(2, prologue_call_count_second);
isolate->AddGCEpilogueCallback(EpilogueCallback);
CHECK_EQ(0, prologue_call_count);
CHECK_EQ(0, epilogue_call_count);
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
CHECK_EQ(1, prologue_call_count);
CHECK_EQ(1, epilogue_call_count);
isolate->AddGCPrologueCallback(PrologueCallbackSecond);
isolate->AddGCEpilogueCallback(EpilogueCallbackSecond);
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
CHECK_EQ(2, prologue_call_count);
CHECK_EQ(2, epilogue_call_count);
CHECK_EQ(1, prologue_call_count_second);
CHECK_EQ(1, epilogue_call_count_second);
isolate->RemoveGCPrologueCallback(PrologueCallback);
isolate->RemoveGCEpilogueCallback(EpilogueCallback);
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
CHECK_EQ(2, prologue_call_count);
CHECK_EQ(2, epilogue_call_count);
CHECK_EQ(2, prologue_call_count_second);
CHECK_EQ(2, epilogue_call_count_second);
isolate->RemoveGCPrologueCallback(PrologueCallbackSecond);
isolate->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
CHECK_EQ(2, prologue_call_count);
CHECK_EQ(2, epilogue_call_count);
CHECK_EQ(2, prologue_call_count_second);
void FailedAccessCheckCallbackGC(Local<v8::Object> target,
v8::AccessType type,
Local<v8::Value> data) {
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
+ CcTest::isolate()->ThrowException(
+ v8::Exception::Error(v8_str("cross context")));
}
v8::Handle<v8::ObjectTemplate> global_template =
v8::ObjectTemplate::New(isolate);
global_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL,
- v8::Handle<v8::Value>(), false);
+ v8::Handle<v8::Value>());
// Create a context and set an x property on it's global object.
LocalContext context0(NULL, global_template);
LocalContext context1(NULL, global_template);
context1->Global()->Set(v8_str("other"), global0);
+ v8::TryCatch try_catch(isolate);
+
// Get property with failed access check.
- ExpectUndefined("other.x");
+ CHECK(CompileRun("other.x").IsEmpty());
+ CHECK(try_catch.HasCaught());
+ try_catch.Reset();
// Get element with failed access check.
- ExpectUndefined("other[0]");
+ CHECK(CompileRun("other[0]").IsEmpty());
+ CHECK(try_catch.HasCaught());
+ try_catch.Reset();
// Set property with failed access check.
- v8::Handle<v8::Value> result = CompileRun("other.x = new Object()");
- CHECK(result->IsObject());
+ CHECK(CompileRun("other.x = new Object()").IsEmpty());
+ CHECK(try_catch.HasCaught());
+ try_catch.Reset();
// Set element with failed access check.
- result = CompileRun("other[0] = new Object()");
- CHECK(result->IsObject());
+ CHECK(CompileRun("other[0] = new Object()").IsEmpty());
+ CHECK(try_catch.HasCaught());
+ try_catch.Reset();
// Get property attribute with failed access check.
- ExpectFalse("\'x\' in other");
+ CHECK(CompileRun("\'x\' in other").IsEmpty());
+ CHECK(try_catch.HasCaught());
+ try_catch.Reset();
// Get property attribute for element with failed access check.
- ExpectFalse("0 in other");
+ CHECK(CompileRun("0 in other").IsEmpty());
+ CHECK(try_catch.HasCaught());
+ try_catch.Reset();
// Delete property.
- ExpectFalse("delete other.x");
+ CHECK(CompileRun("delete other.x").IsEmpty());
+ CHECK(try_catch.HasCaught());
+ try_catch.Reset();
// Delete element.
CHECK_EQ(false, global0->Delete(0));
global0->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("x")));
// Define JavaScript accessor.
- ExpectUndefined("Object.prototype.__defineGetter__.call("
- " other, \'x\', function() { return 42; })");
+ CHECK(CompileRun(
+ "Object.prototype.__defineGetter__.call("
+ " other, \'x\', function() { return 42; })").IsEmpty());
+ CHECK(try_catch.HasCaught());
+ try_catch.Reset();
// LookupAccessor.
- ExpectUndefined("Object.prototype.__lookupGetter__.call("
- " other, \'x\')");
+ CHECK(CompileRun(
+ "Object.prototype.__lookupGetter__.call("
+ " other, \'x\')").IsEmpty());
+ CHECK(try_catch.HasCaught());
+ try_catch.Reset();
// HasOwnElement.
- ExpectFalse("Object.prototype.hasOwnProperty.call(other, \'0\')");
+ CHECK(CompileRun(
+ "Object.prototype.hasOwnProperty.call("
+ "other, \'0\')").IsEmpty());
+ CHECK(try_catch.HasCaught());
+ try_catch.Reset();
CHECK_EQ(false, global0->HasRealIndexedProperty(0));
CHECK_EQ(false, global0->HasRealNamedProperty(v8_str("x")));
TEST(IsolateNewDispose) {
v8::Isolate* current_isolate = CcTest::isolate();
- v8::Isolate* isolate = v8::Isolate::New();
+ v8::Isolate::CreateParams create_params;
+ create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
+ v8::Isolate* isolate = v8::Isolate::New(create_params);
CHECK(isolate != NULL);
CHECK(current_isolate != isolate);
CHECK(current_isolate == CcTest::isolate());
UNINITIALIZED_TEST(DisposeIsolateWhenInUse) {
- v8::Isolate* isolate = v8::Isolate::New();
+ v8::Isolate::CreateParams create_params;
+ create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
+ v8::Isolate* isolate = v8::Isolate::New(create_params);
{
v8::Isolate::Scope i_scope(isolate);
v8::HandleScope scope(isolate);
}
+static void BreakArrayGuarantees(const char* script) {
+ v8::Isolate::CreateParams create_params;
+ create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
+ v8::Isolate* isolate1 = v8::Isolate::New(create_params);
+ isolate1->Enter();
+ v8::Persistent<v8::Context> context1;
+ {
+ v8::HandleScope scope(isolate1);
+ context1.Reset(isolate1, Context::New(isolate1));
+ }
+
+ {
+ v8::HandleScope scope(isolate1);
+ v8::Local<v8::Context> context =
+ v8::Local<v8::Context>::New(isolate1, context1);
+ v8::Context::Scope context_scope(context);
+ v8::internal::Isolate* i_isolate =
+ reinterpret_cast<v8::internal::Isolate*>(isolate1);
+ CHECK_EQ(true, i_isolate->IsFastArrayConstructorPrototypeChainIntact());
+ // Run something in new isolate.
+ CompileRun(script);
+ CHECK_EQ(false, i_isolate->IsFastArrayConstructorPrototypeChainIntact());
+ }
+ isolate1->Exit();
+ isolate1->Dispose();
+}
+
+
+TEST(VerifyArrayPrototypeGuarantees) {
+ // Break fast array hole handling by element changes.
+ BreakArrayGuarantees("[].__proto__[1] = 3;");
+ BreakArrayGuarantees("Object.prototype[3] = 'three';");
+ BreakArrayGuarantees("Array.prototype.push(1);");
+ BreakArrayGuarantees("Array.prototype.unshift(1);");
+ // Break fast array hole handling by changing length.
+ BreakArrayGuarantees("Array.prototype.length = 30;");
+ // Break fast array hole handling by prototype structure changes.
+ BreakArrayGuarantees("[].__proto__.__proto__ = { funny: true };");
+ // By sending elements to dictionary mode.
+ BreakArrayGuarantees("Object.freeze(Array.prototype);");
+ BreakArrayGuarantees("Object.freeze(Object.prototype);");
+ BreakArrayGuarantees(
+ "Object.defineProperty(Array.prototype, 0, {"
+ " get: function() { return 3; }});");
+ BreakArrayGuarantees(
+ "Object.defineProperty(Object.prototype, 0, {"
+ " get: function() { return 3; }});");
+}
+
+
TEST(RunTwoIsolatesOnSingleThread) {
// Run isolate 1.
- v8::Isolate* isolate1 = v8::Isolate::New();
+ v8::Isolate::CreateParams create_params;
+ create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
+ v8::Isolate* isolate1 = v8::Isolate::New(create_params);
isolate1->Enter();
v8::Persistent<v8::Context> context1;
{
}
// Run isolate 2.
- v8::Isolate* isolate2 = v8::Isolate::New();
+ v8::Isolate* isolate2 = v8::Isolate::New(create_params);
v8::Persistent<v8::Context> context2;
{
: Thread(Options("IsolateThread")), fib_limit_(fib_limit), result_(0) {}
void Run() {
- v8::Isolate* isolate = v8::Isolate::New();
+ v8::Isolate::CreateParams create_params;
+ create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
+ v8::Isolate* isolate = v8::Isolate::New(create_params);
result_ = CalcFibonacci(isolate, fib_limit_);
isolate->Dispose();
}
TEST(IsolateDifferentContexts) {
- v8::Isolate* isolate = v8::Isolate::New();
+ v8::Isolate::CreateParams create_params;
+ create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
+ v8::Isolate* isolate = v8::Isolate::New(create_params);
Local<v8::Context> context;
{
v8::Isolate::Scope isolate_scope(isolate);
void Run() {
v8::Isolate::CreateParams create_params;
+ create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
switch (testCase_) {
case SetResourceConstraints: {
create_params.constraints.set_max_semi_space_size(1);
"})()",
"ReferenceError: cell is not defined");
CompileRun("cell = \"new_second\";");
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
ExpectString("readCell()", "new_second");
ExpectString("readCell()", "new_second");
}
object1.SetWrapperClassId(42);
CHECK_EQ(42, object1.WrapperClassId());
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ CcTest::heap()->CollectAllGarbage();
+ CcTest::heap()->CollectAllGarbage();
v8::Persistent<v8::Object> object2(isolate, v8::Object::New(isolate));
CHECK_EQ(0, object2.WrapperClassId());
v8::Handle<v8::Value> value(CompileRun("re.property"));
CHECK_EQ(32, value->Int32Value());
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(context->GetIsolate());
re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone);
CHECK(re.IsEmpty());
CHECK(try_catch.HasCaught());
void CheckCodeGenerationDisallowed() {
- TryCatch try_catch;
+ TryCatch try_catch(CcTest::isolate());
Handle<Value> result = CompileRun("eval('42')");
CHECK(result.IsEmpty());
TEST(SetErrorMessageForCodeGenFromStrings) {
LocalContext context;
v8::HandleScope scope(context->GetIsolate());
- TryCatch try_catch;
+ TryCatch try_catch(context->GetIsolate());
Handle<String> message = v8_str("Message") ;
Handle<String> expected_message = v8_str("Uncaught EvalError: Message");
v8::FunctionTemplate::New(isolate, NonObjectThis);
Handle<Function> function = templ->GetFunction();
context->Global()->Set(v8_str("f"), function);
- TryCatch try_catch;
+ TryCatch try_catch(isolate);
CompileRun("f.call(2)");
}
int elements = CountLiveMapsInMapCache(CcTest::i_isolate()->context());
CHECK_LE(1, elements);
- CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+ CcTest::heap()->CollectAllGarbage();
CHECK_GT(elements, CountLiveMapsInMapCache(CcTest::i_isolate()->context()));
}
Function::New(isolate, MicrotaskExceptionOne));
isolate->EnqueueMicrotask(
Function::New(isolate, MicrotaskExceptionTwo));
- TryCatch try_catch;
+ TryCatch try_catch(isolate);
CompileRun("1+1;");
CHECK(!try_catch.HasCaught());
CHECK_EQ(1, CompileRun("exception1Calls")->Int32Value());
UNINITIALIZED_TEST(IsolateEmbedderData) {
CcTest::DisableAutomaticDispose();
- v8::Isolate* isolate = v8::Isolate::New();
+ v8::Isolate::CreateParams create_params;
+ create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
+ v8::Isolate* isolate = v8::Isolate::New(create_params);
isolate->Enter();
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
static void CheckInstanceCheckedAccessors(bool expects_callbacks) {
instance_checked_getter_count = 0;
instance_checked_setter_count = 0;
- TryCatch try_catch;
+ TryCatch try_catch(CcTest::isolate());
// Test path through generic runtime code.
CompileRun("obj.foo");
// Test that the original error message is not lost if there is a
// recursive call into Javascript is done in the finally block, e.g. to
// initialize an IC. (crbug.com/129171)
- TryCatch try_catch;
+ TryCatch try_catch(context->GetIsolate());
const char* trigger_ic =
"try { \n"
" throw new Error('test'); \n"
{
// Test that the original exception message is indeed overwritten if
// a new error is thrown in the finally block.
- TryCatch try_catch;
+ TryCatch try_catch(context->GetIsolate());
const char* throw_again =
"try { \n"
" throw new Error('test'); \n"
}
-THREADED_TEST(Regress3337) {
- LocalContext context;
- v8::Isolate* isolate = context->GetIsolate();
- v8::HandleScope scope(isolate);
- Local<v8::Object> o1 = Object::New(isolate);
- Local<v8::Object> o2 = Object::New(isolate);
- i::Handle<i::JSObject> io1 = v8::Utils::OpenHandle(*o1);
- i::Handle<i::JSObject> io2 = v8::Utils::OpenHandle(*o2);
- CHECK(io1->map() == io2->map());
- o1->SetIndexedPropertiesToExternalArrayData(
- NULL, v8::kExternalUint32Array, 0);
- o2->SetIndexedPropertiesToExternalArrayData(
- NULL, v8::kExternalUint32Array, 0);
- CHECK(io1->map() == io2->map());
-}
-
-
THREADED_TEST(Regress137496) {
i::FLAG_expose_gc = true;
LocalContext context;
// Compile a try-finally clause where the finally block causes a GC
// while there still is a message pending for external reporting.
- TryCatch try_catch;
+ TryCatch try_catch(context->GetIsolate());
try_catch.SetVerbose(true);
CompileRun("try { throw new Error(); } finally { gc(); }");
CHECK(try_catch.HasCaught());
struct sigaction action;
// Ensure that we'll enter waiting condition
- v8::base::OS::Sleep(100);
+ v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
// Setup signal handler
memset(&action, 0, sizeof(action));
kill(getpid(), SIGCHLD);
// Ensure that if wait has returned because of error
- v8::base::OS::Sleep(100);
+ v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
// Set value and signal semaphore
test_->sem_value_ = 1;
CHECK(CompileRun("JSON.stringify(other)").IsEmpty());
CHECK(CompileRun("JSON.stringify({ 'a' : other, 'b' : ['c'] })").IsEmpty());
CHECK(CompileRun("JSON.stringify([other, 'b', 'c'])").IsEmpty());
-
- v8::Handle<v8::Array> array = v8::Array::New(isolate, 2);
- array->Set(0, v8_str("a"));
- array->Set(1, v8_str("b"));
- context1->Global()->Set(v8_str("array"), array);
- ExpectString("JSON.stringify(array)", "[\"a\",\"b\"]");
- array->TurnOnAccessCheck();
- CHECK(CompileRun("JSON.stringify(array)").IsEmpty());
- CHECK(CompileRun("JSON.stringify([array])").IsEmpty());
- CHECK(CompileRun("JSON.stringify({'a' : array})").IsEmpty());
}
}
TEST(AccessCheckThrows) {
i::FLAG_allow_natives_syntax = true;
+ i::FLAG_turbo_try_catch = true;
v8::V8::Initialize();
v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckThrows);
v8::Isolate* isolate = CcTest::isolate();
context1->Global()->Set(v8_str("has_own_property"),
has_own_property_fun->GetFunction());
- { v8::TryCatch try_catch;
+ {
+ v8::TryCatch try_catch(isolate);
access_check_fail_thrown = false;
CompileRun("other.x;");
CHECK(access_check_fail_thrown);
isolate_, ShouldContinueCallback, v8::External::New(isolate_, this));
env_->Global()->Set(v8_str("ShouldContinue"), func);
- i::FLAG_turbo_osr = false; // TODO(titzer): interrupts in TF loops.
CompileRun("while (ShouldContinue()) { }");
}
};
isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
env_->Global()->Set(v8_str("Klass"), t->GetFunction());
- i::FLAG_turbo_osr = false; // TODO(titzer): interrupts in TF loops.
CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
}
};
isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
env_->Global()->Set(v8_str("Klass"), t->GetFunction());
- i::FLAG_turbo_osr = false; // TODO(titzer): interrupts in TF loops.
CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
}
};
v8::External::New(isolate_, this));
env_->Global()->Set(v8_str("Klass"), t->GetFunction());
- i::FLAG_turbo_osr = false; // TODO(titzer): interrupts in TF loops.
CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
}
env_->Global()->Set(v8_str("Klass"), t->GetFunction());
- i::FLAG_turbo_osr = false; // TODO(titzer): interrupts in TF loops.
CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
}
v8::External::New(isolate_, this)));
i::FLAG_allow_natives_syntax = true;
- i::FLAG_turbo_osr = false; // TODO(titzer): interrupts in TF loops.
CompileRun("function loopish(o) {"
" var pre = 10;"
" while (o.abs(1) > 0) {"
isolate_, ShouldContinueCallback, v8::External::New(isolate_, this));
env_->Global()->Set(v8_str("ShouldContinue"), func);
- i::FLAG_turbo_osr = false; // TODO(titzer): interrupts in TF loops.
CompileRun("while (ShouldContinue()) { }");
}
TEST(RequestMultipleInterrupts) { RequestMultipleInterrupts().RunTest(); }
+static bool interrupt_was_called = false;
+
+
+void SmallScriptsInterruptCallback(v8::Isolate* isolate, void* data) {
+ interrupt_was_called = true;
+}
+
+
+TEST(RequestInterruptSmallScripts) {
+ LocalContext env;
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope scope(isolate);
+
+ interrupt_was_called = false;
+ isolate->RequestInterrupt(&SmallScriptsInterruptCallback, NULL);
+ CompileRun("(function(x){return x;})(1);");
+ CHECK(interrupt_was_called);
+}
+
+
static Local<Value> function_new_expected_env;
static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
CHECK(function_new_expected_env->Equals(info.Data()));
"%%OptimizeFunctionOnNextCall(wrap_set_%d);\n"
"check(wrap_set());\n",
wrap_function.start(), key, key, key, key, key, key);
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
CompileRun(source.start());
DCHECK(!try_catch.HasCaught());
CHECK_EQ(9, count);
LocalContext context;
v8::Isolate* isolate = context->GetIsolate();
v8::HandleScope scope(isolate);
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
v8::Isolate::DisallowJavascriptExecutionScope throw_js(
isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
CompileRun("1+1");
v8::HandleScope scope(isolate);
V8::SetCaptureStackTraceForUncaughtExceptions(
true, 10, v8::StackTrace::kDetailed);
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
CompileRun("(function f(x) { f(x+1); })(0)");
CHECK(try_catch.HasCaught());
}
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
v8::HandleScope scope(isolate);
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
v8::ScriptCompiler::StreamedSource source(new TestSourceStream(chunks),
encoding);
CompileRun("function break_here() { }");
i::Handle<i::JSFunction> func = i::Handle<i::JSFunction>::cast(
v8::Utils::OpenHandle(*env->Global()->Get(v8_str("break_here"))));
+ EnableDebugger();
v8::internal::Debug* debug = CcTest::i_isolate()->debug();
int position = 0;
debug->SetBreakPoint(func, i::Handle<i::Object>(v8::internal::Smi::FromInt(1),
// Check that we got no cached data.
CHECK(source.GetCachedData() == NULL);
+ DisableDebugger();
}
// variable again.
const char* chunks[] = {"\"use strict\"; let x = 2;", NULL};
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
v8::ScriptCompiler::StreamedSource source(
new TestSourceStream(chunks),
v8::ScriptCompiler::StreamedSource::ONE_BYTE);
CHECK(!script.IsEmpty());
CHECK_EQ(false, try_catch.HasCaught());
- // Running the script exposes the error.
- v8::Handle<Value> result(script->Run());
- CHECK(result.IsEmpty());
- CHECK(try_catch.HasCaught());
- delete[] full_source;
+ // Running the script exposes the error.
+ v8::Handle<Value> result(script->Run());
+ CHECK(result.IsEmpty());
+ CHECK(try_catch.HasCaught());
+ delete[] full_source;
+}
+
+
+TEST(CodeCache) {
+ v8::Isolate::CreateParams create_params;
+ create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
+
+ const char* source = "Math.sqrt(4)";
+ const char* origin = "code cache test";
+ v8::ScriptCompiler::CachedData* cache;
+
+ v8::Isolate* isolate1 = v8::Isolate::New(create_params);
+ {
+ v8::Isolate::Scope iscope(isolate1);
+ v8::HandleScope scope(isolate1);
+ v8::Local<v8::Context> context = v8::Context::New(isolate1);
+ v8::Context::Scope cscope(context);
+ v8::Local<v8::String> source_string = v8_str(source);
+ v8::ScriptOrigin script_origin(v8_str(origin));
+ v8::ScriptCompiler::Source source(source_string, script_origin);
+ v8::ScriptCompiler::CompileOptions option =
+ v8::ScriptCompiler::kProduceCodeCache;
+ v8::ScriptCompiler::Compile(context, &source, option).ToLocalChecked();
+ int length = source.GetCachedData()->length;
+ uint8_t* cache_data = new uint8_t[length];
+ memcpy(cache_data, source.GetCachedData()->data, length);
+ cache = new v8::ScriptCompiler::CachedData(
+ cache_data, length, v8::ScriptCompiler::CachedData::BufferOwned);
+ }
+ isolate1->Dispose();
+
+ v8::Isolate* isolate2 = v8::Isolate::New(create_params);
+ {
+ v8::Isolate::Scope iscope(isolate2);
+ v8::HandleScope scope(isolate2);
+ v8::Local<v8::Context> context = v8::Context::New(isolate2);
+ v8::Context::Scope cscope(context);
+ v8::Local<v8::String> source_string = v8_str(source);
+ v8::ScriptOrigin script_origin(v8_str(origin));
+ v8::ScriptCompiler::Source source(source_string, script_origin, cache);
+ v8::ScriptCompiler::CompileOptions option =
+ v8::ScriptCompiler::kConsumeCodeCache;
+ v8::Local<v8::Script> script;
+ {
+ i::DisallowCompilation no_compile(
+ reinterpret_cast<i::Isolate*>(isolate2));
+ script = v8::ScriptCompiler::Compile(context, &source, option)
+ .ToLocalChecked();
+ }
+ CHECK_EQ(2, script->Run()->ToInt32(isolate2)->Int32Value());
+ }
+ isolate2->Dispose();
}
new RandomLengthOneByteResource(i::String::kMaxLength);
v8::Local<v8::String> str = v8::String::NewExternal(CcTest::isolate(), r);
CHECK(!str.IsEmpty());
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(CcTest::isolate());
v8::Local<v8::String> result = v8::String::Concat(str, str);
CHECK(result.IsEmpty());
CHECK(!try_catch.HasCaught());
env->Global()->Set(v8_str("prohibited"), obj_template->NewInstance());
{
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
CompileRun(
"function f() { %_GetPrototype(prohibited); }"
"%OptimizeFunctionOnNextCall(f);"
TEST(ClassPrototypeCreationContext) {
- i::FLAG_harmony_classes = true;
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope handle_scope(isolate);
LocalContext env;
if (buffer == NULL) return;
memset(buffer, 'A', buffer_size);
{
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
char* data = reinterpret_cast<char*>(buffer);
CHECK(v8::String::NewFromUtf8(isolate, data, v8::String::kNormalString,
length).IsEmpty());
CHECK(!try_catch.HasCaught());
}
{
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
uint8_t* data = reinterpret_cast<uint8_t*>(buffer);
CHECK(v8::String::NewFromOneByte(isolate, data, v8::String::kNormalString,
length).IsEmpty());
CHECK(!try_catch.HasCaught());
}
{
- v8::TryCatch try_catch;
+ v8::TryCatch try_catch(isolate);
uint16_t* data = reinterpret_cast<uint16_t*>(buffer);
CHECK(v8::String::NewFromTwoByte(isolate, data, v8::String::kNormalString,
length).IsEmpty());
USE(obj);
}
}
+
+
+static bool access_was_called = false;
+
+
+static bool AccessAlwaysAllowedWithFlag(Local<v8::Object> global,
+ Local<Value> name, v8::AccessType type,
+ Local<Value> data) {
+ access_was_called = true;
+ return true;
+}
+
+
+static bool AccessAlwaysBlockedWithFlag(Local<v8::Object> global,
+ Local<Value> name, v8::AccessType type,
+ Local<Value> data) {
+ access_was_called = true;
+ return false;
+}
+
+
+TEST(StrongModeAccessCheckAllowed) {
+ i::FLAG_strong_mode = true;
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope handle_scope(isolate);
+ v8::Handle<Value> value;
+ access_was_called = false;
+
+ v8::Handle<v8::ObjectTemplate> obj_template =
+ v8::ObjectTemplate::New(isolate);
+
+ obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
+ obj_template->SetAccessCheckCallbacks(AccessAlwaysAllowedWithFlag, NULL);
+
+ // Create an environment
+ v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
+ context0->Enter();
+ v8::Handle<v8::Object> global0 = context0->Global();
+ global0->Set(v8_str("object"), obj_template->NewInstance());
+ {
+ v8::TryCatch try_catch(isolate);
+ value = CompileRun("'use strong'; object.x");
+ CHECK(!try_catch.HasCaught());
+ CHECK(!access_was_called);
+ CHECK_EQ(42, value->Int32Value());
+ }
+ {
+ v8::TryCatch try_catch(isolate);
+ value = CompileRun("'use strong'; object.foo");
+ CHECK(try_catch.HasCaught());
+ CHECK(!access_was_called);
+ }
+ {
+ v8::TryCatch try_catch(isolate);
+ value = CompileRun("'use strong'; object[10]");
+ CHECK(try_catch.HasCaught());
+ CHECK(!access_was_called);
+ }
+
+ // Create an environment
+ v8::Local<Context> context1 = Context::New(isolate);
+ context1->Enter();
+ v8::Handle<v8::Object> global1 = context1->Global();
+ global1->Set(v8_str("object"), obj_template->NewInstance());
+ {
+ v8::TryCatch try_catch(isolate);
+ value = CompileRun("'use strong'; object.x");
+ CHECK(!try_catch.HasCaught());
+ CHECK(access_was_called);
+ CHECK_EQ(42, value->Int32Value());
+ }
+ access_was_called = false;
+ {
+ v8::TryCatch try_catch(isolate);
+ value = CompileRun("'use strong'; object.foo");
+ CHECK(try_catch.HasCaught());
+ CHECK(access_was_called);
+ }
+ access_was_called = false;
+ {
+ v8::TryCatch try_catch(isolate);
+ value = CompileRun("'use strong'; object[10]");
+ CHECK(try_catch.HasCaught());
+ CHECK(access_was_called);
+ }
+
+ context1->Exit();
+ context0->Exit();
+}
+
+
+TEST(StrongModeAccessCheckBlocked) {
+ i::FLAG_strong_mode = true;
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope handle_scope(isolate);
+ v8::Handle<Value> value;
+ access_was_called = false;
+
+ v8::Handle<v8::ObjectTemplate> obj_template =
+ v8::ObjectTemplate::New(isolate);
+
+ obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
+ obj_template->SetAccessCheckCallbacks(AccessAlwaysBlockedWithFlag, NULL);
+
+ // Create an environment
+ v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
+ context0->Enter();
+ v8::Handle<v8::Object> global0 = context0->Global();
+ global0->Set(v8_str("object"), obj_template->NewInstance());
+ {
+ v8::TryCatch try_catch(isolate);
+ value = CompileRun("'use strong'; object.x");
+ CHECK(!try_catch.HasCaught());
+ CHECK(!access_was_called);
+ CHECK_EQ(42, value->Int32Value());
+ }
+ {
+ v8::TryCatch try_catch(isolate);
+ value = CompileRun("'use strong'; object.foo");
+ CHECK(try_catch.HasCaught());
+ CHECK(!access_was_called);
+ }
+ {
+ v8::TryCatch try_catch(isolate);
+ value = CompileRun("'use strong'; object[10]");
+ CHECK(try_catch.HasCaught());
+ CHECK(!access_was_called);
+ }
+
+ // Create an environment
+ v8::Local<Context> context1 = Context::New(isolate);
+ context1->Enter();
+ v8::Handle<v8::Object> global1 = context1->Global();
+ global1->Set(v8_str("object"), obj_template->NewInstance());
+ {
+ v8::TryCatch try_catch(isolate);
+ value = CompileRun("'use strong'; object.x");
+ CHECK(try_catch.HasCaught());
+ CHECK(access_was_called);
+ }
+ access_was_called = false;
+ {
+ v8::TryCatch try_catch(isolate);
+ value = CompileRun("'use strong'; object.foo");
+ CHECK(try_catch.HasCaught());
+ CHECK(access_was_called);
+ }
+ access_was_called = false;
+ {
+ v8::TryCatch try_catch(isolate);
+ value = CompileRun("'use strong'; object[10]");
+ CHECK(try_catch.HasCaught());
+ CHECK(access_was_called);
+ }
+
+ context1->Exit();
+ context0->Exit();
+}
+
+
+TEST(StrongModeArityCallFromApi) {
+ i::FLAG_strong_mode = true;
+ LocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope scope(isolate);
+ Local<Function> fun;
+ {
+ v8::TryCatch try_catch(isolate);
+ fun = Local<Function>::Cast(CompileRun(
+ "function f(x) { 'use strong'; }"
+ "f"));
+
+ CHECK(!try_catch.HasCaught());
+ }
+
+ {
+ v8::TryCatch try_catch(isolate);
+ fun->Call(v8::Undefined(isolate), 0, nullptr);
+ CHECK(try_catch.HasCaught());
+ }
+
+ {
+ v8::TryCatch try_catch(isolate);
+ v8::Handle<Value> args[] = {v8_num(42)};
+ fun->Call(v8::Undefined(isolate), arraysize(args), args);
+ CHECK(!try_catch.HasCaught());
+ }
+
+ {
+ v8::TryCatch try_catch(isolate);
+ v8::Handle<Value> args[] = {v8_num(42), v8_num(555)};
+ fun->Call(v8::Undefined(isolate), arraysize(args), args);
+ CHECK(!try_catch.HasCaught());
+ }
+}
+
+
+TEST(StrongModeArityCallFromApi2) {
+ i::FLAG_strong_mode = true;
+ LocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope scope(isolate);
+ Local<Function> fun;
+ {
+ v8::TryCatch try_catch(isolate);
+ fun = Local<Function>::Cast(CompileRun(
+ "'use strong';"
+ "function f(x) {}"
+ "f"));
+
+ CHECK(!try_catch.HasCaught());
+ }
+
+ {
+ v8::TryCatch try_catch(isolate);
+ fun->Call(v8::Undefined(isolate), 0, nullptr);
+ CHECK(try_catch.HasCaught());
+ }
+
+ {
+ v8::TryCatch try_catch(isolate);
+ v8::Handle<Value> args[] = {v8_num(42)};
+ fun->Call(v8::Undefined(isolate), arraysize(args), args);
+ CHECK(!try_catch.HasCaught());
+ }
+
+ {
+ v8::TryCatch try_catch(isolate);
+ v8::Handle<Value> args[] = {v8_num(42), v8_num(555)};
+ fun->Call(v8::Undefined(isolate), arraysize(args), args);
+ CHECK(!try_catch.HasCaught());
+ }
+}
+
+
+TEST(StrongObjectDelete) {
+ i::FLAG_strong_mode = true;
+ LocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope scope(isolate);
+ Local<Object> obj;
+ {
+ v8::TryCatch try_catch;
+ obj = Local<Object>::Cast(CompileRun(
+ "'use strong';"
+ "({});"));
+ CHECK(!try_catch.HasCaught());
+ }
+ obj->ForceSet(v8_str("foo"), v8_num(1), v8::None);
+ obj->ForceSet(v8_str("2"), v8_num(1), v8::None);
+ CHECK(obj->HasOwnProperty(v8_str("foo")));
+ CHECK(obj->HasOwnProperty(v8_str("2")));
+ CHECK(!obj->Delete(v8_str("foo")));
+ CHECK(!obj->Delete(2));
+}
+
+
+static void ExtrasExportsTestRuntimeFunction(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
+ CHECK_EQ(3, args[0]->Int32Value());
+ args.GetReturnValue().Set(v8_num(7));
+}
+
+
+TEST(ExtrasExportsObject) {
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope handle_scope(isolate);
+ LocalContext env;
+
+ // standalone.gypi ensures we include the test-extra.js file, which should
+ // export the tested functions.
+ v8::Local<v8::Object> exports = env->GetExtrasExportsObject();
+
+ auto func =
+ exports->Get(v8_str("testExtraShouldReturnFive")).As<v8::Function>();
+ auto undefined = v8::Undefined(isolate);
+ auto result = func->Call(undefined, 0, {}).As<v8::Number>();
+ CHECK_EQ(5, result->Int32Value());
+
+ v8::Handle<v8::FunctionTemplate> runtimeFunction =
+ v8::FunctionTemplate::New(isolate, ExtrasExportsTestRuntimeFunction);
+ exports->Set(v8_str("runtime"), runtimeFunction->GetFunction());
+ func =
+ exports->Get(v8_str("testExtraShouldCallToRuntime")).As<v8::Function>();
+ result = func->Call(undefined, 0, {}).As<v8::Number>();
+ CHECK_EQ(7, result->Int32Value());
+}
+
+
+TEST(Map) {
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope handle_scope(isolate);
+ LocalContext env;
+
+ v8::Local<v8::Map> map = v8::Map::New(isolate);
+ CHECK(map->IsObject());
+ CHECK(map->IsMap());
+ CHECK(map->GetPrototype()->StrictEquals(CompileRun("Map.prototype")));
+ CHECK_EQ(0U, map->Size());
+
+ v8::Local<v8::Value> val = CompileRun("new Map([[1, 2], [3, 4]])");
+ CHECK(val->IsMap());
+ map = v8::Local<v8::Map>::Cast(val);
+ CHECK_EQ(2U, map->Size());
+
+ v8::Local<v8::Array> contents = map->AsArray();
+ CHECK_EQ(4U, contents->Length());
+ CHECK_EQ(1, contents->Get(0).As<v8::Int32>()->Value());
+ CHECK_EQ(2, contents->Get(1).As<v8::Int32>()->Value());
+ CHECK_EQ(3, contents->Get(2).As<v8::Int32>()->Value());
+ CHECK_EQ(4, contents->Get(3).As<v8::Int32>()->Value());
+
+ map = v8::Map::FromArray(env.local(), contents).ToLocalChecked();
+ CHECK_EQ(2U, map->Size());
+
+ CHECK(map->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust());
+ CHECK(map->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust());
+
+ CHECK(!map->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust());
+ CHECK(!map->Has(env.local(), map).FromJust());
+
+ CHECK_EQ(2, map->Get(env.local(), v8::Integer::New(isolate, 1))
+ .ToLocalChecked()
+ ->Int32Value());
+ CHECK_EQ(4, map->Get(env.local(), v8::Integer::New(isolate, 3))
+ .ToLocalChecked()
+ ->Int32Value());
+
+ CHECK(map->Get(env.local(), v8::Integer::New(isolate, 42))
+ .ToLocalChecked()
+ ->IsUndefined());
+
+ CHECK(!map->Set(env.local(), map, map).IsEmpty());
+ CHECK_EQ(3U, map->Size());
+ CHECK(map->Has(env.local(), map).FromJust());
+
+ CHECK(map->Delete(env.local(), map).FromJust());
+ CHECK_EQ(2U, map->Size());
+ CHECK(!map->Has(env.local(), map).FromJust());
+ CHECK(!map->Delete(env.local(), map).FromJust());
+
+ map->Clear();
+ CHECK_EQ(0U, map->Size());
+}
+
+
+TEST(MapFromArrayOddLength) {
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope handle_scope(isolate);
+ LocalContext env;
+ // Odd lengths result in a null MaybeLocal.
+ Local<v8::Array> contents = v8::Array::New(isolate, 41);
+ CHECK(v8::Map::FromArray(env.local(), contents).IsEmpty());
+}
+
+
+TEST(Set) {
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope handle_scope(isolate);
+ LocalContext env;
+
+ v8::Local<v8::Set> set = v8::Set::New(isolate);
+ CHECK(set->IsObject());
+ CHECK(set->IsSet());
+ CHECK(set->GetPrototype()->StrictEquals(CompileRun("Set.prototype")));
+ CHECK_EQ(0U, set->Size());
+
+ v8::Local<v8::Value> val = CompileRun("new Set([1, 2])");
+ CHECK(val->IsSet());
+ set = v8::Local<v8::Set>::Cast(val);
+ CHECK_EQ(2U, set->Size());
+
+ v8::Local<v8::Array> keys = set->AsArray();
+ CHECK_EQ(2U, keys->Length());
+ CHECK_EQ(1, keys->Get(0).As<v8::Int32>()->Value());
+ CHECK_EQ(2, keys->Get(1).As<v8::Int32>()->Value());
+
+ set = v8::Set::FromArray(env.local(), keys).ToLocalChecked();
+ CHECK_EQ(2U, set->Size());
+
+ CHECK(set->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust());
+ CHECK(set->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust());
+
+ CHECK(!set->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust());
+ CHECK(!set->Has(env.local(), set).FromJust());
+
+ CHECK(!set->Add(env.local(), set).IsEmpty());
+ CHECK_EQ(3U, set->Size());
+ CHECK(set->Has(env.local(), set).FromJust());
+
+ CHECK(set->Delete(env.local(), set).FromJust());
+ CHECK_EQ(2U, set->Size());
+ CHECK(!set->Has(env.local(), set).FromJust());
+ CHECK(!set->Delete(env.local(), set).FromJust());
+
+ set->Clear();
+ CHECK_EQ(0U, set->Size());
+}
+
+
+TEST(CompatibleReceiverCheckOnCachedICHandler) {
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope scope(isolate);
+ v8::Local<v8::FunctionTemplate> parent = FunctionTemplate::New(isolate);
+ v8::Local<v8::Signature> signature = v8::Signature::New(isolate, parent);
+ auto returns_42 =
+ v8::FunctionTemplate::New(isolate, Returns42, Local<Value>(), signature);
+ parent->PrototypeTemplate()->SetAccessorProperty(v8_str("age"), returns_42);
+ v8::Local<v8::FunctionTemplate> child = v8::FunctionTemplate::New(isolate);
+ child->Inherit(parent);
+ LocalContext env;
+ env->Global()->Set(v8_str("Child"), child->GetFunction());
+
+ // Make sure there's a compiled stub for "Child.prototype.age" in the cache.
+ CompileRun(
+ "var real = new Child();\n"
+ "for (var i = 0; i < 3; ++i) {\n"
+ " real.age;\n"
+ "}\n");
+
+ // Check that the cached stub is never used.
+ ExpectInt32(
+ "var fake = Object.create(Child.prototype);\n"
+ "var result = 0;\n"
+ "function test(d) {\n"
+ " if (d == 3) return;\n"
+ " try {\n"
+ " fake.age;\n"
+ " result = 1;\n"
+ " } catch (e) {\n"
+ " }\n"
+ " test(d+1);\n"
+ "}\n"
+ "test(0);\n"
+ "result;\n",
+ 0);
+}
+
+
+static int nb_uncaught_exception_callback_calls = 0;
+
+
+bool NoAbortOnUncaughtException(v8::Isolate* isolate) {
+ ++nb_uncaught_exception_callback_calls;
+ return false;
+}
+
+
+TEST(AbortOnUncaughtExceptionNoAbort) {
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope handle_scope(isolate);
+ v8::Handle<v8::ObjectTemplate> global_template =
+ v8::ObjectTemplate::New(isolate);
+ LocalContext env(NULL, global_template);
+
+ i::FLAG_abort_on_uncaught_exception = true;
+ isolate->SetAbortOnUncaughtExceptionCallback(NoAbortOnUncaughtException);
+
+ CompileRun("function boom() { throw new Error(\"boom\") }");
+
+ v8::Local<v8::Object> global_object = env->Global();
+ v8::Local<v8::Function> foo =
+ v8::Local<v8::Function>::Cast(global_object->Get(v8_str("boom")));
+
+ foo->Call(global_object, 0, NULL);
+
+ CHECK_EQ(1, nb_uncaught_exception_callback_calls);
+}