#include <string>
#include <map>
-#include "v8.h"
+#include "src/v8.h"
#if V8_OS_POSIX
#include <unistd.h> // NOLINT
#endif
-#include "api.h"
-#include "arguments.h"
-#include "cctest.h"
-#include "compilation-cache.h"
-#include "cpu-profiler.h"
-#include "execution.h"
-#include "isolate.h"
-#include "objects.h"
-#include "parser.h"
-#include "platform.h"
-#include "snapshot.h"
-#include "unicode-inl.h"
-#include "utils.h"
-#include "vm-state.h"
-#include "../include/v8-util.h"
+#include "include/v8-util.h"
+#include "src/api.h"
+#include "src/arguments.h"
+#include "src/compilation-cache.h"
+#include "src/cpu-profiler.h"
+#include "src/execution.h"
+#include "src/isolate.h"
+#include "src/objects.h"
+#include "src/parser.h"
+#include "src/platform.h"
+#include "src/snapshot.h"
+#include "src/unicode-inl.h"
+#include "src/utils.h"
+#include "src/vm-state.h"
+#include "test/cctest/cctest.h"
static const bool kLogThreading = false;
v8::String::NewFromUtf8(env->GetIsolate(), "my_profile1");
v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
- cpu_profiler->StartCpuProfiling(profile_name);
+ cpu_profiler->StartProfiling(profile_name);
(*test)();
reinterpret_cast<i::CpuProfiler*>(cpu_profiler)->DeleteAllProfiles();
}
-static void ExpectString(const char* code, const char* expected) {
- Local<Value> result = CompileRun(code);
- CHECK(result->IsString());
- String::Utf8Value utf8(result);
- CHECK_EQ(expected, *utf8);
-}
-
-
-static void ExpectInt32(const char* code, int expected) {
- Local<Value> result = CompileRun(code);
- CHECK(result->IsInt32());
- CHECK_EQ(expected, result->Int32Value());
-}
-
-
-static void ExpectBoolean(const char* code, bool expected) {
- Local<Value> result = CompileRun(code);
- CHECK(result->IsBoolean());
- CHECK_EQ(expected, result->BooleanValue());
-}
-
-
-static void ExpectTrue(const char* code) {
- ExpectBoolean(code, true);
-}
-
-
-static void ExpectFalse(const char* code) {
- ExpectBoolean(code, false);
-}
-
-
-static void ExpectObject(const char* code, Local<Value> expected) {
- Local<Value> result = CompileRun(code);
- CHECK(result->Equals(expected));
-}
-
-
-static void ExpectUndefined(const char* code) {
- Local<Value> result = CompileRun(code);
- CHECK(result->IsUndefined());
-}
-
-
static int signature_callback_count;
static Local<Value> signature_expected_receiver;
static void IncrementingSignatureCallback(
static void TestSignature(const char* loop_js, Local<Value> receiver) {
i::ScopedVector<char> source(200);
- i::OS::SNPrintF(source,
- "for (var i = 0; i < 10; i++) {"
- " %s"
- "}",
- loop_js);
+ i::SNPrintF(source,
+ "for (var i = 0; i < 10; i++) {"
+ " %s"
+ "}",
+ loop_js);
signature_callback_count = 0;
signature_expected_receiver = receiver;
bool expected_to_throw = receiver.IsEmpty();
unsigned bad_signature_start_offset = 2;
for (unsigned i = 0; i < ARRAY_SIZE(test_objects); i++) {
i::ScopedVector<char> source(200);
- i::OS::SNPrintF(
+ i::SNPrintF(
source, "var test_object = %s; test_object", test_objects[i]);
Local<Value> test_object = CompileRun(source.start());
TestSignature("test_object.prop();", test_object);
}
-static uint16_t* AsciiToTwoByteString(const char* source) {
- int array_length = i::StrLength(source) + 1;
- uint16_t* converted = i::NewArray<uint16_t>(array_length);
- for (int i = 0; i < array_length; i++) converted[i] = source[i];
- return converted;
-}
-
-
class TestResource: public String::ExternalStringResource {
public:
TestResource(uint16_t* data, int* counter = NULL, bool owning_data = true)
void SimpleAccessorGetter(Local<String> name,
const v8::PropertyCallbackInfo<v8::Value>& info) {
- Handle<Object> self = info.This();
+ Handle<Object> self = Handle<Object>::Cast(info.This());
info.GetReturnValue().Set(
self->Get(String::Concat(v8_str("accessor_"), name)));
}
void SimpleAccessorSetter(Local<String> name, Local<Value> value,
const v8::PropertyCallbackInfo<void>& info) {
- Handle<Object> self = info.This();
+ Handle<Object> self = Handle<Object>::Cast(info.This());
self->Set(String::Concat(v8_str("accessor_"), name), value);
}
for (i = 0; name_str[i] && prefix[i]; ++i) {
if (name_str[i] != prefix[i]) return;
}
- Handle<Object> self = info.This();
+ Handle<Object> self = Handle<Object>::Cast(info.This());
info.GetReturnValue().Set(self->GetHiddenValue(v8_str(name_str + i)));
}
if (!prefix[i]) return;
if (value->IsInt32() && value->Int32Value() < 10000) {
- Handle<Object> self = info.This();
+ Handle<Object> self = Handle<Object>::Cast(info.This());
self->SetHiddenValue(name, value);
info.GetReturnValue().Set(value);
}
}
+THREADED_TEST(ExecutableAccessorIsPreservedOnAttributeChange) {
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope scope(isolate);
+ LocalContext env;
+ v8::Local<v8::Value> res = CompileRun("var a = []; a;");
+ i::Handle<i::JSObject> a(v8::Utils::OpenHandle(v8::Object::Cast(*res)));
+ CHECK(a->map()->instance_descriptors()->IsFixedArray());
+ CHECK_GT(i::FixedArray::cast(a->map()->instance_descriptors())->length(), 0);
+ CompileRun("Object.defineProperty(a, 'length', { writable: false });");
+ CHECK_EQ(i::FixedArray::cast(a->map()->instance_descriptors())->length(), 0);
+ // But we should still have an ExecutableAccessorInfo.
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+ i::LookupResult lookup(i_isolate);
+ i::Handle<i::String> name(v8::Utils::OpenHandle(*v8_str("length")));
+ a->LookupOwnRealNamedProperty(name, &lookup);
+ CHECK(lookup.IsPropertyCallbacks());
+ i::Handle<i::Object> callback(lookup.GetCallbackObject(), i_isolate);
+ CHECK(callback->IsExecutableAccessorInfo());
+}
+
+
THREADED_TEST(EmptyInterceptorBreakTransitions) {
v8::HandleScope scope(CcTest::isolate());
Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
}
+THREADED_TEST(GlobalProxyIdentityHash) {
+ LocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope scope(isolate);
+ Handle<Object> global_proxy = env->Global();
+ int hash1 = global_proxy->GetIdentityHash();
+ // Hash should be retained after being detached.
+ env->DetachGlobal();
+ int hash2 = global_proxy->GetIdentityHash();
+ CHECK_EQ(hash1, hash2);
+ {
+ // Re-attach global proxy to a new context, hash should stay the same.
+ LocalContext env2(NULL, Handle<ObjectTemplate>(), global_proxy);
+ int hash3 = global_proxy->GetIdentityHash();
+ CHECK_EQ(hash1, hash3);
+ }
+}
+
+
THREADED_TEST(SymbolProperties) {
i::FLAG_harmony_symbols = true;
static void CheckIsTypedArrayVarNeutered(const char* name) {
i::ScopedVector<char> source(1024);
- i::OS::SNPrintF(source,
+ i::SNPrintF(source,
"%s.byteLength == 0 && %s.byteOffset == 0 && %s.length == 0",
name, name, name);
CHECK(CompileRun(source.start())->IsTrue());
template<typename K, typename V>
class WeakStdMapTraits : public v8::StdMapTraits<K, V> {
public:
- typedef typename v8::DefaultPersistentValueMapTraits<K, V>::Impl Impl;
- static const bool kIsWeak = true;
+ typedef typename v8::PersistentValueMap<K, V, WeakStdMapTraits<K, V> >
+ MapType;
+ static const v8::PersistentContainerCallbackType kCallbackType = v8::kWeak;
struct WeakCallbackDataType {
- Impl* impl;
+ MapType* map;
K key;
};
static WeakCallbackDataType* WeakCallbackParameter(
- Impl* impl, const K& key, Local<V> value) {
+ MapType* map, const K& key, Local<V> value) {
WeakCallbackDataType* data = new WeakCallbackDataType;
- data->impl = impl;
+ data->map = map;
data->key = key;
return data;
}
- static Impl* ImplFromWeakCallbackData(
+ static MapType* MapFromWeakCallbackData(
const v8::WeakCallbackData<V, WeakCallbackDataType>& data) {
- return data.GetParameter()->impl;
+ return data.GetParameter()->map;
}
static K KeyFromWeakCallbackData(
const v8::WeakCallbackData<V, WeakCallbackDataType>& data) {
delete data;
}
static void Dispose(v8::Isolate* isolate, v8::UniquePersistent<V> value,
- Impl* impl, K key) { }
+ K key) { }
};
CHECK_EQ(1, static_cast<int>(map.Size()));
obj = map.Get(7);
CHECK_EQ(expected, obj);
+ {
+ typename Map::PersistentValueReference ref = map.GetReference(7);
+ CHECK_EQ(expected, ref.NewLocal(isolate));
+ }
v8::UniquePersistent<v8::Object> removed = map.Remove(7);
CHECK_EQ(0, static_cast<int>(map.Size()));
CHECK(expected == removed);
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::UniquePersistent<v8::Object>(isolate, expected2), &ref);
+ CHECK_EQ(1, static_cast<int>(map.Size()));
+ CHECK(expected == removed);
+ CHECK_EQ(expected2, ref.NewLocal(isolate));
+ }
}
CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
if (map.IsWeak()) {
TestPersistentValueMap<v8::StdPersistentValueMap<int, v8::Object> >();
// Custom traits with weak callbacks:
- typedef v8::StdPersistentValueMap<int, v8::Object,
+ typedef v8::PersistentValueMap<int, v8::Object,
WeakStdMapTraits<int, v8::Object> > WeakPersistentValueMap;
TestPersistentValueMap<WeakPersistentValueMap>();
}
+TEST(PersistentValueVector) {
+ LocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::internal::GlobalHandles* global_handles =
+ reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
+ int handle_count = global_handles->global_handles_count();
+ HandleScope scope(isolate);
+
+ v8::PersistentValueVector<v8::Object> vector(isolate);
+
+ Local<v8::Object> obj1 = v8::Object::New(isolate);
+ Local<v8::Object> obj2 = v8::Object::New(isolate);
+ v8::UniquePersistent<v8::Object> obj3(isolate, v8::Object::New(isolate));
+
+ CHECK(vector.IsEmpty());
+ CHECK_EQ(0, static_cast<int>(vector.Size()));
+
+ vector.ReserveCapacity(3);
+ CHECK(vector.IsEmpty());
+
+ vector.Append(obj1);
+ vector.Append(obj2);
+ vector.Append(obj1);
+ vector.Append(obj3.Pass());
+ vector.Append(obj1);
+
+ CHECK(!vector.IsEmpty());
+ CHECK_EQ(5, static_cast<int>(vector.Size()));
+ CHECK(obj3.IsEmpty());
+ CHECK_EQ(obj1, vector.Get(0));
+ CHECK_EQ(obj1, vector.Get(2));
+ CHECK_EQ(obj1, vector.Get(4));
+ CHECK_EQ(obj2, vector.Get(1));
+
+ CHECK_EQ(5 + handle_count, global_handles->global_handles_count());
+
+ vector.Clear();
+ CHECK(vector.IsEmpty());
+ CHECK_EQ(0, static_cast<int>(vector.Size()));
+ CHECK_EQ(handle_count, global_handles->global_handles_count());
+}
+
+
THREADED_TEST(GlobalHandleUpcast) {
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope scope(isolate);
v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
iso)->heap();
- heap->CollectGarbage(i::NEW_SPACE);
+ heap->CollectAllGarbage(i::Heap::kNoGCFlags);
// All objects should be alive.
CHECK_EQ(0, counter.NumberOfWeakCalls());
v8_str("x"), Local<Value>::New(iso, g1s1.handle));
}
- heap->CollectGarbage(i::NEW_SPACE);
+ heap->CollectAllGarbage(i::Heap::kNoGCFlags);
// All objects should be gone. 7 global handles in total.
CHECK_EQ(7, counter.NumberOfWeakCalls());
}
-template <typename T> static void USE(T) { }
-
-
// The point of this test is type checking. We run it only so compilers
// don't complain about an unused function.
TEST(PersistentHandles) {
source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
v8::HandleScope handle_scope(CcTest::isolate());
i::ScopedVector<char> extension_name(32);
- i::OS::SNPrintF(extension_name, "ext #%d", source_len);
+ i::SNPrintF(extension_name, "ext #%d", source_len);
v8::RegisterExtension(new Extension(extension_name.start(),
kEmbeddedExtensionSource, 0, 0,
source_len));
int len = str->Utf8Length();
if (len < 0) {
i::Handle<i::String> istr(v8::Utils::OpenHandle(*str));
- i::FlattenString(istr);
+ i::String::Flatten(istr);
len = str->Utf8Length();
}
return len;
static void Utf16Helper(
- LocalContext& context,
+ LocalContext& context, // NOLINT
const char* name,
const char* lengths_name,
int len) {
static void WriteUtf8Helper(
- LocalContext& context,
+ LocalContext& context, // NOLINT
const char* name,
const char* lengths_name,
int len) {
static void YSetter(Local<String> name,
Local<Value> value,
const v8::PropertyCallbackInfo<void>& info) {
- if (info.This()->Has(name)) {
- info.This()->Delete(name);
- }
- info.This()->Set(name, value);
+ Local<Object> this_obj = Local<Object>::Cast(info.This());
+ if (this_obj->Has(name)) this_obj->Delete(name);
+ this_obj->Set(name, value);
}
}
-// For use within the TestSecurityHandler() test.
-static bool g_security_callback_result = false;
-static bool NamedSecurityTestCallback(Local<v8::Object> global,
- Local<Value> name,
- v8::AccessType type,
- Local<Value> data) {
- // Always allow read access.
- if (type == v8::ACCESS_GET)
- return true;
-
- // Sometimes allow other access.
- return g_security_callback_result;
-}
-
-
-static bool IndexedSecurityTestCallback(Local<v8::Object> global,
- uint32_t key,
- v8::AccessType type,
- Local<Value> data) {
- // Always allow read access.
- if (type == v8::ACCESS_GET)
- return true;
-
- // Sometimes allow other access.
- return g_security_callback_result;
-}
-
-
static int trouble_nesting = 0;
static void TroubleCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
ApiTestFuzzer::Fuzz();
}
+void CEvaluate(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ v8::HandleScope scope(args.GetIsolate());
+ CompileRun(args[0]->ToString());
+}
+
+
+TEST(TryCatchFinallyStoresMessageUsingTryCatchHandler) {
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope scope(isolate);
+ Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
+ templ->Set(v8_str("CEvaluate"),
+ v8::FunctionTemplate::New(isolate, CEvaluate));
+ LocalContext context(0, templ);
+ v8::TryCatch try_catch;
+ CompileRun("try {"
+ " CEvaluate('throw 1;');"
+ "} finally {"
+ "}");
+ CHECK(try_catch.HasCaught());
+ CHECK(!try_catch.Message().IsEmpty());
+ String::Utf8Value exception_value(try_catch.Exception());
+ CHECK_EQ(*exception_value, "1");
+ try_catch.Reset();
+ CompileRun("try {"
+ " CEvaluate('throw 1;');"
+ "} finally {"
+ " throw 2;"
+ "}");
+ CHECK(try_catch.HasCaught());
+ CHECK(!try_catch.Message().IsEmpty());
+ String::Utf8Value finally_exception_value(try_catch.Exception());
+ CHECK_EQ(*finally_exception_value, "2");
+}
+
+
+// For use within the TestSecurityHandler() test.
+static bool g_security_callback_result = false;
+static bool NamedSecurityTestCallback(Local<v8::Object> global,
+ Local<Value> name,
+ v8::AccessType type,
+ Local<Value> data) {
+ printf("a\n");
+ // Always allow read access.
+ if (type == v8::ACCESS_GET)
+ return true;
+
+ // Sometimes allow other access.
+ return g_security_callback_result;
+}
+
+
+static bool IndexedSecurityTestCallback(Local<v8::Object> global,
+ uint32_t key,
+ v8::AccessType type,
+ Local<Value> data) {
+ printf("b\n");
+ // Always allow read access.
+ if (type == v8::ACCESS_GET)
+ return true;
+
+ // Sometimes allow other access.
+ return g_security_callback_result;
+}
+
+
// SecurityHandler can't be run twice
TEST(SecurityHandler) {
v8::Isolate* isolate = CcTest::isolate();
}
+static bool named_security_check_with_gc_called;
+
+static bool NamedSecurityCallbackWithGC(Local<v8::Object> global,
+ Local<Value> name,
+ v8::AccessType type,
+ Local<Value> data) {
+ CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ named_security_check_with_gc_called = true;
+ return true;
+}
+
+
+static bool indexed_security_check_with_gc_called;
+
+static bool IndexedSecurityTestCallbackWithGC(Local<v8::Object> global,
+ uint32_t key,
+ v8::AccessType type,
+ Local<Value> data) {
+ CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ indexed_security_check_with_gc_called = true;
+ return true;
+}
+
+
+TEST(SecurityTestGCAllowed) {
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope handle_scope(isolate);
+ v8::Handle<v8::ObjectTemplate> object_template =
+ v8::ObjectTemplate::New(isolate);
+ object_template->SetAccessCheckCallbacks(NamedSecurityCallbackWithGC,
+ IndexedSecurityTestCallbackWithGC);
+
+ v8::Handle<Context> context = Context::New(isolate);
+ v8::Context::Scope context_scope(context);
+
+ context->Global()->Set(v8_str("obj"), object_template->NewInstance());
+
+ named_security_check_with_gc_called = false;
+ CompileRun("obj.foo = new String(1001);");
+ CHECK(named_security_check_with_gc_called);
+
+ indexed_security_check_with_gc_called = false;
+ CompileRun("obj[0] = new String(1002);");
+ CHECK(indexed_security_check_with_gc_called);
+
+ named_security_check_with_gc_called = false;
+ CHECK(CompileRun("obj.foo")->ToString()->Equals(v8_str("1001")));
+ CHECK(named_security_check_with_gc_called);
+
+ indexed_security_check_with_gc_called = false;
+ CHECK(CompileRun("obj[0]")->ToString()->Equals(v8_str("1002")));
+ CHECK(indexed_security_check_with_gc_called);
+}
+
+
THREADED_TEST(CrossDomainDelete) {
LocalContext env1;
v8::HandleScope handle_scope(env1->GetIsolate());
CHECK_EQ(42, g_echo_value_1);
v8::Handle<Value> value;
- // We follow Safari in ignoring assignments to host object accessors.
CompileRun("Object.defineProperty(other, 'accessible_prop', {value: -1})");
value = CompileRun("other.accessible_prop == 42");
CHECK(value->IsTrue());
// Getting property names of an object with a prototype chain that
-// triggers dictionary elements in GetLocalPropertyNames() shouldn't
+// triggers dictionary elements in GetOwnPropertyNames() shouldn't
// crash the runtime.
THREADED_TEST(Regress91517) {
i::FLAG_allow_natives_syntax = true;
// Force dictionary-based properties.
i::ScopedVector<char> name_buf(1024);
for (int i = 1; i <= 1000; i++) {
- i::OS::SNPrintF(name_buf, "sdf%d", i);
+ i::SNPrintF(name_buf, "sdf%d", i);
t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2));
}
CHECK(o3->SetPrototype(o2));
CHECK(o2->SetPrototype(o1));
- // Call the runtime version of GetLocalPropertyNames() on the natively
+ // Call the runtime version of GetOwnPropertyNames() on the natively
// created object through JavaScript.
context->Global()->Set(v8_str("obj"), o4);
// PROPERTY_ATTRIBUTES_NONE = 0
- CompileRun("var names = %GetLocalPropertyNames(obj, 0);");
+ CompileRun("var names = %GetOwnPropertyNames(obj, 0);");
ExpectInt32("names.length", 1006);
ExpectTrue("names.indexOf(\"baz\") >= 0");
o1->SetHiddenValue(
v8_str("h1"), v8::Integer::New(context->GetIsolate(), 2013));
- // Call the runtime version of GetLocalPropertyNames() on
+ // Call the runtime version of GetOwnPropertyNames() on
// the natively created object through JavaScript.
context->Global()->Set(v8_str("obj"), o2);
context->Global()->Set(v8_str("sym"), sym);
// PROPERTY_ATTRIBUTES_NONE = 0
- CompileRun("var names = %GetLocalPropertyNames(obj, 0);");
+ CompileRun("var names = %GetOwnPropertyNames(obj, 0);");
ExpectInt32("names.length", 7);
ExpectTrue("names.indexOf(\"foo\") >= 0");
static void SetOnThis(Local<String> name,
Local<Value> value,
const v8::PropertyCallbackInfo<void>& info) {
- info.This()->ForceSet(name, value);
+ Local<Object>::Cast(info.This())->ForceSet(name, value);
}
static int GetGlobalObjectsCount() {
- CcTest::heap()->EnsureHeapIsIterable();
int count = 0;
i::HeapIterator it(CcTest::heap());
for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
UNINITIALIZED_TEST(SetJitCodeEventHandler) {
i::FLAG_stress_compaction = true;
i::FLAG_incremental_marking = false;
+ if (i::FLAG_never_compact) return;
const char* script =
"function bar() {"
" var sum = 0;"
}
-// This test verifies that pre-compilation (aka preparsing) can be called
-// without initializing the whole VM. Thus we cannot run this test in a
-// multi-threaded setup.
-TEST(PreCompile) {
- // TODO(155): This test would break without the initialization of V8. This is
- // a workaround for now to make this test not fail.
- v8::V8::Initialize();
- v8::Isolate* isolate = CcTest::isolate();
- HandleScope handle_scope(isolate);
- const char* script = "function foo(a) { return a+1; }";
- v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
- isolate, script, v8::String::kNormalString, i::StrLength(script)));
- CHECK_NE(sd->Length(), 0);
- CHECK_NE(sd->Data(), NULL);
- CHECK(!sd->HasError());
- delete sd;
-}
-
-
-TEST(PreCompileWithError) {
- v8::V8::Initialize();
- v8::Isolate* isolate = CcTest::isolate();
- HandleScope handle_scope(isolate);
- const char* script = "function foo(a) { return 1 * * 2; }";
- v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
- isolate, script, v8::String::kNormalString, i::StrLength(script)));
- CHECK(sd->HasError());
- delete sd;
-}
-
-
-TEST(Regress31661) {
- v8::V8::Initialize();
- v8::Isolate* isolate = CcTest::isolate();
- HandleScope handle_scope(isolate);
- const char* script = " The Definintive Guide";
- v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
- isolate, script, v8::String::kNormalString, i::StrLength(script)));
- CHECK(sd->HasError());
- delete sd;
-}
-
-
// Tests that ScriptData can be serialized and deserialized.
TEST(PreCompileSerialization) {
v8::V8::Initialize();
- v8::Isolate* isolate = CcTest::isolate();
+ LocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
HandleScope handle_scope(isolate);
- const char* script = "function foo(a) { return a+1; }";
- v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
- isolate, script, v8::String::kNormalString, i::StrLength(script)));
+ i::FLAG_min_preparse_length = 0;
+ const char* script = "function foo(a) { return a+1; }";
+ v8::ScriptCompiler::Source source(v8_str(script));
+ v8::ScriptCompiler::Compile(isolate, &source,
+ v8::ScriptCompiler::kProduceDataToCache);
// Serialize.
- int serialized_data_length = sd->Length();
- char* serialized_data = i::NewArray<char>(serialized_data_length);
- i::OS::MemCopy(serialized_data, sd->Data(), serialized_data_length);
+ const v8::ScriptCompiler::CachedData* cd = source.GetCachedData();
+ char* serialized_data = i::NewArray<char>(cd->length);
+ i::MemCopy(serialized_data, cd->data, cd->length);
// Deserialize.
- v8::ScriptData* deserialized_sd =
- v8::ScriptData::New(serialized_data, serialized_data_length);
+ i::ScriptData* deserialized = i::ScriptData::New(serialized_data, cd->length);
// Verify that the original is the same as the deserialized.
- CHECK_EQ(sd->Length(), deserialized_sd->Length());
- CHECK_EQ(0, memcmp(sd->Data(), deserialized_sd->Data(), sd->Length()));
- CHECK_EQ(sd->HasError(), deserialized_sd->HasError());
+ CHECK_EQ(cd->length, deserialized->Length());
+ CHECK_EQ(0, memcmp(cd->data, deserialized->Data(), cd->length));
- delete sd;
- delete deserialized_sd;
+ delete deserialized;
i::DeleteArray(serialized_data);
}
v8::V8::Initialize();
const char* data = "DONT CARE";
int invalid_size = 3;
- v8::ScriptData* sd = v8::ScriptData::New(data, invalid_size);
-
- CHECK_EQ(0, sd->Length());
-
- delete sd;
+ i::ScriptData* sd = i::ScriptData::New(data, invalid_size);
+ CHECK_EQ(NULL, sd);
}
-// Attempts to deserialize bad data.
-TEST(PreCompileInvalidPreparseDataError) {
+TEST(CompileWithInvalidCachedData) {
v8::V8::Initialize();
v8::Isolate* isolate = CcTest::isolate();
LocalContext context;
v8::HandleScope scope(context->GetIsolate());
+ i::FLAG_min_preparse_length = 0;
const char* script = "function foo(){ return 5;}\n"
"function bar(){ return 6 + 7;} foo();";
- v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
- isolate, script, v8::String::kNormalString, i::StrLength(script)));
+ v8::ScriptCompiler::Source source(v8_str(script));
+ v8::ScriptCompiler::Compile(isolate, &source,
+ v8::ScriptCompiler::kProduceDataToCache);
+ // source owns its cached data. Create a ScriptData based on it. The user
+ // never needs to create ScriptDatas any more; we only need it here because we
+ // want to modify the data before passing it back.
+ const v8::ScriptCompiler::CachedData* cd = source.GetCachedData();
+ // ScriptData does not take ownership of the buffers passed to it.
+ i::ScriptData* sd =
+ i::ScriptData::New(reinterpret_cast<const char*>(cd->data), cd->length);
CHECK(!sd->HasError());
- // ScriptDataImpl private implementation details
+ // ScriptData private implementation details
const int kHeaderSize = i::PreparseDataConstants::kHeaderSize;
const int kFunctionEntrySize = i::FunctionEntry::kSize;
const int kFunctionEntryStartOffset = 0;
sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryEndOffset] = 0;
v8::TryCatch try_catch;
- v8::ScriptCompiler::Source script_source(
- String::NewFromUtf8(isolate, script),
+ // Make the script slightly different so that we don't hit the compilation
+ // cache. Don't change the lenghts of tokens.
+ const char* script2 = "function foo(){ return 6;}\n"
+ "function bar(){ return 6 + 7;} foo();";
+ v8::ScriptCompiler::Source source2(
+ v8_str(script2),
+ // CachedData doesn't take ownership of the buffers, Source takes
+ // ownership of CachedData.
new v8::ScriptCompiler::CachedData(
reinterpret_cast<const uint8_t*>(sd->Data()), sd->Length()));
Local<v8::UnboundScript> compiled_script =
- v8::ScriptCompiler::CompileUnbound(isolate, &script_source);
+ v8::ScriptCompiler::CompileUnbound(isolate, &source2);
CHECK(try_catch.HasCaught());
- String::Utf8Value exception_value(try_catch.Message()->Get());
- CHECK_EQ("Uncaught SyntaxError: Invalid preparser data for function bar",
- *exception_value);
+ {
+ String::Utf8Value exception_value(try_catch.Message()->Get());
+ CHECK_EQ("Uncaught SyntaxError: Invalid cached data for function bar",
+ *exception_value);
+ }
try_catch.Reset();
delete sd;
- // Overwrite function bar's start position with 200. The function entry
- // will not be found when searching for it by position and we should fall
- // back on eager compilation.
- sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
- isolate, script, v8::String::kNormalString, i::StrLength(script)));
+ // Overwrite function bar's start position with 200. The function entry will
+ // not be found when searching for it by position, and the compilation fails.
+
+ // ScriptData does not take ownership of the buffers passed to it.
+ sd = i::ScriptData::New(reinterpret_cast<const char*>(cd->data), cd->length);
sd_data = reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryStartOffset] =
200;
- v8::ScriptCompiler::Source script_source2(
- String::NewFromUtf8(isolate, script),
+ const char* script3 = "function foo(){ return 7;}\n"
+ "function bar(){ return 6 + 7;} foo();";
+ v8::ScriptCompiler::Source source3(
+ v8_str(script3),
new v8::ScriptCompiler::CachedData(
reinterpret_cast<const uint8_t*>(sd->Data()), sd->Length()));
compiled_script =
- v8::ScriptCompiler::CompileUnbound(isolate, &script_source2);
- CHECK(!try_catch.HasCaught());
+ v8::ScriptCompiler::CompileUnbound(isolate, &source3);
+ CHECK(try_catch.HasCaught());
+ {
+ String::Utf8Value exception_value(try_catch.Message()->Get());
+ CHECK_EQ("Uncaught SyntaxError: Invalid cached data for function bar",
+ *exception_value);
+ }
+ CHECK(compiled_script.IsEmpty());
+ try_catch.Reset();
+ delete sd;
+ // Try passing in cached data which is obviously invalid (wrong length).
+ sd = i::ScriptData::New(reinterpret_cast<const char*>(cd->data), cd->length);
+ const char* script4 =
+ "function foo(){ return 8;}\n"
+ "function bar(){ return 6 + 7;} foo();";
+ v8::ScriptCompiler::Source source4(
+ v8_str(script4),
+ new v8::ScriptCompiler::CachedData(
+ reinterpret_cast<const uint8_t*>(sd->Data()), sd->Length() - 1));
+ compiled_script =
+ v8::ScriptCompiler::CompileUnbound(isolate, &source4);
+ CHECK(try_catch.HasCaught());
+ {
+ String::Utf8Value exception_value(try_catch.Message()->Get());
+ CHECK_EQ("Uncaught SyntaxError: Invalid cached data",
+ *exception_value);
+ }
+ CHECK(compiled_script.IsEmpty());
delete sd;
}
i::StrLength(c_string)));
Local<String> lhs(v8::Utils::ToLocal(
- factory->NewExternalStringFromAscii(&ascii_resource)));
+ factory->NewExternalStringFromAscii(&ascii_resource)
+ .ToHandleChecked()));
Local<String> rhs(v8::Utils::ToLocal(
- factory->NewExternalStringFromAscii(&ascii_resource)));
+ factory->NewExternalStringFromAscii(&ascii_resource)
+ .ToHandleChecked()));
env->Global()->Set(v8_str("lhs"), lhs);
env->Global()->Set(v8_str("rhs"), rhs);
int expected,
i::Handle<i::Object> obj,
int offset) {
- i::Object* element = *i::Object::GetElement(isolate, obj, offset);
+ i::Object* element =
+ *i::Object::GetElement(isolate, obj, offset).ToHandleChecked();
CHECK_EQ(expected, i::Smi::cast(element)->value());
}
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);
+ no_failure = i::JSObject::SetElement(
+ jsobj, 1, value, NONE, i::SLOPPY).ToHandleChecked();
ASSERT(!no_failure.is_null());
- i::USE(no_failure);
+ 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);
+ no_failure = i::JSObject::SetElement(
+ jsobj, 1, value, NONE, i::SLOPPY).ToHandleChecked();
ASSERT(!no_failure.is_null());
- i::USE(no_failure);
+ 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);
+ no_failure = i::JSObject::SetElement(
+ jsobj, 1, value, NONE, i::SLOPPY).ToHandleChecked();
ASSERT(!no_failure.is_null());
- i::USE(no_failure);
+ USE(no_failure);
CheckElementValue(isolate, 0, jsobj, 1);
result = CompileRun("for (var i = 0; i < 8; i++) {"
" }"
"}"
"res;";
- i::OS::SNPrintF(test_buf,
- boundary_program,
- low);
+ i::SNPrintF(test_buf,
+ boundary_program,
+ low);
result = CompileRun(test_buf.start());
CHECK_EQ(low, result->IntegerValue());
- i::OS::SNPrintF(test_buf,
- boundary_program,
- high);
+ i::SNPrintF(test_buf,
+ boundary_program,
+ high);
result = CompileRun(test_buf.start());
CHECK_EQ(high, result->IntegerValue());
CHECK_EQ(28, result->Int32Value());
// Make sure out-of-range loads do not throw.
- i::OS::SNPrintF(test_buf,
- "var caught_exception = false;"
- "try {"
- " ext_array[%d];"
- "} catch (e) {"
- " caught_exception = true;"
- "}"
- "caught_exception;",
- element_count);
+ i::SNPrintF(test_buf,
+ "var caught_exception = false;"
+ "try {"
+ " ext_array[%d];"
+ "} catch (e) {"
+ " caught_exception = true;"
+ "}"
+ "caught_exception;",
+ element_count);
result = CompileRun(test_buf.start());
CHECK_EQ(false, result->BooleanValue());
// Make sure out-of-range stores do not throw.
- i::OS::SNPrintF(test_buf,
- "var caught_exception = false;"
- "try {"
- " ext_array[%d] = 1;"
- "} catch (e) {"
- " caught_exception = true;"
- "}"
- "caught_exception;",
- element_count);
+ i::SNPrintF(test_buf,
+ "var caught_exception = false;"
+ "try {"
+ " ext_array[%d] = 1;"
+ "} catch (e) {"
+ " caught_exception = true;"
+ "}"
+ "caught_exception;",
+ element_count);
result = CompileRun(test_buf.start());
CHECK_EQ(false, result->BooleanValue());
array_type == v8::kExternalFloat32Array) {
CHECK_EQ(static_cast<int>(i::OS::nan_value()),
static_cast<int>(
- i::Object::GetElement(isolate, jsobj, 7)->Number()));
+ i::Object::GetElement(
+ isolate, jsobj, 7).ToHandleChecked()->Number()));
} else {
CheckElementValue(isolate, 0, jsobj, 7);
}
CHECK_EQ(2, result->Int32Value());
CHECK_EQ(2,
static_cast<int>(
- i::Object::GetElement(isolate, jsobj, 6)->Number()));
+ i::Object::GetElement(
+ isolate, jsobj, 6).ToHandleChecked()->Number()));
if (array_type != v8::kExternalFloat32Array &&
array_type != v8::kExternalFloat64Array) {
array_type == v8::kExternalUint32Array);
bool is_pixel_data = array_type == v8::kExternalUint8ClampedArray;
- i::OS::SNPrintF(test_buf,
- "%s"
- "var all_passed = true;"
- "for (var i = 0; i < source_data.length; i++) {"
- " for (var j = 0; j < 8; j++) {"
- " ext_array[j] = source_data[i];"
- " }"
- " all_passed = all_passed &&"
- " (ext_array[5] == expected_results[i]);"
- "}"
- "all_passed;",
- (is_unsigned ?
- unsigned_data :
- (is_pixel_data ? pixel_data : signed_data)));
+ i::SNPrintF(test_buf,
+ "%s"
+ "var all_passed = true;"
+ "for (var i = 0; i < source_data.length; i++) {"
+ " for (var j = 0; j < 8; j++) {"
+ " ext_array[j] = source_data[i];"
+ " }"
+ " all_passed = all_passed &&"
+ " (ext_array[5] == expected_results[i]);"
+ "}"
+ "all_passed;",
+ (is_unsigned ?
+ unsigned_data :
+ (is_pixel_data ? pixel_data : signed_data)));
result = CompileRun(test_buf.start());
CHECK_EQ(true, result->BooleanValue());
}
kElementCount);
CHECK_EQ(1,
static_cast<int>(
- i::Object::GetElement(isolate, jsobj, 1)->Number()));
+ i::Object::GetElement(
+ isolate, jsobj, 1).ToHandleChecked()->Number()));
ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
context.local(), obj, kElementCount, array_type, low, high);
stackTrace->GetFrame(0));
checkStackFrame(origin, "baz", 8, 3, false, true,
stackTrace->GetFrame(1));
-#ifdef ENABLE_DEBUGGER_SUPPORT
bool is_eval = true;
-#else // ENABLE_DEBUGGER_SUPPORT
- bool is_eval = false;
-#endif // ENABLE_DEBUGGER_SUPPORT
-
// This is the source string inside the eval which has the call to baz.
checkStackFrame(NULL, "", 1, 5, is_eval, false,
stackTrace->GetFrame(2));
"eval('(' + outer +')()%s');";
i::ScopedVector<char> code(1024);
- i::OS::SNPrintF(code, source, "//# sourceURL=eval_url");
+ i::SNPrintF(code, source, "//# sourceURL=eval_url");
CHECK(CompileRun(code.start())->IsUndefined());
- i::OS::SNPrintF(code, source, "//@ sourceURL=eval_url");
+ i::SNPrintF(code, source, "//@ sourceURL=eval_url");
CHECK(CompileRun(code.start())->IsUndefined());
}
script->Run();
for (int i = 0; i < 2; i++) {
CHECK(scriptIdInStack[i] != v8::Message::kNoScriptIdInfo);
- CHECK_EQ(scriptIdInStack[i], script->GetId());
+ CHECK_EQ(scriptIdInStack[i], script->GetUnboundScript()->GetId());
}
}
"outer()\n%s";
i::ScopedVector<char> code(1024);
- i::OS::SNPrintF(code, source, "//# sourceURL=source_url");
+ i::SNPrintF(code, source, "//# sourceURL=source_url");
CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
- i::OS::SNPrintF(code, source, "//@ sourceURL=source_url");
+ i::SNPrintF(code, source, "//@ sourceURL=source_url");
CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
}
"outer()\n%s";
i::ScopedVector<char> code(1024);
- i::OS::SNPrintF(code, source, "//# sourceURL=source_url");
+ i::SNPrintF(code, source, "//# sourceURL=source_url");
CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
- i::OS::SNPrintF(code, source, "//@ sourceURL=source_url");
+ i::SNPrintF(code, source, "//@ sourceURL=source_url");
CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
}
"outer()\n%s";
i::ScopedVector<char> code(1024);
- i::OS::SNPrintF(code, source, "//# sourceURL=source_url");
+ i::SNPrintF(code, source, "//# sourceURL=source_url");
v8::TryCatch try_catch;
CompileRunWithOrigin(code.start(), "", 0, 0);
CHECK(try_catch.HasCaught());
CcTest::heap()->CollectAllAvailableGarbage(); // Tenure string.
// Turn into a symbol.
i::Handle<i::String> string3_i = v8::Utils::OpenHandle(*string3);
- CHECK(!CcTest::heap()->InternalizeString(*string3_i)->IsFailure());
+ CHECK(!CcTest::i_isolate()->factory()->InternalizeString(
+ string3_i).is_null());
CHECK(string3_i->IsInternalizedString());
// We need to add usages for string* to avoid warnings in GCC 4.7
static double DoubleFromBits(uint64_t value) {
double target;
- i::OS::MemCopy(&target, &value, sizeof(target));
+ i::MemCopy(&target, &value, sizeof(target));
return target;
}
static uint64_t DoubleToBits(double value) {
uint64_t target;
- i::OS::MemCopy(&target, &value, sizeof(target));
+ i::MemCopy(&target, &value, sizeof(target));
return target;
}
env->Global()->Get(v8::String::NewFromUtf8(isolate, "foo")));
v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
env->Global()->Get(v8::String::NewFromUtf8(isolate, "bar")));
- CHECK_EQ(script->GetId(), foo->ScriptId());
- CHECK_EQ(script->GetId(), bar->ScriptId());
+ CHECK_EQ(script->GetUnboundScript()->GetId(), foo->ScriptId());
+ CHECK_EQ(script->GetUnboundScript()->GetId(), bar->ScriptId());
}
const v8::PropertyCallbackInfo<void>& info) {
CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
- info.This()->Set(v8_str("y"), v8_num(23));
+ Local<Object>::Cast(info.This())->Set(v8_str("y"), v8_num(23));
}
CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
if (!name->Equals(v8_str("foo"))) return;
- info.This()->Set(v8_str("y"), v8_num(23));
+ Local<Object>::Cast(info.This())->Set(v8_str("y"), v8_num(23));
info.GetReturnValue().Set(v8_num(23));
}
Local<Value> value,
const v8::PropertyCallbackInfo<v8::Value>& info) {
if (name->Equals(v8_str("x"))) {
- info.This()->Set(v8_str("y"), v8_num(23));
+ Local<Object>::Cast(info.This())->Set(v8_str("y"), v8_num(23));
}
}
int length = string->length();
CHECK(string->IsOneByteRepresentation());
- FlattenString(string);
- i::Handle<i::String> flat_string = FlattenGetString(string);
+ i::Handle<i::String> flat_string = i::String::Flatten(string);
CHECK(string->IsOneByteRepresentation());
CHECK(flat_string->IsOneByteRepresentation());
ExpectUndefined("Object.prototype.__lookupGetter__.call("
" other, \'x\')");
- // HasLocalElement.
+ // HasOwnElement.
ExpectFalse("Object.prototype.hasOwnProperty.call(other, \'0\')");
CHECK_EQ(false, global0->HasRealIndexedProperty(0));
v8::Isolate* current_isolate = CcTest::isolate();
v8::Isolate* isolate = v8::Isolate::New();
CHECK(isolate != NULL);
- CHECK(!reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate());
CHECK(current_isolate != isolate);
CHECK(current_isolate == CcTest::isolate());
v8::HandleScope scope(isolate);
LocalContext context(isolate);
i::ScopedVector<char> code(1024);
- i::OS::SNPrintF(code, "function fib(n) {"
- " if (n <= 2) return 1;"
- " return fib(n-1) + fib(n-2);"
- "}"
- "fib(%d)", limit);
+ i::SNPrintF(code, "function fib(n) {"
+ " if (n <= 2) return 1;"
+ " return fib(n-1) + fib(n-2);"
+ "}"
+ "fib(%d)", limit);
Local<Value> value = CompileRun(code.start());
CHECK(value->IsNumber());
return static_cast<int>(value->NumberValue());
isolate->Enter();
switch (testCase_) {
case SetResourceConstraints: {
- static const int K = 1024;
v8::ResourceConstraints constraints;
- constraints.set_max_young_space_size(256 * K);
- constraints.set_max_old_space_size(4 * K * K);
+ constraints.set_max_semi_space_size(1);
+ constraints.set_max_old_space_size(4);
v8::SetResourceConstraints(CcTest::isolate(), &constraints);
break;
}
break;
case SetCounterFunction:
- v8::V8::SetCounterFunction(NULL);
+ CcTest::isolate()->SetCounterFunction(NULL);
break;
case SetCreateHistogramFunction:
- v8::V8::SetCreateHistogramFunction(NULL);
+ CcTest::isolate()->SetCreateHistogramFunction(NULL);
break;
case SetAddHistogramSampleFunction:
- v8::V8::SetAddHistogramSampleFunction(NULL);
+ CcTest::isolate()->SetAddHistogramSampleFunction(NULL);
break;
}
isolate->Exit();
i::OS::Print("Entering recursion level %d.\n", level);
char script[64];
i::Vector<char> script_vector(script, sizeof(script));
- i::OS::SNPrintF(script_vector, "recursion(%d)", level);
+ i::SNPrintF(script_vector, "recursion(%d)", level);
CompileRun(script_vector.start());
i::OS::Print("Leaving recursion level %d.\n", level);
CHECK_EQ(0, callback_fired);
env->Global()->Set(v8_str("recursion"),
recursive_runtime->GetFunction());
// Adding the same callback a second time has no effect.
- v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
- v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
- v8::V8::AddCallCompletedCallback(CallCompletedCallback2);
+ env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
+ env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
+ env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback2);
i::OS::Print("--- Script (1) ---\n");
Local<Script> script = v8::Script::Compile(
v8::String::NewFromUtf8(env->GetIsolate(), "recursion(0)"));
i::OS::Print("\n--- Script (2) ---\n");
callback_fired = 0;
- v8::V8::RemoveCallCompletedCallback(CallCompletedCallback1);
+ env->GetIsolate()->RemoveCallCompletedCallback(CallCompletedCallback1);
script->Run();
CHECK_EQ(2, callback_fired);
TEST(CallCompletedCallbackOneException) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
- v8::V8::AddCallCompletedCallback(CallCompletedCallbackNoException);
+ env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackNoException);
CompileRun("throw 'exception';");
}
TEST(CallCompletedCallbackTwoExceptions) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
- v8::V8::AddCallCompletedCallback(CallCompletedCallbackException);
+ env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackException);
CompileRun("throw 'first exception';");
}
}
+void* g_passed_to_three = NULL;
+
+
+static void MicrotaskThree(void* data) {
+ g_passed_to_three = data;
+}
+
+
TEST(EnqueueMicrotask) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value());
CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
- v8::V8::EnqueueMicrotask(env->GetIsolate(),
- Function::New(env->GetIsolate(), MicrotaskOne));
+ env->GetIsolate()->EnqueueMicrotask(
+ Function::New(env->GetIsolate(), MicrotaskOne));
CompileRun("1+1;");
CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
- v8::V8::EnqueueMicrotask(env->GetIsolate(),
- Function::New(env->GetIsolate(), MicrotaskOne));
- v8::V8::EnqueueMicrotask(env->GetIsolate(),
- Function::New(env->GetIsolate(), MicrotaskTwo));
+ env->GetIsolate()->EnqueueMicrotask(
+ Function::New(env->GetIsolate(), MicrotaskOne));
+ env->GetIsolate()->EnqueueMicrotask(
+ Function::New(env->GetIsolate(), MicrotaskTwo));
CompileRun("1+1;");
CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value());
- v8::V8::EnqueueMicrotask(env->GetIsolate(),
- Function::New(env->GetIsolate(), MicrotaskTwo));
+ env->GetIsolate()->EnqueueMicrotask(
+ Function::New(env->GetIsolate(), MicrotaskTwo));
+ CompileRun("1+1;");
+ CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
+ CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
+
CompileRun("1+1;");
CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
+ g_passed_to_three = NULL;
+ env->GetIsolate()->EnqueueMicrotask(MicrotaskThree);
CompileRun("1+1;");
+ CHECK_EQ(NULL, g_passed_to_three);
CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
+
+ int dummy;
+ env->GetIsolate()->EnqueueMicrotask(
+ Function::New(env->GetIsolate(), MicrotaskOne));
+ env->GetIsolate()->EnqueueMicrotask(MicrotaskThree, &dummy);
+ env->GetIsolate()->EnqueueMicrotask(
+ Function::New(env->GetIsolate(), MicrotaskTwo));
+ CompileRun("1+1;");
+ CHECK_EQ(&dummy, g_passed_to_three);
+ CHECK_EQ(3, CompileRun("ext1Calls")->Int32Value());
+ CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value());
+ g_passed_to_three = NULL;
+}
+
+
+static void MicrotaskExceptionOne(
+ const v8::FunctionCallbackInfo<Value>& info) {
+ v8::HandleScope scope(info.GetIsolate());
+ CompileRun("exception1Calls++;");
+ info.GetIsolate()->ThrowException(
+ v8::Exception::Error(v8_str("first")));
+}
+
+
+static void MicrotaskExceptionTwo(
+ const v8::FunctionCallbackInfo<Value>& info) {
+ v8::HandleScope scope(info.GetIsolate());
+ CompileRun("exception2Calls++;");
+ info.GetIsolate()->ThrowException(
+ v8::Exception::Error(v8_str("second")));
+}
+
+
+TEST(RunMicrotasksIgnoresThrownExceptions) {
+ LocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope scope(isolate);
+ CompileRun(
+ "var exception1Calls = 0;"
+ "var exception2Calls = 0;");
+ isolate->EnqueueMicrotask(
+ Function::New(isolate, MicrotaskExceptionOne));
+ isolate->EnqueueMicrotask(
+ Function::New(isolate, MicrotaskExceptionTwo));
+ TryCatch try_catch;
+ CompileRun("1+1;");
+ CHECK(!try_catch.HasCaught());
+ CHECK_EQ(1, CompileRun("exception1Calls")->Int32Value());
+ CHECK_EQ(1, CompileRun("exception2Calls")->Int32Value());
}
CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value());
CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
- v8::V8::EnqueueMicrotask(env->GetIsolate(),
- Function::New(env->GetIsolate(), MicrotaskOne));
+ env->GetIsolate()->EnqueueMicrotask(
+ Function::New(env->GetIsolate(), MicrotaskOne));
CompileRun("1+1;");
CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
- V8::SetAutorunMicrotasks(env->GetIsolate(), false);
- v8::V8::EnqueueMicrotask(env->GetIsolate(),
- Function::New(env->GetIsolate(), MicrotaskOne));
- v8::V8::EnqueueMicrotask(env->GetIsolate(),
- Function::New(env->GetIsolate(), MicrotaskTwo));
+ env->GetIsolate()->SetAutorunMicrotasks(false);
+ env->GetIsolate()->EnqueueMicrotask(
+ Function::New(env->GetIsolate(), MicrotaskOne));
+ env->GetIsolate()->EnqueueMicrotask(
+ Function::New(env->GetIsolate(), MicrotaskTwo));
CompileRun("1+1;");
CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
- V8::RunMicrotasks(env->GetIsolate());
+ env->GetIsolate()->RunMicrotasks();
CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value());
- v8::V8::EnqueueMicrotask(env->GetIsolate(),
- Function::New(env->GetIsolate(), MicrotaskTwo));
+ env->GetIsolate()->EnqueueMicrotask(
+ Function::New(env->GetIsolate(), MicrotaskTwo));
CompileRun("1+1;");
CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value());
- V8::RunMicrotasks(env->GetIsolate());
+ env->GetIsolate()->RunMicrotasks();
CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
- V8::SetAutorunMicrotasks(env->GetIsolate(), true);
- v8::V8::EnqueueMicrotask(env->GetIsolate(),
- Function::New(env->GetIsolate(), MicrotaskTwo));
+ env->GetIsolate()->SetAutorunMicrotasks(true);
+ env->GetIsolate()->EnqueueMicrotask(
+ Function::New(env->GetIsolate(), MicrotaskTwo));
CompileRun("1+1;");
CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value());
+
+ env->GetIsolate()->EnqueueMicrotask(
+ Function::New(env->GetIsolate(), MicrotaskTwo));
+ {
+ v8::Isolate::SuppressMicrotaskExecutionScope scope(env->GetIsolate());
+ CompileRun("1+1;");
+ CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
+ CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value());
+ }
+
+ CompileRun("1+1;");
+ CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
+ CHECK_EQ(4, CompileRun("ext2Calls")->Int32Value());
+}
+
+
+TEST(RunMicrotasksWithoutEnteringContext) {
+ v8::Isolate* isolate = CcTest::isolate();
+ HandleScope handle_scope(isolate);
+ isolate->SetAutorunMicrotasks(false);
+ Handle<Context> context = Context::New(isolate);
+ {
+ Context::Scope context_scope(context);
+ CompileRun("var ext1Calls = 0;");
+ isolate->EnqueueMicrotask(Function::New(isolate, MicrotaskOne));
+ }
+ isolate->RunMicrotasks();
+ {
+ Context::Scope context_scope(context);
+ CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
+ }
+ isolate->SetAutorunMicrotasks(true);
}
+#ifdef DEBUG
static int probes_counter = 0;
static int misses_counter = 0;
static int updates_counter = 0;
" fooify(a);"
" fooify(b);"
"}";
+#endif
static void StubCacheHelper(bool primary) {
- V8::SetCounterFunction(LookupCounter);
- USE(kMegamorphicTestProgram);
#ifdef DEBUG
i::FLAG_native_code_counters = true;
if (primary) {
}
i::FLAG_crankshaft = false;
LocalContext env;
+ env->GetIsolate()->SetCounterFunction(LookupCounter);
v8::HandleScope scope(env->GetIsolate());
int initial_probes = probes_counter;
int initial_misses = misses_counter;
}
+#ifdef DEBUG
static int cow_arrays_created_runtime = 0;
}
return NULL;
}
+#endif
TEST(CheckCOWArraysCreatedRuntimeCounter) {
- V8::SetCounterFunction(LookupCounterCOWArrays);
#ifdef DEBUG
i::FLAG_native_code_counters = true;
LocalContext env;
+ env->GetIsolate()->SetCounterFunction(LookupCounterCOWArrays);
v8::HandleScope scope(env->GetIsolate());
int initial_cow_arrays = cow_arrays_created_runtime;
CompileRun("var o = [1, 2, 3];");
}
+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;
THREADED_TEST(Regress2535) {
i::FLAG_harmony_collections = true;
+ i::FLAG_harmony_symbols = true;
LocalContext context;
v8::HandleScope scope(context->GetIsolate());
Local<Value> set_value = CompileRun("new Set();");
access_check_fail_thrown = false;
catch_callback_called = false;
i::ScopedVector<char> source(1024);
- i::OS::SNPrintF(source, "try { %s; } catch (e) { catcher(e); }", script);
+ i::SNPrintF(source, "try { %s; } catch (e) { catcher(e); }", script);
CompileRun(source.start());
CHECK(access_check_fail_thrown);
CHECK(catch_callback_called);
CheckCorrectThrow("%IgnoreAttributesAndSetProperty(other, 'x', 'foo')");
CheckCorrectThrow("%DeleteProperty(other, 'x', 0)");
CheckCorrectThrow("%DeleteProperty(other, '1', 0)");
- CheckCorrectThrow("%HasLocalProperty(other, 'x')");
+ CheckCorrectThrow("%HasOwnProperty(other, 'x')");
CheckCorrectThrow("%HasProperty(other, 'x')");
CheckCorrectThrow("%HasElement(other, 1)");
CheckCorrectThrow("%IsPropertyEnumerable(other, 'x')");
CheckCorrectThrow("%GetPropertyNames(other)");
// PROPERTY_ATTRIBUTES_NONE = 0
- CheckCorrectThrow("%GetLocalPropertyNames(other, 0)");
+ CheckCorrectThrow("%GetOwnPropertyNames(other, 0)");
CheckCorrectThrow("%DefineOrRedefineAccessorProperty("
"other, 'x', null, null, 1)");
virtual ~RequestInterruptTestBase() { }
+ virtual void StartInterruptThread() = 0;
+
virtual void TestBody() = 0;
void RunTest() {
- InterruptThread i_thread(this);
- i_thread.Start();
+ StartInterruptThread();
v8::HandleScope handle_scope(isolate_);
return should_continue_;
}
- protected:
static void ShouldContinueCallback(
const v8::FunctionCallbackInfo<Value>& info) {
RequestInterruptTestBase* test =
info.GetReturnValue().Set(test->ShouldContinue());
}
+ LocalContext env_;
+ v8::Isolate* isolate_;
+ i::Semaphore sem_;
+ int warmup_;
+ bool should_continue_;
+};
+
+
+class RequestInterruptTestBaseWithSimpleInterrupt
+ : public RequestInterruptTestBase {
+ public:
+ RequestInterruptTestBaseWithSimpleInterrupt() : i_thread(this) { }
+
+ virtual void StartInterruptThread() {
+ i_thread.Start();
+ }
+
+ private:
class InterruptThread : public i::Thread {
public:
explicit InterruptThread(RequestInterruptTestBase* test)
RequestInterruptTestBase* test_;
};
- LocalContext env_;
- v8::Isolate* isolate_;
- i::Semaphore sem_;
- int warmup_;
- bool should_continue_;
+ InterruptThread i_thread;
};
-class RequestInterruptTestWithFunctionCall : public RequestInterruptTestBase {
+class RequestInterruptTestWithFunctionCall
+ : public RequestInterruptTestBaseWithSimpleInterrupt {
public:
virtual void TestBody() {
Local<Function> func = Function::New(
};
-class RequestInterruptTestWithMethodCall : public RequestInterruptTestBase {
+class RequestInterruptTestWithMethodCall
+ : public RequestInterruptTestBaseWithSimpleInterrupt {
public:
virtual void TestBody() {
v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
};
-class RequestInterruptTestWithAccessor : public RequestInterruptTestBase {
+class RequestInterruptTestWithAccessor
+ : public RequestInterruptTestBaseWithSimpleInterrupt {
public:
virtual void TestBody() {
v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
};
-class RequestInterruptTestWithNativeAccessor : public RequestInterruptTestBase {
+class RequestInterruptTestWithNativeAccessor
+ : public RequestInterruptTestBaseWithSimpleInterrupt {
public:
virtual void TestBody() {
v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
class RequestInterruptTestWithMethodCallAndInterceptor
- : public RequestInterruptTestBase {
+ : public RequestInterruptTestBaseWithSimpleInterrupt {
public:
virtual void TestBody() {
v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
};
-class RequestInterruptTestWithMathAbs : public RequestInterruptTestBase {
+class RequestInterruptTestWithMathAbs
+ : public RequestInterruptTestBaseWithSimpleInterrupt {
public:
virtual void TestBody() {
env_->Global()->Set(v8_str("WakeUpInterruptor"), Function::New(
}
+class ClearInterruptFromAnotherThread
+ : public RequestInterruptTestBase {
+ public:
+ ClearInterruptFromAnotherThread() : i_thread(this), sem2_(0) { }
+
+ virtual void StartInterruptThread() {
+ i_thread.Start();
+ }
+
+ virtual void TestBody() {
+ Local<Function> func = Function::New(
+ isolate_, ShouldContinueCallback, v8::External::New(isolate_, this));
+ env_->Global()->Set(v8_str("ShouldContinue"), func);
+
+ CompileRun("while (ShouldContinue()) { }");
+ }
+
+ private:
+ class InterruptThread : public i::Thread {
+ public:
+ explicit InterruptThread(ClearInterruptFromAnotherThread* test)
+ : Thread("RequestInterruptTest"), test_(test) {}
+
+ virtual void Run() {
+ test_->sem_.Wait();
+ test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
+ test_->sem_.Wait();
+ test_->isolate_->ClearInterrupt();
+ test_->sem2_.Signal();
+ }
+
+ static void OnInterrupt(v8::Isolate* isolate, void* data) {
+ ClearInterruptFromAnotherThread* test =
+ reinterpret_cast<ClearInterruptFromAnotherThread*>(data);
+ test->sem_.Signal();
+ bool success = test->sem2_.WaitFor(i::TimeDelta::FromSeconds(2));
+ // Crash instead of timeout to make this failure more prominent.
+ CHECK(success);
+ test->should_continue_ = false;
+ }
+
+ private:
+ ClearInterruptFromAnotherThread* test_;
+ };
+
+ InterruptThread i_thread;
+ i::Semaphore sem2_;
+};
+
+
+TEST(ClearInterruptFromAnotherThread) {
+ ClearInterruptFromAnotherThread().RunTest();
+}
+
+
static Local<Value> function_new_expected_env;
static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
CHECK_EQ(function_new_expected_env, info.Data());
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
i::Handle<i::JSObject> cache(i_isolate->native_context()->function_cache());
i::Handle<i::Object> elm =
- i::Object::GetElementNoExceptionThrown(i_isolate, cache, serial_number);
+ i::Object::GetElement(i_isolate, cache, serial_number).ToHandleChecked();
CHECK(elm->IsUndefined());
// Verify that each Function::New creates a new function instance
Local<Object> data2 = v8::Object::New(isolate);
info.GetReturnValue().Set(v8_str("returned"));
}
- public:
- enum SignatureType {
- kNoSignature,
- kSignatureOnReceiver,
- kSignatureOnPrototype
- };
-
- void RunAll() {
- SignatureType signature_types[] =
- {kNoSignature, kSignatureOnReceiver, kSignatureOnPrototype};
- for (unsigned i = 0; i < ARRAY_SIZE(signature_types); i++) {
- SignatureType signature_type = signature_types[i];
- for (int j = 0; j < 2; j++) {
- bool global = j == 0;
- int key = signature_type +
- ARRAY_SIZE(signature_types) * (global ? 1 : 0);
- Run(signature_type, global, key);
- }
+ public:
+ enum SignatureType {
+ kNoSignature,
+ kSignatureOnReceiver,
+ kSignatureOnPrototype
+ };
+
+ void RunAll() {
+ SignatureType signature_types[] =
+ {kNoSignature, kSignatureOnReceiver, kSignatureOnPrototype};
+ for (unsigned i = 0; i < ARRAY_SIZE(signature_types); i++) {
+ SignatureType signature_type = signature_types[i];
+ for (int j = 0; j < 2; j++) {
+ bool global = j == 0;
+ int key = signature_type +
+ ARRAY_SIZE(signature_types) * (global ? 1 : 0);
+ Run(signature_type, global, key);
}
}
+ }
- void Run(SignatureType signature_type, bool global, int key) {
- v8::Isolate* isolate = CcTest::isolate();
- v8::HandleScope scope(isolate);
- // Build a template for signature checks.
- Local<v8::ObjectTemplate> signature_template;
- Local<v8::Signature> signature;
- {
- Local<v8::FunctionTemplate> parent_template =
- FunctionTemplate::New(isolate);
- parent_template->SetHiddenPrototype(true);
- Local<v8::FunctionTemplate> function_template
- = FunctionTemplate::New(isolate);
- function_template->Inherit(parent_template);
- switch (signature_type) {
- case kNoSignature:
- break;
- case kSignatureOnReceiver:
- signature = v8::Signature::New(isolate, function_template);
- break;
- case kSignatureOnPrototype:
- signature = v8::Signature::New(isolate, parent_template);
- break;
- }
- signature_template = function_template->InstanceTemplate();
- }
- // Global object must pass checks.
- Local<v8::Context> context =
- v8::Context::New(isolate, NULL, signature_template);
- v8::Context::Scope context_scope(context);
- // Install regular object that can pass signature checks.
- Local<Object> function_receiver = signature_template->NewInstance();
- context->Global()->Set(v8_str("function_receiver"), function_receiver);
- // Get the holder objects.
- Local<Object> inner_global =
- Local<Object>::Cast(context->Global()->GetPrototype());
- // Install functions on hidden prototype object if there is one.
- data = Object::New(isolate);
- Local<FunctionTemplate> function_template = FunctionTemplate::New(
- isolate, OptimizationCallback, data, signature);
- Local<Function> function = function_template->GetFunction();
- Local<Object> global_holder = inner_global;
- Local<Object> function_holder = function_receiver;
- if (signature_type == kSignatureOnPrototype) {
- function_holder = Local<Object>::Cast(function_holder->GetPrototype());
- global_holder = Local<Object>::Cast(global_holder->GetPrototype());
+ void Run(SignatureType signature_type, bool global, int key) {
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope scope(isolate);
+ // Build a template for signature checks.
+ Local<v8::ObjectTemplate> signature_template;
+ Local<v8::Signature> signature;
+ {
+ Local<v8::FunctionTemplate> parent_template =
+ FunctionTemplate::New(isolate);
+ parent_template->SetHiddenPrototype(true);
+ Local<v8::FunctionTemplate> function_template
+ = FunctionTemplate::New(isolate);
+ function_template->Inherit(parent_template);
+ switch (signature_type) {
+ case kNoSignature:
+ break;
+ case kSignatureOnReceiver:
+ signature = v8::Signature::New(isolate, function_template);
+ break;
+ case kSignatureOnPrototype:
+ signature = v8::Signature::New(isolate, parent_template);
+ break;
}
- global_holder->Set(v8_str("g_f"), function);
- global_holder->SetAccessorProperty(v8_str("g_acc"), function, function);
- function_holder->Set(v8_str("f"), function);
- function_holder->SetAccessorProperty(v8_str("acc"), function, function);
- // Initialize expected values.
- callee = function;
- count = 0;
- if (global) {
- receiver = context->Global();
- holder = inner_global;
- } else {
- holder = function_receiver;
- // If not using a signature, add something else to the prototype chain
- // to test the case that holder != receiver
- if (signature_type == kNoSignature) {
- receiver = Local<Object>::Cast(CompileRun(
- "var receiver_subclass = {};\n"
- "receiver_subclass.__proto__ = function_receiver;\n"
- "receiver_subclass"));
- } else {
- receiver = Local<Object>::Cast(CompileRun(
- "var receiver_subclass = function_receiver;\n"
+ signature_template = function_template->InstanceTemplate();
+ }
+ // Global object must pass checks.
+ Local<v8::Context> context =
+ v8::Context::New(isolate, NULL, signature_template);
+ v8::Context::Scope context_scope(context);
+ // Install regular object that can pass signature checks.
+ Local<Object> function_receiver = signature_template->NewInstance();
+ context->Global()->Set(v8_str("function_receiver"), function_receiver);
+ // Get the holder objects.
+ Local<Object> inner_global =
+ Local<Object>::Cast(context->Global()->GetPrototype());
+ // Install functions on hidden prototype object if there is one.
+ data = Object::New(isolate);
+ Local<FunctionTemplate> function_template = FunctionTemplate::New(
+ isolate, OptimizationCallback, data, signature);
+ Local<Function> function = function_template->GetFunction();
+ Local<Object> global_holder = inner_global;
+ Local<Object> function_holder = function_receiver;
+ if (signature_type == kSignatureOnPrototype) {
+ function_holder = Local<Object>::Cast(function_holder->GetPrototype());
+ global_holder = Local<Object>::Cast(global_holder->GetPrototype());
+ }
+ global_holder->Set(v8_str("g_f"), function);
+ global_holder->SetAccessorProperty(v8_str("g_acc"), function, function);
+ function_holder->Set(v8_str("f"), function);
+ function_holder->SetAccessorProperty(v8_str("acc"), function, function);
+ // Initialize expected values.
+ callee = function;
+ count = 0;
+ if (global) {
+ receiver = context->Global();
+ holder = inner_global;
+ } else {
+ holder = function_receiver;
+ // If not using a signature, add something else to the prototype chain
+ // to test the case that holder != receiver
+ if (signature_type == kNoSignature) {
+ receiver = Local<Object>::Cast(CompileRun(
+ "var receiver_subclass = {};\n"
+ "receiver_subclass.__proto__ = function_receiver;\n"
"receiver_subclass"));
- }
- }
- // With no signature, the holder is not set.
- if (signature_type == kNoSignature) holder = receiver;
- // build wrap_function
- i::ScopedVector<char> wrap_function(200);
- if (global) {
- i::OS::SNPrintF(
- wrap_function,
- "function wrap_f_%d() { var f = g_f; return f(); }\n"
- "function wrap_get_%d() { return this.g_acc; }\n"
- "function wrap_set_%d() { return this.g_acc = 1; }\n",
- key, key, key);
} else {
- i::OS::SNPrintF(
- wrap_function,
- "function wrap_f_%d() { return receiver_subclass.f(); }\n"
- "function wrap_get_%d() { return receiver_subclass.acc; }\n"
- "function wrap_set_%d() { return receiver_subclass.acc = 1; }\n",
- key, key, key);
+ receiver = Local<Object>::Cast(CompileRun(
+ "var receiver_subclass = function_receiver;\n"
+ "receiver_subclass"));
}
- // build source string
- i::ScopedVector<char> source(1000);
- i::OS::SNPrintF(
- source,
- "%s\n" // wrap functions
- "function wrap_f() { return wrap_f_%d(); }\n"
- "function wrap_get() { return wrap_get_%d(); }\n"
- "function wrap_set() { return wrap_set_%d(); }\n"
- "check = function(returned) {\n"
- " if (returned !== 'returned') { throw returned; }\n"
- "}\n"
- "\n"
- "check(wrap_f());\n"
- "check(wrap_f());\n"
- "%%OptimizeFunctionOnNextCall(wrap_f_%d);\n"
- "check(wrap_f());\n"
- "\n"
- "check(wrap_get());\n"
- "check(wrap_get());\n"
- "%%OptimizeFunctionOnNextCall(wrap_get_%d);\n"
- "check(wrap_get());\n"
- "\n"
- "check = function(returned) {\n"
- " if (returned !== 1) { throw returned; }\n"
- "}\n"
- "check(wrap_set());\n"
- "check(wrap_set());\n"
- "%%OptimizeFunctionOnNextCall(wrap_set_%d);\n"
- "check(wrap_set());\n",
- wrap_function.start(), key, key, key, key, key, key);
- v8::TryCatch try_catch;
- CompileRun(source.start());
- ASSERT(!try_catch.HasCaught());
- CHECK_EQ(9, count);
}
+ // With no signature, the holder is not set.
+ if (signature_type == kNoSignature) holder = receiver;
+ // build wrap_function
+ i::ScopedVector<char> wrap_function(200);
+ if (global) {
+ i::SNPrintF(
+ wrap_function,
+ "function wrap_f_%d() { var f = g_f; return f(); }\n"
+ "function wrap_get_%d() { return this.g_acc; }\n"
+ "function wrap_set_%d() { return this.g_acc = 1; }\n",
+ key, key, key);
+ } else {
+ i::SNPrintF(
+ wrap_function,
+ "function wrap_f_%d() { return receiver_subclass.f(); }\n"
+ "function wrap_get_%d() { return receiver_subclass.acc; }\n"
+ "function wrap_set_%d() { return receiver_subclass.acc = 1; }\n",
+ key, key, key);
+ }
+ // build source string
+ i::ScopedVector<char> source(1000);
+ i::SNPrintF(
+ source,
+ "%s\n" // wrap functions
+ "function wrap_f() { return wrap_f_%d(); }\n"
+ "function wrap_get() { return wrap_get_%d(); }\n"
+ "function wrap_set() { return wrap_set_%d(); }\n"
+ "check = function(returned) {\n"
+ " if (returned !== 'returned') { throw returned; }\n"
+ "}\n"
+ "\n"
+ "check(wrap_f());\n"
+ "check(wrap_f());\n"
+ "%%OptimizeFunctionOnNextCall(wrap_f_%d);\n"
+ "check(wrap_f());\n"
+ "\n"
+ "check(wrap_get());\n"
+ "check(wrap_get());\n"
+ "%%OptimizeFunctionOnNextCall(wrap_get_%d);\n"
+ "check(wrap_get());\n"
+ "\n"
+ "check = function(returned) {\n"
+ " if (returned !== 1) { throw returned; }\n"
+ "}\n"
+ "check(wrap_set());\n"
+ "check(wrap_set());\n"
+ "%%OptimizeFunctionOnNextCall(wrap_set_%d);\n"
+ "check(wrap_set());\n",
+ wrap_function.start(), key, key, key, key, key, key);
+ v8::TryCatch try_catch;
+ CompileRun(source.start());
+ ASSERT(!try_catch.HasCaught());
+ CHECK_EQ(9, count);
+ }
};
TEST(EventLogging) {
v8::Isolate* isolate = CcTest::isolate();
isolate->SetEventLogger(StoringEventLoggerCallback);
- v8::internal::HistogramTimer* histogramTimer =
- new v8::internal::HistogramTimer(
- "V8.Test", 0, 10000, 50,
- reinterpret_cast<v8::internal::Isolate*>(isolate));
- histogramTimer->Start();
+ v8::internal::HistogramTimer histogramTimer(
+ "V8.Test", 0, 10000, 50,
+ reinterpret_cast<v8::internal::Isolate*>(isolate));
+ histogramTimer.Start();
CHECK_EQ("V8.Test", last_event_message);
CHECK_EQ(0, last_event_status);
- histogramTimer->Stop();
+ histogramTimer.Stop();
CHECK_EQ("V8.Test", last_event_message);
CHECK_EQ(1, last_event_status);
}
TEST(Promises) {
- i::FLAG_harmony_promises = true;
-
LocalContext context;
v8::Isolate* isolate = context->GetIsolate();
v8::HandleScope scope(isolate);
p->Chain(f1);
CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
- V8::RunMicrotasks(isolate);
+ isolate->RunMicrotasks();
CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
p->Catch(f2);
- V8::RunMicrotasks(isolate);
+ isolate->RunMicrotasks();
CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
r->Catch(f2);
CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
- V8::RunMicrotasks(isolate);
+ isolate->RunMicrotasks();
CHECK_EQ(2, global->Get(v8_str("x2"))->Int32Value());
r->Chain(f1);
- V8::RunMicrotasks(isolate);
+ isolate->RunMicrotasks();
CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
// Chaining pending promises.
pr->GetPromise()->Chain(f1);
rr->GetPromise()->Catch(f2);
- V8::RunMicrotasks(isolate);
+ isolate->RunMicrotasks();
CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
- V8::RunMicrotasks(isolate);
+ isolate->RunMicrotasks();
CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
CHECK_EQ(2, global->Get(v8_str("x2"))->Int32Value());
pr->Resolve(v8::Integer::New(isolate, 3));
CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
- V8::RunMicrotasks(isolate);
+ isolate->RunMicrotasks();
CHECK_EQ(3, global->Get(v8_str("x1"))->Int32Value());
CHECK_EQ(4, global->Get(v8_str("x2"))->Int32Value());
rr->Reject(v8::Integer::New(isolate, 3));
CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
- V8::RunMicrotasks(isolate);
+ isolate->RunMicrotasks();
+ CHECK_EQ(3, global->Get(v8_str("x1"))->Int32Value());
+ CHECK_EQ(4, global->Get(v8_str("x2"))->Int32Value());
+}
+
+
+TEST(PromiseThen) {
+ LocalContext context;
+ v8::Isolate* isolate = context->GetIsolate();
+ v8::HandleScope scope(isolate);
+ Handle<Object> global = context->Global();
+
+ // Creation.
+ Handle<v8::Promise::Resolver> pr = v8::Promise::Resolver::New(isolate);
+ Handle<v8::Promise::Resolver> qr = v8::Promise::Resolver::New(isolate);
+ Handle<v8::Promise> p = pr->GetPromise();
+ Handle<v8::Promise> q = qr->GetPromise();
+
+ CHECK(p->IsPromise());
+ CHECK(q->IsPromise());
+
+ pr->Resolve(v8::Integer::New(isolate, 1));
+ qr->Resolve(p);
+
+ // Chaining non-pending promises.
+ CompileRun(
+ "var x1 = 0;\n"
+ "var x2 = 0;\n"
+ "function f1(x) { x1 = x; return x+1 };\n"
+ "function f2(x) { x2 = x; return x+1 };\n");
+ Handle<Function> f1 = Handle<Function>::Cast(global->Get(v8_str("f1")));
+ Handle<Function> f2 = Handle<Function>::Cast(global->Get(v8_str("f2")));
+
+ // Chain
+ q->Chain(f1);
+ CHECK(global->Get(v8_str("x1"))->IsNumber());
+ CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
+ isolate->RunMicrotasks();
+ CHECK(!global->Get(v8_str("x1"))->IsNumber());
+ CHECK_EQ(p, global->Get(v8_str("x1")));
+
+ // Then
+ CompileRun("x1 = x2 = 0;");
+ q->Then(f1);
+ CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
+ isolate->RunMicrotasks();
+ CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
+
+ // Then
+ CompileRun("x1 = x2 = 0;");
+ pr = v8::Promise::Resolver::New(isolate);
+ qr = v8::Promise::Resolver::New(isolate);
+
+ qr->Resolve(pr);
+ qr->GetPromise()->Then(f1)->Then(f2);
+
+ CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
+ CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
+ isolate->RunMicrotasks();
+ CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
+ CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
+
+ pr->Resolve(v8::Integer::New(isolate, 3));
+
+ CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
+ CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
+ isolate->RunMicrotasks();
CHECK_EQ(3, global->Get(v8_str("x1"))->Int32Value());
CHECK_EQ(4, global->Get(v8_str("x2"))->Int32Value());
}
CompileRun("Object.getPrototypeOf(friend);");
CHECK_EQ(2, named_access_count);
}
+
+
+TEST(CaptureStackTraceForStackOverflow) {
+ v8::internal::FLAG_stack_size = 150;
+ LocalContext current;
+ v8::Isolate* isolate = current->GetIsolate();
+ v8::HandleScope scope(isolate);
+ V8::SetCaptureStackTraceForUncaughtExceptions(
+ true, 10, v8::StackTrace::kDetailed);
+ v8::TryCatch try_catch;
+ CompileRun("(function f(x) { f(x+1); })(0)");
+ CHECK(try_catch.HasCaught());
+}
+
+
+TEST(ScriptNameAndLineNumber) {
+ LocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope scope(isolate);
+ const char* url = "http://www.foo.com/foo.js";
+ v8::ScriptOrigin origin(v8_str(url), v8::Integer::New(isolate, 13));
+ v8::ScriptCompiler::Source script_source(v8_str("var foo;"), origin);
+ Local<Script> script = v8::ScriptCompiler::Compile(
+ isolate, &script_source);
+ Local<Value> script_name = script->GetUnboundScript()->GetScriptName();
+ CHECK(!script_name.IsEmpty());
+ CHECK(script_name->IsString());
+ String::Utf8Value utf8_name(script_name);
+ CHECK_EQ(url, *utf8_name);
+ int line_number = script->GetUnboundScript()->GetLineNumber(0);
+ CHECK_EQ(13, line_number);
+}
+
+
+Local<v8::Context> call_eval_context;
+Local<v8::Function> call_eval_bound_function;
+static void CallEval(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ v8::Context::Scope scope(call_eval_context);
+ args.GetReturnValue().Set(
+ call_eval_bound_function->Call(call_eval_context->Global(), 0, NULL));
+}
+
+
+TEST(CrossActivationEval) {
+ LocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope scope(isolate);
+ {
+ call_eval_context = v8::Context::New(isolate);
+ v8::Context::Scope scope(call_eval_context);
+ call_eval_bound_function =
+ Local<Function>::Cast(CompileRun("eval.bind(this, '1')"));
+ }
+ env->Global()->Set(v8_str("CallEval"),
+ v8::FunctionTemplate::New(isolate, CallEval)->GetFunction());
+ Local<Value> result = CompileRun("CallEval();");
+ CHECK_EQ(result, v8::Integer::New(isolate, 1));
+}