Revision: 12398
Author: [email protected]
Date: Tue Aug 28 04:25:08 2012
Log: Allocate block-scoped global bindings to global context.
- The global object has a reference to the current global scope chain.
Running a script adds to the chain if it contains global lexical
declarations.
- Scripts are executed relative to a global, not a native context.
- Harmony let and const bindings are allocated to the innermost global
context;
var and function still live on the global object.
(Lexical bindings are not reflected on the global object at all,
but that will probably change later using accessors, as for modules.)
- Compilation of scripts now needs a (global) context (previously only eval
did).
- The global scope chain represents one logical scope, so collision tests
take
the chain into account.
[email protected]
BUG=
Review URL: https://chromiumcodereview.appspot.com/10872084
http://code.google.com/p/v8/source/detail?r=12398
Modified:
/branches/bleeding_edge/src/api.cc
/branches/bleeding_edge/src/bootstrapper.cc
/branches/bleeding_edge/src/bootstrapper.h
/branches/bleeding_edge/src/compiler.cc
/branches/bleeding_edge/src/compiler.h
/branches/bleeding_edge/src/heap.cc
/branches/bleeding_edge/src/isolate.cc
/branches/bleeding_edge/src/isolate.h
/branches/bleeding_edge/src/objects-inl.h
/branches/bleeding_edge/src/objects.cc
/branches/bleeding_edge/src/objects.h
/branches/bleeding_edge/src/parser.cc
/branches/bleeding_edge/src/rewriter.cc
/branches/bleeding_edge/src/runtime.cc
/branches/bleeding_edge/src/scopes.cc
/branches/bleeding_edge/src/variables.cc
/branches/bleeding_edge/src/variables.h
/branches/bleeding_edge/test/cctest/test-decls.cc
/branches/bleeding_edge/test/mjsunit/harmony/block-conflicts.js
=======================================
--- /branches/bleeding_edge/src/api.cc Tue Aug 28 03:49:23 2012
+++ /branches/bleeding_edge/src/api.cc Tue Aug 28 04:25:08 2012
@@ -1539,7 +1539,7 @@
name_obj,
line_offset,
column_offset,
- isolate->native_context(),
+ isolate->global_context(),
NULL,
pre_data_impl,
Utils::OpenHandle(*script_data),
@@ -1577,7 +1577,7 @@
i::Handle<i::JSFunction> result =
isolate->factory()->NewFunctionFromSharedFunctionInfo(
function,
- isolate->native_context());
+ isolate->global_context());
return Local<Script>(ToApi<Script>(result));
}
@@ -1604,7 +1604,7 @@
i::Handle<i::SharedFunctionInfo>
function_info(i::SharedFunctionInfo::cast(*obj), isolate);
fun = isolate->factory()->NewFunctionFromSharedFunctionInfo(
- function_info, isolate->native_context());
+ function_info, isolate->global_context());
} else {
fun = i::Handle<i::JSFunction>(i::JSFunction::cast(*obj), isolate);
}
@@ -4536,9 +4536,9 @@
i::Object** ctx = reinterpret_cast<i::Object**>(this);
i::Handle<i::Context> context =
i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
- isolate->bootstrapper()->ReattachGlobal(
- context,
- Utils::OpenHandle(*global_object));
+ i::Handle<i::JSGlobalProxy> global_proxy =
+ i::Handle<i::JSGlobalProxy>::cast(Utils::OpenHandle(*global_object));
+ isolate->bootstrapper()->ReattachGlobal(context, global_proxy);
}
=======================================
--- /branches/bleeding_edge/src/bootstrapper.cc Tue Aug 28 03:49:23 2012
+++ /branches/bleeding_edge/src/bootstrapper.cc Tue Aug 28 04:25:08 2012
@@ -327,23 +327,20 @@
void Bootstrapper::DetachGlobal(Handle<Context> env) {
Factory* factory = env->GetIsolate()->factory();
- JSGlobalProxy::cast(env->global_proxy())->
- set_native_context(*factory->null_value());
- SetObjectPrototype(Handle<JSObject>(env->global_proxy()),
- factory->null_value());
+ Handle<JSGlobalProxy>
global_proxy(JSGlobalProxy::cast(env->global_proxy()));
+ global_proxy->set_native_context(*factory->null_value());
+ SetObjectPrototype(global_proxy, factory->null_value());
env->set_global_proxy(env->global_object());
env->global_object()->set_global_receiver(env->global_object());
}
void Bootstrapper::ReattachGlobal(Handle<Context> env,
- Handle<Object> global_object) {
- ASSERT(global_object->IsJSGlobalProxy());
- Handle<JSGlobalProxy> global =
Handle<JSGlobalProxy>::cast(global_object);
- env->global_object()->set_global_receiver(*global);
- env->set_global_proxy(*global);
- SetObjectPrototype(global, Handle<JSObject>(env->global_object()));
- global->set_native_context(*env);
+ Handle<JSGlobalProxy> global_proxy) {
+ env->global_object()->set_global_receiver(*global_proxy);
+ env->set_global_proxy(*global_proxy);
+ SetObjectPrototype(global_proxy, Handle<JSObject>(env->global_object()));
+ global_proxy->set_native_context(*env);
}
@@ -797,6 +794,7 @@
Handle<JSGlobalProxy> global_proxy) {
// Set the native context for the global object.
inner_global->set_native_context(*native_context());
+ inner_global->set_global_context(*native_context());
inner_global->set_global_receiver(*global_proxy);
global_proxy->set_native_context(*native_context());
native_context()->set_global_proxy(*global_proxy);
@@ -1443,6 +1441,7 @@
Handle<JSBuiltinsObject>::cast(factory()->NewGlobalObject(builtins_fun));
builtins->set_builtins(*builtins);
builtins->set_native_context(*native_context());
+ builtins->set_global_context(*native_context());
builtins->set_global_receiver(*builtins);
// Set up the 'global' properties of the builtins object. The
=======================================
--- /branches/bleeding_edge/src/bootstrapper.h Fri Aug 17 02:03:08 2012
+++ /branches/bleeding_edge/src/bootstrapper.h Tue Aug 28 04:25:08 2012
@@ -104,7 +104,7 @@
void DetachGlobal(Handle<Context> env);
// Reattach an outer global object to an environment.
- void ReattachGlobal(Handle<Context> env, Handle<Object> global_object);
+ void ReattachGlobal(Handle<Context> env, Handle<JSGlobalProxy>
global_proxy);
// Traverses the pointers for memory management.
void Iterate(ObjectVisitor* v);
=======================================
--- /branches/bleeding_edge/src/compiler.cc Tue Aug 28 03:49:23 2012
+++ /branches/bleeding_edge/src/compiler.cc Tue Aug 28 04:25:08 2012
@@ -98,6 +98,7 @@
script_(Handle<Script>(Script::cast(shared_info_->script()))),
extension_(NULL),
pre_parse_data_(NULL),
+ context_(closure->context()),
osr_ast_id_(BailoutId::None()),
zone_(zone),
deferred_handles_(NULL) {
@@ -292,6 +293,7 @@
// optimized code.
unoptimized.SetFunction(info()->function());
unoptimized.SetScope(info()->scope());
+ unoptimized.SetContext(info()->context());
if (should_recompile) unoptimized.EnableDeoptimizationSupport();
bool succeeded = FullCodeGenerator::MakeCode(&unoptimized);
if (should_recompile) {
@@ -595,6 +597,7 @@
info.MarkAsGlobal();
info.SetExtension(extension);
info.SetPreParseData(pre_data);
+ info.SetContext(context);
if (FLAG_use_strict) {
info.SetLanguageMode(FLAG_harmony_scoping ? EXTENDED_MODE :
STRICT_MODE);
}
@@ -643,7 +646,7 @@
info.MarkAsEval();
if (is_global) info.MarkAsGlobal();
info.SetLanguageMode(language_mode);
- info.SetCallingContext(context);
+ info.SetContext(context);
result = MakeFunctionInfo(&info);
if (!result.is_null()) {
// Explicitly disable optimization for eval code. We're not yet
prepared
=======================================
--- /branches/bleeding_edge/src/compiler.h Tue Aug 28 03:49:23 2012
+++ /branches/bleeding_edge/src/compiler.h Tue Aug 28 04:25:08 2012
@@ -72,7 +72,7 @@
Handle<Script> script() const { return script_; }
v8::Extension* extension() const { return extension_; }
ScriptDataImpl* pre_parse_data() const { return pre_parse_data_; }
- Handle<Context> calling_context() const { return calling_context_; }
+ Handle<Context> context() const { return context_; }
BailoutId osr_ast_id() const { return osr_ast_id_; }
void MarkAsEval() {
@@ -120,9 +120,8 @@
ASSERT(!is_lazy());
pre_parse_data_ = pre_parse_data;
}
- void SetCallingContext(Handle<Context> context) {
- ASSERT(is_eval());
- calling_context_ = context;
+ void SetContext(Handle<Context> context) {
+ context_ = context;
}
void MarkCompilingForDebugging(Handle<Code> current_code) {
ASSERT(mode_ != OPTIMIZE);
@@ -180,7 +179,7 @@
void SaveHandles() {
SaveHandle(&closure_);
SaveHandle(&shared_info_);
- SaveHandle(&calling_context_);
+ SaveHandle(&context_);
SaveHandle(&script_);
}
@@ -262,9 +261,9 @@
v8::Extension* extension_;
ScriptDataImpl* pre_parse_data_;
- // The context of the caller is needed for eval code, and will be a null
- // handle otherwise.
- Handle<Context> calling_context_;
+ // The context of the caller for eval code, and the global context for a
+ // global script. Will be a null handle otherwise.
+ Handle<Context> context_;
// Compilation mode flag and whether deoptimization is allowed.
Mode mode_;
=======================================
--- /branches/bleeding_edge/src/heap.cc Mon Aug 27 12:47:02 2012
+++ /branches/bleeding_edge/src/heap.cc Tue Aug 28 04:25:08 2012
@@ -4919,7 +4919,9 @@
Context* context = reinterpret_cast<Context*>(result);
context->set_map_no_write_barrier(global_context_map());
context->set_closure(function);
+ context->set_previous(function->context());
context->set_extension(scope_info);
+ context->set_global_object(function->context()->global_object());
ASSERT(context->IsGlobalContext());
ASSERT(result->IsContext());
return context;
=======================================
--- /branches/bleeding_edge/src/isolate.cc Mon Aug 27 12:47:02 2012
+++ /branches/bleeding_edge/src/isolate.cc Tue Aug 28 04:25:08 2012
@@ -1328,6 +1328,12 @@
GlobalObject* global = thread_local_top()->context_->global_object();
return Handle<Context>(global->native_context());
}
+
+
+Handle<Context> Isolate::global_context() {
+ GlobalObject* global = thread_local_top()->context_->global_object();
+ return Handle<Context>(global->global_context());
+}
Handle<Context> Isolate::GetCallingNativeContext() {
=======================================
--- /branches/bleeding_edge/src/isolate.h Tue Aug 28 02:37:41 2012
+++ /branches/bleeding_edge/src/isolate.h Tue Aug 28 04:25:08 2012
@@ -764,8 +764,9 @@
void IterateThread(ThreadVisitor* v, char* t);
- // Returns the current native context.
+ // Returns the current native and global context.
Handle<Context> native_context();
+ Handle<Context> global_context();
// Returns the native context of the calling JavaScript code. That
// is, the native context of the top-most JavaScript frame.
=======================================
--- /branches/bleeding_edge/src/objects-inl.h Mon Aug 27 08:17:14 2012
+++ /branches/bleeding_edge/src/objects-inl.h Tue Aug 28 04:25:08 2012
@@ -3689,6 +3689,7 @@
ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
ACCESSORS(GlobalObject, native_context, Context, kNativeContextOffset)
+ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
ACCESSORS(JSGlobalProxy, native_context, Object, kNativeContextOffset)
=======================================
--- /branches/bleeding_edge/src/objects.cc Tue Aug 28 03:49:23 2012
+++ /branches/bleeding_edge/src/objects.cc Tue Aug 28 04:25:08 2012
@@ -11998,20 +11998,15 @@
shared,
CurrentGlobalLanguageMode(),
RelocInfo::kNoPosition);
- Object* obj;
- { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
- if (!maybe_obj->ToObject(&obj)) return maybe_obj;
- }
-
- CompilationCacheTable* cache =
- reinterpret_cast<CompilationCacheTable*>(obj);
- int entry = cache->FindInsertionEntry(key.Hash());
+ CompilationCacheTable* cache;
+ MaybeObject* maybe_cache = EnsureCapacity(1, &key);
+ if (!maybe_cache->To(&cache)) return maybe_cache;
Object* k;
- { MaybeObject* maybe_k = key.AsObject();
- if (!maybe_k->ToObject(&k)) return maybe_k;
- }
+ MaybeObject* maybe_k = key.AsObject();
+ if (!maybe_k->To(&k)) return maybe_k;
+ int entry = cache->FindInsertionEntry(key.Hash());
cache->set(EntryToIndex(entry), k);
cache->set(EntryToIndex(entry) + 1, value);
cache->ElementAdded();
=======================================
--- /branches/bleeding_edge/src/objects.h Tue Aug 28 03:49:23 2012
+++ /branches/bleeding_edge/src/objects.h Tue Aug 28 04:25:08 2012
@@ -6198,6 +6198,9 @@
// [native context]: the natives corresponding to this global object.
DECL_ACCESSORS(native_context, Context)
+ // [global context]: the most recent (i.e. innermost) global context.
+ DECL_ACCESSORS(global_context, Context)
+
// [global receiver]: the global receiver object of the context
DECL_ACCESSORS(global_receiver, JSObject)
@@ -6227,7 +6230,8 @@
// Layout description.
static const int kBuiltinsOffset = JSObject::kHeaderSize;
static const int kNativeContextOffset = kBuiltinsOffset + kPointerSize;
- static const int kGlobalReceiverOffset = kNativeContextOffset +
kPointerSize;
+ static const int kGlobalContextOffset = kNativeContextOffset +
kPointerSize;
+ static const int kGlobalReceiverOffset = kGlobalContextOffset +
kPointerSize;
static const int kHeaderSize = kGlobalReceiverOffset + kPointerSize;
private:
=======================================
--- /branches/bleeding_edge/src/parser.cc Thu Aug 16 04:54:48 2012
+++ /branches/bleeding_edge/src/parser.cc Tue Aug 28 04:25:08 2012
@@ -624,19 +624,20 @@
FunctionLiteral* result = NULL;
{ Scope* scope = NewScope(top_scope_, GLOBAL_SCOPE);
info->SetGlobalScope(scope);
+ if (!info->context().is_null()) {
+ scope = Scope::DeserializeScopeChain(*info->context(), scope,
zone());
+ }
if (info->is_eval()) {
- Handle<SharedFunctionInfo> shared = info->shared_info();
- if (!info->is_global() && (shared.is_null() ||
shared->is_function())) {
- scope = Scope::DeserializeScopeChain(*info->calling_context(),
scope,
- zone());
- }
if (!scope->is_global_scope() || info->language_mode() !=
CLASSIC_MODE) {
scope = NewScope(scope, EVAL_SCOPE);
}
+ } else if (info->is_global()) {
+ scope = NewScope(scope, GLOBAL_SCOPE);
}
scope->set_start_position(0);
scope->set_end_position(source->length());
- FunctionState function_state(this, scope, isolate());
+
+ FunctionState function_state(this, scope, isolate()); //
Enters 'scope'.
top_scope_->SetLanguageMode(info->language_mode());
ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16,
zone());
bool ok = true;
@@ -1787,50 +1788,58 @@
declaration_scope->is_strict_or_extended_eval_scope() ||
declaration_scope->is_block_scope() ||
declaration_scope->is_module_scope() ||
- declaration->AsModuleDeclaration() != NULL) {
+ declaration_scope->is_global_scope()) {
// Declare the variable in the declaration scope.
- var = declaration_scope->LocalLookup(name);
+ // For the global scope, we have to check for collisions with earlier
+ // (i.e., enclosing) global scopes, to maintain the illusion of a
single
+ // global scope.
+ var = declaration_scope->is_global_scope()
+ ? declaration_scope->Lookup(name)
+ : declaration_scope->LocalLookup(name);
if (var == NULL) {
// Declare the name.
var = declaration_scope->DeclareLocal(
name, mode, declaration->initialization(), proxy->interface());
- } else {
+ } else if ((mode != VAR || var->mode() != VAR) &&
+ (!declaration_scope->is_global_scope() ||
+ (mode != VAR && mode != CONST) ||
+ (var->mode() != VAR && var->mode() != CONST))) {
// The name was declared in this scope before; check for conflicting
// re-declarations. We have a conflict if either of the declarations
is
- // not a var. There is similar code in runtime.cc in the Declare
+ // not a var (in the global scope, we also have to ignore legacy
const for
+ // compatibility). There is similar code in runtime.cc in the Declare
// functions. The function CheckNonConflictingScope checks for
conflicting
// var and let bindings from different scopes whereas this is a
check for
// conflicting declarations within the same scope. This check also
covers
+ // the special case
//
// function () { let x; { var x; } }
//
// because the var declaration is hoisted to the function scope
where 'x'
// is already bound.
- if ((mode != VAR) || (var->mode() != VAR)) {
- // We only have vars, consts and lets in declarations.
- ASSERT(var->mode() == VAR ||
- var->mode() == CONST ||
- var->mode() == CONST_HARMONY ||
- var->mode() == LET);
- if (is_extended_mode()) {
- // In harmony mode we treat re-declarations as early errors. See
- // ES5 16 for a definition of early errors.
- SmartArrayPointer<char> c_string =
name->ToCString(DISALLOW_NULLS);
- const char* elms[2] = { "Variable", *c_string };
- Vector<const char*> args(elms, 2);
- ReportMessage("redeclaration", args);
- *ok = false;
- return;
- }
- const char* type = (var->mode() == VAR)
- ? "var" : var->is_const_mode() ? "const" : "let";
- Handle<String> type_string =
- isolate()->factory()->NewStringFromUtf8(CStrVector(type),
TENURED);
- Expression* expression =
- NewThrowTypeError(isolate()->factory()->redeclaration_symbol(),
- type_string, name);
- declaration_scope->SetIllegalRedeclaration(expression);
+ // We only have vars, consts and lets in declarations.
+ ASSERT(var->mode() == VAR ||
+ var->mode() == CONST ||
+ var->mode() == CONST_HARMONY ||
+ var->mode() == LET);
+ if (is_extended_mode()) {
+ // In harmony mode we treat re-declarations as early errors. See
+ // ES5 16 for a definition of early errors.
+ SmartArrayPointer<char> c_string = name->ToCString(DISALLOW_NULLS);
+ const char* elms[2] = { "Variable", *c_string };
+ Vector<const char*> args(elms, 2);
+ ReportMessage("redeclaration", args);
+ *ok = false;
+ return;
}
+ const char* type =
+ (var->mode() == VAR) ? "var" :
var->is_const_mode() ? "const" : "let";
+ Handle<String> type_string =
+ isolate()->factory()->NewStringFromUtf8(CStrVector(type),
TENURED);
+ Expression* expression =
+ NewThrowTypeError(isolate()->factory()->redeclaration_symbol(),
+ type_string, name);
+ declaration_scope->SetIllegalRedeclaration(expression);
}
}
@@ -1852,8 +1861,7 @@
// Runtime::DeclareContextSlot() calls.
declaration_scope->AddDeclaration(declaration);
- if ((mode == CONST || mode == CONST_HARMONY) &&
- declaration_scope->is_global_scope()) {
+ if (mode == CONST && declaration_scope->is_global_scope()) {
// For global const variables we bind the proxy to a variable.
ASSERT(resolve); // should be set by all callers
Variable::Kind kind = Variable::NORMAL;
@@ -2004,9 +2012,12 @@
FunctionLiteral::DECLARATION,
CHECK_OK);
// Even if we're not at the top-level of the global or a function
- // scope, we treat is as such and introduce the function with it's
+ // scope, we treat it as such and introduce the function with its
// initial value upon entering the corresponding scope.
- VariableMode mode = is_extended_mode() ? LET : VAR;
+ // In extended mode, a function behaves as a lexical binding, except in
the
+ // global scope.
+ VariableMode mode =
+ is_extended_mode() && !top_scope_->is_global_scope() ? LET : VAR;
VariableProxy* proxy = NewUnresolved(name, mode, Interface::NewValue());
Declaration* declaration =
factory()->NewFunctionDeclaration(proxy, mode, fun, top_scope_);
@@ -2329,7 +2340,8 @@
// declaration statement has been executed. This is important in
// browsers where the global object (window) has lots of
// properties defined in prototype objects.
- if (initialization_scope->is_global_scope()) {
+ if (initialization_scope->is_global_scope() &&
+ mode != LET && mode != CONST_HARMONY) {
// Compute the arguments for the runtime call.
ZoneList<Expression*>* arguments =
new(zone()) ZoneList<Expression*>(3, zone());
=======================================
--- /branches/bleeding_edge/src/rewriter.cc Fri Jul 13 02:29:43 2012
+++ /branches/bleeding_edge/src/rewriter.cc Tue Aug 28 04:25:08 2012
@@ -230,8 +230,8 @@
#undef DEF_VISIT
-// Assumes code has been parsed and scopes have been analyzed. Mutates the
-// AST, so the AST should not continue to be used in the case of failure.
+// Assumes code has been parsed. Mutates the AST, so the AST should not
+// continue to be used in the case of failure.
bool Rewriter::Rewrite(CompilationInfo* info) {
FunctionLiteral* function = info->function();
ASSERT(function != NULL);
=======================================
--- /branches/bleeding_edge/src/runtime.cc Tue Aug 28 02:37:41 2012
+++ /branches/bleeding_edge/src/runtime.cc Tue Aug 28 04:25:08 2012
@@ -8378,7 +8378,10 @@
isolate->heap()->AllocateGlobalContext(function, scope_info);
if (!maybe_result->To(&result)) return maybe_result;
+ ASSERT(function->context() == isolate->context());
+ ASSERT(function->context()->global_object() == result->global_object());
isolate->set_context(result);
+ result->global_object()->set_global_context(result);
return result; // non-failure
}
@@ -10901,7 +10904,7 @@
} else {
ASSERT(scope_info->Type() == EVAL_SCOPE);
info.MarkAsEval();
- info.SetCallingContext(Handle<Context>(function_->context()));
+ info.SetContext(Handle<Context>(function_->context()));
}
if (ParserApi::Parse(&info, kNoParsingFlags) &&
Scope::Analyze(&info)) {
scope = info.function()->scope();
=======================================
--- /branches/bleeding_edge/src/scopes.cc Mon Aug 27 02:40:26 2012
+++ /branches/bleeding_edge/src/scopes.cc Tue Aug 28 04:25:08 2012
@@ -118,10 +118,8 @@
already_resolved_(false),
zone_(zone) {
SetDefaults(type, outer_scope, Handle<ScopeInfo>::null());
- // At some point we might want to provide outer scopes to
- // eval scopes (by walking the stack and reading the scope info).
- // In that case, the ASSERT below needs to be adjusted.
- ASSERT_EQ(type == GLOBAL_SCOPE, outer_scope == NULL);
+ // The outermost scope must be a global scope.
+ ASSERT(type == GLOBAL_SCOPE || outer_scope != NULL);
ASSERT(!HasIllegalRedeclaration());
}
@@ -1041,7 +1039,7 @@
// gave up on it (e.g. by encountering a local with the same in the
outer
// scope which was not promoted to a context, this can happen if we
use
// debugger to evaluate arbitrary expressions at a break point).
- if (var->is_global()) {
+ if (var->IsGlobalObjectProperty()) {
var = NonLocal(proxy->name(), DYNAMIC_GLOBAL);
} else if (var->is_dynamic()) {
var = NonLocal(proxy->name(), DYNAMIC);
@@ -1162,11 +1160,12 @@
scope_contains_with_ ||
is_catch_scope() ||
is_block_scope() ||
- is_module_scope())) {
+ is_module_scope() ||
+ is_global_scope())) {
var->set_is_used(true);
}
// Global variables do not need to be allocated.
- return !var->is_global() && var->is_used();
+ return !var->IsGlobalObjectProperty() && var->is_used();
}
@@ -1180,11 +1179,12 @@
// catch-bound variables are always allocated in a context.
if (var->mode() == TEMPORARY) return false;
if (is_catch_scope() || is_block_scope() || is_module_scope()) return
true;
+ if (is_global_scope() && (var->mode() == LET || var->mode() ==
CONST_HARMONY))
+ return true;
return var->has_forced_context_allocation() ||
scope_calls_eval_ ||
inner_scope_calls_eval_ ||
- scope_contains_with_ ||
- var->is_global();
+ scope_contains_with_;
}
=======================================
--- /branches/bleeding_edge/src/variables.cc Thu Mar 8 05:03:07 2012
+++ /branches/bleeding_edge/src/variables.cc Tue Aug 28 04:25:08 2012
@@ -81,10 +81,11 @@
}
-bool Variable::is_global() const {
+bool Variable::IsGlobalObjectProperty() const {
// Temporaries are never global, they must always be allocated in the
// activation frame.
- return mode_ != TEMPORARY && scope_ != NULL && scope_->is_global_scope();
+ return mode_ != TEMPORARY && mode_ != LET && mode_ != CONST_HARMONY
+ && scope_ != NULL && scope_->is_global_scope();
}
=======================================
--- /branches/bleeding_edge/src/variables.h Thu Aug 23 01:15:38 2012
+++ /branches/bleeding_edge/src/variables.h Tue Aug 28 04:25:08 2012
@@ -118,6 +118,7 @@
bool IsStackAllocated() const { return IsParameter() || IsStackLocal(); }
bool IsContextSlot() const { return location_ == CONTEXT; }
bool IsLookupSlot() const { return location_ == LOOKUP; }
+ bool IsGlobalObjectProperty() const;
bool is_dynamic() const {
return (mode_ == DYNAMIC ||
@@ -132,7 +133,6 @@
return initialization_flag_ == kNeedsInitialization;
}
- bool is_global() const;
bool is_this() const { return kind_ == THIS; }
bool is_arguments() const { return kind_ == ARGUMENTS; }
=======================================
--- /branches/bleeding_edge/test/cctest/test-decls.cc Tue Aug 28 03:49:23
2012
+++ /branches/bleeding_edge/test/cctest/test-decls.cc Tue Aug 28 04:25:08
2012
@@ -784,14 +784,26 @@
context.Check("this.x",
EXPECT_RESULT, Number::New(1));
}
+
+ { SimpleContext context;
+ context.Check("function x() { return 4 }; x()",
+ EXPECT_RESULT, Number::New(4));
+ context.Check("x()",
+ EXPECT_RESULT, Number::New(4));
+ context.Check("this.x()",
+ EXPECT_RESULT, Number::New(4));
+ }
{ SimpleContext context;
context.Check("let x = 2; x",
EXPECT_RESULT, Number::New(2));
context.Check("x",
EXPECT_RESULT, Number::New(2));
- context.Check("this.x",
- EXPECT_RESULT, Number::New(2));
+ // 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.
+ // context.Check("this.x",
+ // EXPECT_RESULT, Number::New(2));
}
{ SimpleContext context;
@@ -799,18 +811,12 @@
EXPECT_RESULT, Number::New(3));
context.Check("x",
EXPECT_RESULT, Number::New(3));
- context.Check("this.x",
- EXPECT_RESULT, Number::New(3));
+ // 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.
+ // context.Check("this.x",
+ // EXPECT_RESULT, Number::New(3));
}
-
- { SimpleContext context;
- context.Check("function x() { return 4 }; x()",
- EXPECT_RESULT, Number::New(4));
- context.Check("x()",
- EXPECT_RESULT, Number::New(4));
- context.Check("this.x()",
- EXPECT_RESULT, Number::New(4));
- }
// TODO(rossberg): All of the below should actually be errors in Harmony.
@@ -846,55 +852,55 @@
context.Check("let x = 1; x",
EXPECT_RESULT, Number::New(1));
context.Check("var x = 2; x",
- EXPECT_RESULT, Number::New(2));
+ EXPECT_ERROR);
}
{ SimpleContext context;
context.Check("let x = 1; x",
EXPECT_RESULT, Number::New(1));
context.Check("let x = 2; x",
- EXPECT_RESULT, Number::New(2));
+ EXPECT_ERROR);
}
{ SimpleContext context;
context.Check("let x = 1; x",
EXPECT_RESULT, Number::New(1));
context.Check("const x = 2; x",
- EXPECT_RESULT, Number::New(2));
+ EXPECT_ERROR);
}
{ SimpleContext context;
context.Check("let x = 1; x",
EXPECT_RESULT, Number::New(1));
context.Check("function x() { return 2 }; x()",
- EXPECT_RESULT, Number::New(2));
+ EXPECT_ERROR);
}
{ SimpleContext context;
context.Check("const x = 1; x",
EXPECT_RESULT, Number::New(1));
context.Check("var x = 2; x",
- EXPECT_EXCEPTION);
+ EXPECT_ERROR);
}
{ SimpleContext context;
context.Check("const x = 1; x",
EXPECT_RESULT, Number::New(1));
context.Check("let x = 2; x",
- EXPECT_EXCEPTION);
+ EXPECT_ERROR);
}
{ SimpleContext context;
context.Check("const x = 1; x",
EXPECT_RESULT, Number::New(1));
context.Check("const x = 2; x",
- EXPECT_RESULT, Number::New(1));
+ EXPECT_ERROR);
}
{ SimpleContext context;
context.Check("const x = 1; x",
EXPECT_RESULT, Number::New(1));
context.Check("function x() { return 2 }; x()",
- EXPECT_EXCEPTION);
+ EXPECT_ERROR);
}
}
=======================================
--- /branches/bleeding_edge/test/mjsunit/harmony/block-conflicts.js Tue Feb
14 05:47:54 2012
+++ /branches/bleeding_edge/test/mjsunit/harmony/block-conflicts.js Tue Aug
28 04:25:08 2012
@@ -35,7 +35,8 @@
function CheckException(e) {
var string = e.toString();
assertTrue(string.indexOf("has already been declared") >= 0 ||
- string.indexOf("redeclaration") >= 0); return 'Conflict';
+ string.indexOf("redeclaration") >= 0);
+ return 'Conflict';
}
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev