Index: src/scopes.cc |
diff --git a/src/scopes.cc b/src/scopes.cc |
index faedb5f085871a358807675d50a543666ae27bb9..ccfa82835123861d90cf619d40840cea1fd379de 100644 |
--- a/src/scopes.cc |
+++ b/src/scopes.cc |
@@ -29,6 +29,7 @@ |
#include "scopes.h" |
+#include "accessors.h" |
#include "bootstrapper.h" |
#include "compiler.h" |
#include "messages.h" |
@@ -226,6 +227,12 @@ Scope* Scope::DeserializeScopeChain(Context* context, Scope* global_scope, |
for (Scope* s = innermost_scope; s != NULL; s = s->outer_scope()) { |
s->scope_inside_with_ = true; |
} |
+ } else if (context->IsModuleContext()) { |
+ ScopeInfo* scope_info = ScopeInfo::cast(context->module()->scope_info()); |
+ current_scope = new(zone) Scope(current_scope, |
+ MODULE_SCOPE, |
+ Handle<ScopeInfo>(scope_info), |
+ zone); |
} else if (context->IsFunctionContext()) { |
ScopeInfo* scope_info = context->closure()->shared()->scope_info(); |
current_scope = new(zone) Scope(current_scope, |
@@ -634,6 +641,12 @@ bool Scope::AllocateVariables(CompilationInfo* info, |
// 3) Allocate variables. |
AllocateVariablesRecursively(); |
+ // 4) Allocate and link module instance objects. |
+ if (FLAG_harmony_modules && (is_global_scope() || is_module_scope())) { |
+ AllocateModules(info); |
+ LinkModules(info); |
+ } |
+ |
return true; |
} |
@@ -1111,7 +1124,8 @@ bool Scope::MustAllocate(Variable* var) { |
inner_scope_calls_eval_ || |
scope_contains_with_ || |
is_catch_scope() || |
- is_block_scope())) { |
+ is_block_scope() || |
+ is_module_scope())) { |
var->set_is_used(true); |
} |
// Global variables do not need to be allocated. |
@@ -1299,4 +1313,76 @@ int Scope::ContextLocalCount() const { |
(function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); |
} |
+ |
+void Scope::AllocateModules(CompilationInfo* info) { |
+ ASSERT(is_global_scope() || is_module_scope()); |
+ |
+ if (is_module_scope()) { |
+ ASSERT(interface_->IsFrozen()); |
+ ASSERT(scope_info_.is_null()); |
+ |
+ // TODO(rossberg): This has to be the initial compilation of this code. |
+ // We currently do not allow recompiling any module definitions. |
+ Handle<ScopeInfo> scope_info = GetScopeInfo(); |
+ Factory* factory = info->isolate()->factory(); |
+ Handle<Context> context = factory->NewModuleContext(scope_info); |
+ Handle<JSModule> instance = factory->NewJSModule(context, scope_info); |
+ context->set_module(*instance); |
+ |
+ bool ok; |
+ interface_->MakeSingleton(instance, &ok); |
+ ASSERT(ok); |
+ } |
+ |
+ // Allocate nested modules. |
+ for (int i = 0; i < inner_scopes_.length(); i++) { |
+ Scope* inner_scope = inner_scopes_.at(i); |
+ if (inner_scope->is_module_scope()) { |
+ inner_scope->AllocateModules(info); |
+ } |
+ } |
+} |
+ |
+ |
+void Scope::LinkModules(CompilationInfo* info) { |
+ ASSERT(is_global_scope() || is_module_scope()); |
+ |
+ if (is_module_scope()) { |
+ Handle<JSModule> instance = interface_->Instance(); |
+ |
+ // Populate the module instance object. |
+ const PropertyAttributes ro_attr = |
+ static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE | DONT_ENUM); |
+ const PropertyAttributes rw_attr = |
+ static_cast<PropertyAttributes>(DONT_DELETE | DONT_ENUM); |
+ for (Interface::Iterator it = interface_->iterator(); |
+ !it.done(); it.Advance()) { |
+ if (it.interface()->IsModule()) { |
+ Handle<Object> value = it.interface()->Instance(); |
+ ASSERT(!value.is_null()); |
+ JSReceiver::SetProperty( |
+ instance, it.name(), value, ro_attr, kStrictMode); |
+ } else { |
+ Variable* var = LocalLookup(it.name()); |
+ ASSERT(var != NULL && var->IsContextSlot()); |
+ PropertyAttributes attr = var->is_const_mode() ? ro_attr : rw_attr; |
+ Handle<AccessorInfo> info = |
+ Accessors::MakeModuleExport(it.name(), var->index(), attr); |
+ Handle<Object> result = SetAccessor(instance, info); |
Jakob Kummerow
2012/07/09 11:03:12
unused variable (in release mode).
|
+ ASSERT(!(result.is_null() || result->IsUndefined())); |
+ } |
+ } |
+ USE(JSObject::PreventExtensions(instance)); |
+ } |
+ |
+ // Link nested modules. |
+ for (int i = 0; i < inner_scopes_.length(); i++) { |
+ Scope* inner_scope = inner_scopes_.at(i); |
+ if (inner_scope->is_module_scope()) { |
+ inner_scope->LinkModules(info); |
+ } |
+ } |
+} |
+ |
+ |
} } // namespace v8::internal |