Upgrade to 3.29
Update V8 to 3.29.88.17 and update makefiles to support building on
all the relevant platforms.
Bug: 17370214
Change-Id: Ia3407c157fd8d72a93e23d8318ccaf6ecf77fa4e
diff --git a/test/cctest/test-decls.cc b/test/cctest/test-decls.cc
index aa733c7..34f0b69 100644
--- a/test/cctest/test-decls.cc
+++ b/test/cctest/test-decls.cc
@@ -27,17 +27,18 @@
#include <stdlib.h>
-#include "v8.h"
+#include "src/v8.h"
-#include "heap.h"
-#include "cctest.h"
+#include "src/heap/heap.h"
+#include "test/cctest/cctest.h"
using namespace v8;
enum Expectations {
EXPECT_RESULT,
- EXPECT_EXCEPTION
+ EXPECT_EXCEPTION,
+ EXPECT_ERROR
};
@@ -51,8 +52,11 @@
virtual ~DeclarationContext() {
if (is_initialized_) {
- context_->Exit();
- context_.Dispose();
+ Isolate* isolate = CcTest::isolate();
+ HandleScope scope(isolate);
+ Local<Context> context = Local<Context>::New(isolate, context_);
+ context->Exit();
+ context_.Reset();
}
}
@@ -72,6 +76,10 @@
void InitializeIfNeeded();
+ // Perform optional initialization steps on the context after it has
+ // been created. Defaults to none but may be overwritten.
+ virtual void PostInitializeContext(Handle<Context> context) {}
+
// Get the holder for the interceptor. Default to the instance template
// but may be overwritten.
virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
@@ -80,24 +88,25 @@
// The handlers are called as static functions that forward
// to the instance specific virtual methods.
- static v8::Handle<Value> HandleGet(Local<String> key,
- const AccessorInfo& info);
- static v8::Handle<Value> HandleSet(Local<String> key,
- Local<Value> value,
- const AccessorInfo& info);
- static v8::Handle<Integer> HandleQuery(Local<String> key,
- const AccessorInfo& info);
+ static void HandleGet(Local<String> key,
+ const v8::PropertyCallbackInfo<v8::Value>& info);
+ static void HandleSet(Local<String> key,
+ Local<Value> value,
+ const v8::PropertyCallbackInfo<v8::Value>& info);
+ static void HandleQuery(Local<String> key,
+ const v8::PropertyCallbackInfo<v8::Integer>& info);
+
+ v8::Isolate* isolate() const { return CcTest::isolate(); }
private:
bool is_initialized_;
Persistent<Context> context_;
- Local<String> property_;
int get_count_;
int set_count_;
int query_count_;
- static DeclarationContext* GetInstance(const AccessorInfo& info);
+ static DeclarationContext* GetInstance(Local<Value> data);
};
@@ -109,17 +118,23 @@
void DeclarationContext::InitializeIfNeeded() {
if (is_initialized_) return;
- HandleScope scope;
- Local<FunctionTemplate> function = FunctionTemplate::New();
- Local<Value> data = External::New(this);
+ Isolate* isolate = CcTest::isolate();
+ HandleScope scope(isolate);
+ Local<FunctionTemplate> function = FunctionTemplate::New(isolate);
+ Local<Value> data = External::New(CcTest::isolate(), this);
GetHolder(function)->SetNamedPropertyHandler(&HandleGet,
&HandleSet,
&HandleQuery,
0, 0,
data);
- context_ = Context::New(0, function->InstanceTemplate(), Local<Value>());
- context_->Enter();
+ Local<Context> context = Context::New(isolate,
+ 0,
+ function->InstanceTemplate(),
+ Local<Value>());
+ context_.Reset(isolate, context);
+ context->Enter();
is_initialized_ = true;
+ PostInitializeContext(context);
}
@@ -130,11 +145,18 @@
InitializeIfNeeded();
// A retry after a GC may pollute the counts, so perform gc now
// to avoid that.
- HEAP->CollectGarbage(v8::internal::NEW_SPACE);
- HandleScope scope;
+ CcTest::heap()->CollectGarbage(v8::internal::NEW_SPACE);
+ HandleScope scope(CcTest::isolate());
TryCatch catcher;
catcher.SetVerbose(true);
- Local<Value> result = Script::Compile(String::New(source))->Run();
+ Local<Script> script =
+ Script::Compile(String::NewFromUtf8(CcTest::isolate(), source));
+ if (expectations == EXPECT_ERROR) {
+ CHECK(script.IsEmpty());
+ return;
+ }
+ CHECK(!script.IsEmpty());
+ Local<Value> result = script->Run();
CHECK_EQ(get, get_count());
CHECK_EQ(set, set_count());
CHECK_EQ(query, query_count());
@@ -150,36 +172,42 @@
CHECK_EQ(value, catcher.Exception());
}
}
+ // Clean slate for the next test.
+ CcTest::heap()->CollectAllAvailableGarbage();
}
-v8::Handle<Value> DeclarationContext::HandleGet(Local<String> key,
- const AccessorInfo& info) {
- DeclarationContext* context = GetInstance(info);
+void DeclarationContext::HandleGet(
+ Local<String> key,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ DeclarationContext* context = GetInstance(info.Data());
context->get_count_++;
- return context->Get(key);
+ info.GetReturnValue().Set(context->Get(key));
}
-v8::Handle<Value> DeclarationContext::HandleSet(Local<String> key,
- Local<Value> value,
- const AccessorInfo& info) {
- DeclarationContext* context = GetInstance(info);
+void DeclarationContext::HandleSet(
+ Local<String> key,
+ Local<Value> value,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ DeclarationContext* context = GetInstance(info.Data());
context->set_count_++;
- return context->Set(key, value);
+ info.GetReturnValue().Set(context->Set(key, value));
}
-v8::Handle<Integer> DeclarationContext::HandleQuery(Local<String> key,
- const AccessorInfo& info) {
- DeclarationContext* context = GetInstance(info);
+void DeclarationContext::HandleQuery(
+ Local<String> key,
+ const v8::PropertyCallbackInfo<v8::Integer>& info) {
+ DeclarationContext* context = GetInstance(info.Data());
context->query_count_++;
- return context->Query(key);
+ info.GetReturnValue().Set(context->Query(key));
}
-DeclarationContext* DeclarationContext::GetInstance(const AccessorInfo& info) {
- return static_cast<DeclarationContext*>(External::Unwrap(info.Data()));
+DeclarationContext* DeclarationContext::GetInstance(Local<Value> data) {
+ void* value = Local<External>::Cast(data)->Value();
+ return static_cast<DeclarationContext*>(value);
}
@@ -202,22 +230,20 @@
// Test global declaration of a property the interceptor doesn't know
// about and doesn't handle.
TEST(Unknown) {
- HandleScope scope;
+ HandleScope scope(CcTest::isolate());
+ v8::V8::Initialize();
{ DeclarationContext context;
context.Check("var x; x",
1, // access
- 1, // declaration
- 2, // declaration + initialization
- EXPECT_RESULT, Undefined());
+ 0, 0, EXPECT_RESULT, Undefined(CcTest::isolate()));
}
{ DeclarationContext context;
context.Check("var x = 0; x",
1, // access
- 2, // declaration + initialization
- 2, // declaration + initialization
- EXPECT_RESULT, Number::New(0));
+ 1, // initialization
+ 0, EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
}
{ DeclarationContext context;
@@ -231,77 +257,19 @@
{ DeclarationContext context;
context.Check("const x; x",
1, // access
- 2, // declaration + initialization
- 1, // declaration
- EXPECT_RESULT, Undefined());
+ 0, 0, EXPECT_RESULT, Undefined(CcTest::isolate()));
}
{ DeclarationContext context;
context.Check("const x = 0; x",
1, // access
- 2, // declaration + initialization
- 1, // declaration
- EXPECT_RESULT, Undefined()); // SB 0 - BUG 1213579
+ 0,
+ 0,
+ EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
}
}
-
-class PresentPropertyContext: public DeclarationContext {
- protected:
- virtual v8::Handle<Integer> Query(Local<String> key) {
- return Integer::New(v8::None);
- }
-};
-
-
-
-TEST(Present) {
- HandleScope scope;
-
- { PresentPropertyContext context;
- context.Check("var x; x",
- 1, // access
- 0,
- 2, // declaration + initialization
- EXPECT_EXCEPTION); // x is not defined!
- }
-
- { PresentPropertyContext context;
- context.Check("var x = 0; x",
- 1, // access
- 1, // initialization
- 2, // declaration + initialization
- EXPECT_RESULT, Number::New(0));
- }
-
- { PresentPropertyContext context;
- context.Check("function x() { }; x",
- 1, // access
- 0,
- 0,
- EXPECT_RESULT);
- }
-
- { PresentPropertyContext context;
- context.Check("const x; x",
- 1, // access
- 1, // initialization
- 1, // (re-)declaration
- EXPECT_RESULT, Undefined());
- }
-
- { PresentPropertyContext context;
- context.Check("const x = 0; x",
- 1, // access
- 1, // initialization
- 1, // (re-)declaration
- EXPECT_RESULT, Number::New(0));
- }
-}
-
-
-
class AbsentPropertyContext: public DeclarationContext {
protected:
virtual v8::Handle<Integer> Query(Local<String> key) {
@@ -311,22 +279,21 @@
TEST(Absent) {
- HandleScope scope;
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::V8::Initialize();
+ HandleScope scope(isolate);
{ AbsentPropertyContext context;
context.Check("var x; x",
1, // access
- 1, // declaration
- 2, // declaration + initialization
- EXPECT_RESULT, Undefined());
+ 0, 0, EXPECT_RESULT, Undefined(isolate));
}
{ AbsentPropertyContext context;
context.Check("var x = 0; x",
1, // access
- 2, // declaration + initialization
- 2, // declaration + initialization
- EXPECT_RESULT, Number::New(0));
+ 1, // initialization
+ 0, EXPECT_RESULT, Number::New(isolate, 0));
}
{ AbsentPropertyContext context;
@@ -340,25 +307,19 @@
{ AbsentPropertyContext context;
context.Check("const x; x",
1, // access
- 2, // declaration + initialization
- 1, // declaration
- EXPECT_RESULT, Undefined());
+ 0, 0, EXPECT_RESULT, Undefined(isolate));
}
{ AbsentPropertyContext context;
context.Check("const x = 0; x",
1, // access
- 2, // declaration + initialization
- 1, // declaration
- EXPECT_RESULT, Undefined()); // SB 0 - BUG 1213579
+ 0, 0, EXPECT_RESULT, Number::New(isolate, 0));
}
{ AbsentPropertyContext context;
context.Check("if (false) { var x = 0 }; x",
1, // access
- 1, // declaration
- 1, // declaration + initialization
- EXPECT_RESULT, Undefined());
+ 0, 0, EXPECT_RESULT, Undefined(isolate));
}
}
@@ -386,7 +347,7 @@
// Return that the property is present so we only get the
// setter called when initializing with a value.
state_ = UNKNOWN;
- return Integer::New(v8::None);
+ return Integer::New(isolate(), v8::None);
default:
CHECK(state_ == UNKNOWN);
break;
@@ -401,22 +362,20 @@
TEST(Appearing) {
- HandleScope scope;
+ v8::V8::Initialize();
+ HandleScope scope(CcTest::isolate());
{ AppearingPropertyContext context;
context.Check("var x; x",
1, // access
- 1, // declaration
- 2, // declaration + initialization
- EXPECT_RESULT, Undefined());
+ 0, 0, EXPECT_RESULT, Undefined(CcTest::isolate()));
}
{ AppearingPropertyContext context;
context.Check("var x = 0; x",
1, // access
- 2, // declaration + initialization
- 2, // declaration + initialization
- EXPECT_RESULT, Number::New(0));
+ 1, // initialization
+ 0, EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
}
{ AppearingPropertyContext context;
@@ -430,87 +389,25 @@
{ AppearingPropertyContext context;
context.Check("const x; x",
1, // access
- 2, // declaration + initialization
- 1, // declaration
- EXPECT_RESULT, Undefined());
+ 0, 0, EXPECT_RESULT, Undefined(CcTest::isolate()));
}
{ AppearingPropertyContext context;
context.Check("const x = 0; x",
1, // access
- 2, // declaration + initialization
- 1, // declaration
- EXPECT_RESULT, Undefined());
- // Result is undefined because declaration succeeded but
- // initialization to 0 failed (due to context behavior).
- }
-}
-
-
-
-class ReappearingPropertyContext: public DeclarationContext {
- public:
- enum State {
- DECLARE,
- DONT_DECLARE,
- INITIALIZE,
- UNKNOWN
- };
-
- ReappearingPropertyContext() : state_(DECLARE) { }
-
- protected:
- virtual v8::Handle<Integer> Query(Local<String> key) {
- switch (state_) {
- case DECLARE:
- // Force the first declaration by returning that
- // the property is absent.
- state_ = DONT_DECLARE;
- return Handle<Integer>();
- case DONT_DECLARE:
- // Ignore the second declaration by returning
- // that the property is already there.
- state_ = INITIALIZE;
- return Integer::New(v8::None);
- case INITIALIZE:
- // Force an initialization by returning that
- // the property is absent. This will make sure
- // that the setter is called and it will not
- // lead to redeclaration conflicts (yet).
- state_ = UNKNOWN;
- return Handle<Integer>();
- default:
- CHECK(state_ == UNKNOWN);
- break;
- }
- // Do the lookup in the object.
- return Handle<Integer>();
- }
-
- private:
- State state_;
-};
-
-
-TEST(Reappearing) {
- HandleScope scope;
-
- { ReappearingPropertyContext context;
- context.Check("const x; var x = 0",
- 0,
- 3, // const declaration+initialization, var initialization
- 3, // 2 x declaration + var initialization
- EXPECT_RESULT, Undefined());
+ 0, 0, EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
}
}
class ExistsInPrototypeContext: public DeclarationContext {
+ public:
+ ExistsInPrototypeContext() { InitializeIfNeeded(); }
protected:
virtual v8::Handle<Integer> Query(Local<String> key) {
// Let it seem that the property exists in the prototype object.
- return Integer::New(v8::None);
+ return Integer::New(isolate(), v8::None);
}
// Use the prototype as the holder for the interceptors.
@@ -521,48 +418,45 @@
TEST(ExistsInPrototype) {
- HandleScope scope;
+ HandleScope scope(CcTest::isolate());
// Sanity check to make sure that the holder of the interceptor
// really is the prototype object.
{ ExistsInPrototypeContext context;
- context.Check("this.x = 87; this.x",
- 0,
- 0,
- 0,
- EXPECT_RESULT, Number::New(87));
+ context.Check("this.x = 87; this.x", 0, 0, 1, EXPECT_RESULT,
+ Number::New(CcTest::isolate(), 87));
}
{ ExistsInPrototypeContext context;
context.Check("var x; x",
- 1, // get
0,
- 1, // declaration
- EXPECT_EXCEPTION);
+ 0,
+ 0,
+ EXPECT_RESULT, Undefined(CcTest::isolate()));
}
{ ExistsInPrototypeContext context;
context.Check("var x = 0; x",
0,
0,
- 1, // declaration
- EXPECT_RESULT, Number::New(0));
+ 0,
+ EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
}
{ ExistsInPrototypeContext context;
context.Check("const x; x",
0,
0,
- 1, // declaration
- EXPECT_RESULT, Undefined());
+ 0,
+ EXPECT_RESULT, Undefined(CcTest::isolate()));
}
{ ExistsInPrototypeContext context;
context.Check("const x = 0; x",
0,
0,
- 1, // declaration
- EXPECT_RESULT, Number::New(0));
+ 0,
+ EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
}
}
@@ -583,13 +477,239 @@
TEST(AbsentInPrototype) {
- HandleScope scope;
+ v8::V8::Initialize();
+ HandleScope scope(CcTest::isolate());
{ AbsentInPrototypeContext context;
context.Check("if (false) { var x = 0; }; x",
0,
0,
- 1, // declaration
- EXPECT_RESULT, Undefined());
+ 0,
+ EXPECT_RESULT, Undefined(CcTest::isolate()));
+ }
+}
+
+
+
+class ExistsInHiddenPrototypeContext: public DeclarationContext {
+ public:
+ ExistsInHiddenPrototypeContext() {
+ hidden_proto_ = FunctionTemplate::New(CcTest::isolate());
+ hidden_proto_->SetHiddenPrototype(true);
+ }
+
+ protected:
+ virtual v8::Handle<Integer> Query(Local<String> key) {
+ // Let it seem that the property exists in the hidden prototype object.
+ return Integer::New(isolate(), v8::None);
+ }
+
+ // Install the hidden prototype after the global object has been created.
+ virtual void PostInitializeContext(Handle<Context> context) {
+ Local<Object> global_object = context->Global();
+ Local<Object> hidden_proto = hidden_proto_->GetFunction()->NewInstance();
+ Local<Object> inner_global =
+ Local<Object>::Cast(global_object->GetPrototype());
+ inner_global->SetPrototype(hidden_proto);
+ }
+
+ // Use the hidden prototype as the holder for the interceptors.
+ virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
+ return hidden_proto_->InstanceTemplate();
+ }
+
+ private:
+ Local<FunctionTemplate> hidden_proto_;
+};
+
+
+TEST(ExistsInHiddenPrototype) {
+ HandleScope scope(CcTest::isolate());
+
+ { ExistsInHiddenPrototypeContext context;
+ context.Check("var x; x", 0, 0, 0, EXPECT_RESULT,
+ Undefined(CcTest::isolate()));
+ }
+
+ { ExistsInHiddenPrototypeContext context;
+ context.Check("var x = 0; x", 0, 0, 0, EXPECT_RESULT,
+ Number::New(CcTest::isolate(), 0));
+ }
+
+ { ExistsInHiddenPrototypeContext context;
+ context.Check("function x() { }; x",
+ 0,
+ 0,
+ 0,
+ EXPECT_RESULT);
+ }
+
+ // TODO(mstarzinger): The semantics of global const is vague.
+ { ExistsInHiddenPrototypeContext context;
+ context.Check("const x; x", 0, 0, 0, EXPECT_RESULT,
+ Undefined(CcTest::isolate()));
+ }
+
+ // TODO(mstarzinger): The semantics of global const is vague.
+ { ExistsInHiddenPrototypeContext context;
+ context.Check("const x = 0; x", 0, 0, 0, EXPECT_RESULT,
+ Number::New(CcTest::isolate(), 0));
+ }
+}
+
+
+
+class SimpleContext {
+ public:
+ SimpleContext()
+ : handle_scope_(CcTest::isolate()),
+ context_(Context::New(CcTest::isolate())) {
+ context_->Enter();
+ }
+
+ ~SimpleContext() {
+ context_->Exit();
+ }
+
+ void Check(const char* source,
+ Expectations expectations,
+ v8::Handle<Value> value = Local<Value>()) {
+ HandleScope scope(context_->GetIsolate());
+ TryCatch catcher;
+ catcher.SetVerbose(true);
+ Local<Script> script =
+ Script::Compile(String::NewFromUtf8(context_->GetIsolate(), source));
+ if (expectations == EXPECT_ERROR) {
+ CHECK(script.IsEmpty());
+ return;
+ }
+ CHECK(!script.IsEmpty());
+ Local<Value> result = script->Run();
+ if (expectations == EXPECT_RESULT) {
+ CHECK(!catcher.HasCaught());
+ if (!value.IsEmpty()) {
+ CHECK_EQ(value, result);
+ }
+ } else {
+ CHECK(expectations == EXPECT_EXCEPTION);
+ CHECK(catcher.HasCaught());
+ if (!value.IsEmpty()) {
+ CHECK_EQ(value, catcher.Exception());
+ }
+ }
+ }
+
+ private:
+ HandleScope handle_scope_;
+ Local<Context> context_;
+};
+
+
+TEST(CrossScriptReferences) {
+ v8::Isolate* isolate = CcTest::isolate();
+ HandleScope scope(isolate);
+
+ { SimpleContext context;
+ context.Check("var x = 1; x",
+ EXPECT_RESULT, Number::New(isolate, 1));
+ context.Check("var x = 2; x",
+ EXPECT_RESULT, Number::New(isolate, 2));
+ context.Check("const x = 3; x", EXPECT_EXCEPTION);
+ context.Check("const x = 4; x", EXPECT_EXCEPTION);
+ context.Check("x = 5; x",
+ EXPECT_RESULT, Number::New(isolate, 5));
+ context.Check("var x = 6; x",
+ EXPECT_RESULT, Number::New(isolate, 6));
+ context.Check("this.x",
+ EXPECT_RESULT, Number::New(isolate, 6));
+ context.Check("function x() { return 7 }; x()",
+ EXPECT_RESULT, Number::New(isolate, 7));
+ }
+
+ { SimpleContext context;
+ context.Check("const x = 1; x",
+ EXPECT_RESULT, Number::New(isolate, 1));
+ context.Check("var x = 2; x", // assignment ignored
+ EXPECT_RESULT, Number::New(isolate, 1));
+ context.Check("const x = 3; x", EXPECT_EXCEPTION);
+ context.Check("x = 4; x", // assignment ignored
+ EXPECT_RESULT, Number::New(isolate, 1));
+ context.Check("var x = 5; x", // assignment ignored
+ EXPECT_RESULT, Number::New(isolate, 1));
+ context.Check("this.x",
+ EXPECT_RESULT, Number::New(isolate, 1));
+ context.Check("function x() { return 7 }; x",
+ EXPECT_EXCEPTION);
+ }
+}
+
+
+TEST(CrossScriptReferencesHarmony) {
+ i::FLAG_use_strict = true;
+ i::FLAG_harmony_scoping = true;
+ i::FLAG_harmony_modules = true;
+
+ v8::Isolate* isolate = CcTest::isolate();
+ HandleScope scope(isolate);
+
+ const char* decs[] = {
+ "var x = 1; x", "x", "this.x",
+ "function x() { return 1 }; x()", "x()", "this.x()",
+ "let x = 1; x", "x", "this.x",
+ "const x = 1; x", "x", "this.x",
+ "module x { export let a = 1 }; x.a", "x.a", "this.x.a",
+ NULL
+ };
+
+ for (int i = 0; decs[i] != NULL; i += 3) {
+ SimpleContext context;
+ context.Check(decs[i], EXPECT_RESULT, Number::New(isolate, 1));
+ context.Check(decs[i+1], EXPECT_RESULT, Number::New(isolate, 1));
+ // TODO(rossberg): The current ES6 draft spec does not reflect lexical
+ // bindings on the global object. However, this will probably change, in
+ // which case we reactivate the following test.
+ if (i/3 < 2) {
+ context.Check(decs[i+2], EXPECT_RESULT, Number::New(isolate, 1));
+ }
+ }
+}
+
+
+TEST(CrossScriptConflicts) {
+ i::FLAG_use_strict = true;
+ i::FLAG_harmony_scoping = true;
+ i::FLAG_harmony_modules = true;
+
+ HandleScope scope(CcTest::isolate());
+
+ const char* firsts[] = {
+ "var x = 1; x",
+ "function x() { return 1 }; x()",
+ "let x = 1; x",
+ "const x = 1; x",
+ "module x { export let a = 1 }; x.a",
+ NULL
+ };
+ const char* seconds[] = {
+ "var x = 2; x",
+ "function x() { return 2 }; x()",
+ "let x = 2; x",
+ "const x = 2; x",
+ "module x { export let a = 2 }; x.a",
+ NULL
+ };
+
+ for (int i = 0; firsts[i] != NULL; ++i) {
+ for (int j = 0; seconds[j] != NULL; ++j) {
+ SimpleContext context;
+ context.Check(firsts[i], EXPECT_RESULT,
+ Number::New(CcTest::isolate(), 1));
+ // TODO(rossberg): All tests should actually be errors in Harmony,
+ // but we currently do not detect the cases where the first declaration
+ // is not lexical.
+ context.Check(seconds[j],
+ i < 2 ? EXPECT_RESULT : EXPECT_ERROR,
+ Number::New(CcTest::isolate(), 2));
+ }
}
}