Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(63)

Side by Side Diff: src/objects.cc

Issue 2388153003: [modules] Implement namespace imports. (Closed)
Patch Set: Add comment on VisitModuleNamespaceImports. Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/objects.h ('k') | src/objects-body-descriptors-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/objects.h" 5 #include "src/objects.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 #include <iomanip> 8 #include <iomanip>
9 #include <memory> 9 #include <memory>
10 #include <sstream> 10 #include <sstream>
(...skipping 6536 matching lines...) Expand 10 before | Expand all | Expand 10 after
6547 PropertyDescriptor* desc, 6547 PropertyDescriptor* desc,
6548 ShouldThrow should_throw) { 6548 ShouldThrow should_throw) {
6549 if (object->IsJSArray()) { 6549 if (object->IsJSArray()) {
6550 return JSArray::DefineOwnProperty(isolate, Handle<JSArray>::cast(object), 6550 return JSArray::DefineOwnProperty(isolate, Handle<JSArray>::cast(object),
6551 key, desc, should_throw); 6551 key, desc, should_throw);
6552 } 6552 }
6553 if (object->IsJSProxy()) { 6553 if (object->IsJSProxy()) {
6554 return JSProxy::DefineOwnProperty(isolate, Handle<JSProxy>::cast(object), 6554 return JSProxy::DefineOwnProperty(isolate, Handle<JSProxy>::cast(object),
6555 key, desc, should_throw); 6555 key, desc, should_throw);
6556 } 6556 }
6557 // TODO(jkummerow): Support Modules (ES6 9.4.6.6) 6557 // TODO(neis): Special case for JSModuleNamespace?
6558 6558
6559 // OrdinaryDefineOwnProperty, by virtue of calling 6559 // OrdinaryDefineOwnProperty, by virtue of calling
6560 // DefineOwnPropertyIgnoreAttributes, can handle arguments (ES6 9.4.4.2) 6560 // DefineOwnPropertyIgnoreAttributes, can handle arguments (ES6 9.4.4.2)
6561 // and IntegerIndexedExotics (ES6 9.4.5.3), with one exception: 6561 // and IntegerIndexedExotics (ES6 9.4.5.3), with one exception:
6562 // TODO(jkummerow): Setting an indexed accessor on a typed array should throw. 6562 // TODO(jkummerow): Setting an indexed accessor on a typed array should throw.
6563 return OrdinaryDefineOwnProperty(isolate, Handle<JSObject>::cast(object), key, 6563 return OrdinaryDefineOwnProperty(isolate, Handle<JSObject>::cast(object), key,
6564 desc, should_throw); 6564 desc, should_throw);
6565 } 6565 }
6566 6566
6567 6567
(...skipping 11662 matching lines...) Expand 10 before | Expand all | Expand 10 after
18230 DCHECK(IsKey(isolate, *key)); 18230 DCHECK(IsKey(isolate, *key));
18231 18231
18232 // If the object does not have an identity hash, it was never used as a key. 18232 // If the object does not have an identity hash, it was never used as a key.
18233 Object* hash = key->GetHash(); 18233 Object* hash = key->GetHash();
18234 if (hash->IsUndefined(isolate)) { 18234 if (hash->IsUndefined(isolate)) {
18235 return isolate->heap()->the_hole_value(); 18235 return isolate->heap()->the_hole_value();
18236 } 18236 }
18237 return Lookup(isolate, key, Smi::cast(hash)->value()); 18237 return Lookup(isolate, key, Smi::cast(hash)->value());
18238 } 18238 }
18239 18239
18240 Object* ObjectHashTable::ValueAt(int entry) {
18241 return get(EntryToValueIndex(entry));
18242 }
18240 18243
18241 Object* ObjectHashTable::Lookup(Handle<Object> key, int32_t hash) { 18244 Object* ObjectHashTable::Lookup(Handle<Object> key, int32_t hash) {
18242 return Lookup(GetIsolate(), key, hash); 18245 return Lookup(GetIsolate(), key, hash);
18243 } 18246 }
18244 18247
18245 18248
18246 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table, 18249 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
18247 Handle<Object> key, 18250 Handle<Object> key,
18248 Handle<Object> value) { 18251 Handle<Object> value) {
18249 Isolate* isolate = table->GetIsolate(); 18252 Isolate* isolate = table->GetIsolate();
(...skipping 1327 matching lines...) Expand 10 before | Expand all | Expand 10 after
19577 19580
19578 bool JSReceiver::HasProxyInPrototype(Isolate* isolate) { 19581 bool JSReceiver::HasProxyInPrototype(Isolate* isolate) {
19579 for (PrototypeIterator iter(isolate, this, kStartAtReceiver, 19582 for (PrototypeIterator iter(isolate, this, kStartAtReceiver,
19580 PrototypeIterator::END_AT_NULL); 19583 PrototypeIterator::END_AT_NULL);
19581 !iter.IsAtEnd(); iter.AdvanceIgnoringProxies()) { 19584 !iter.IsAtEnd(); iter.AdvanceIgnoringProxies()) {
19582 if (iter.GetCurrent<Object>()->IsJSProxy()) return true; 19585 if (iter.GetCurrent<Object>()->IsJSProxy()) return true;
19583 } 19586 }
19584 return false; 19587 return false;
19585 } 19588 }
19586 19589
19590 MaybeHandle<Object> JSModuleNamespace::GetExport(Handle<String> name) {
19591 Isolate* isolate = name->GetIsolate();
19592
19593 Handle<Object> object(module()->exports()->Lookup(name), isolate);
19594 if (object->IsTheHole(isolate)) {
19595 return isolate->factory()->undefined_value();
19596 }
19597
19598 Handle<Object> value(Handle<Cell>::cast(object)->value(), isolate);
19599 if (value->IsTheHole(isolate)) {
19600 THROW_NEW_ERROR(
19601 isolate, NewReferenceError(MessageTemplate::kNotDefined, name), Object);
19602 }
19603
19604 return value;
19605 }
19606
19587 namespace { 19607 namespace {
19588 19608
19589 template <typename T> 19609 template <typename T>
19590 struct HandleValueHash { 19610 struct HandleValueHash {
19591 V8_INLINE size_t operator()(Handle<T> handle) const { return handle->Hash(); } 19611 V8_INLINE size_t operator()(Handle<T> handle) const { return handle->Hash(); }
19592 }; 19612 };
19593 19613
19594 struct ModuleHandleEqual { 19614 struct ModuleHandleEqual {
19595 V8_INLINE bool operator()(Handle<Module> lhs, Handle<Module> rhs) const { 19615 V8_INLINE bool operator()(Handle<Module> lhs, Handle<Module> rhs) const {
19596 return *lhs == *rhs; 19616 return *lhs == *rhs;
(...skipping 11 matching lines...) Expand all
19608 StringHandleEqual, 19628 StringHandleEqual,
19609 zone_allocator<Handle<String>>> { 19629 zone_allocator<Handle<String>>> {
19610 public: 19630 public:
19611 explicit UnorderedStringSet(Zone* zone) 19631 explicit UnorderedStringSet(Zone* zone)
19612 : std::unordered_set<Handle<String>, HandleValueHash<String>, 19632 : std::unordered_set<Handle<String>, HandleValueHash<String>,
19613 StringHandleEqual, zone_allocator<Handle<String>>>( 19633 StringHandleEqual, zone_allocator<Handle<String>>>(
19614 2 /* bucket count */, HandleValueHash<String>(), 19634 2 /* bucket count */, HandleValueHash<String>(),
19615 StringHandleEqual(), zone_allocator<Handle<String>>(zone)) {} 19635 StringHandleEqual(), zone_allocator<Handle<String>>(zone)) {}
19616 }; 19636 };
19617 19637
19638 class UnorderedModuleSet
19639 : public std::unordered_set<Handle<Module>, HandleValueHash<Module>,
19640 ModuleHandleEqual,
19641 zone_allocator<Handle<Module>>> {
19642 public:
19643 explicit UnorderedModuleSet(Zone* zone)
19644 : std::unordered_set<Handle<Module>, HandleValueHash<Module>,
19645 ModuleHandleEqual, zone_allocator<Handle<Module>>>(
19646 2 /* bucket count */, HandleValueHash<Module>(),
19647 ModuleHandleEqual(), zone_allocator<Handle<Module>>(zone)) {}
19648 };
19649
19650 class UnorderedStringMap
19651 : public std::unordered_map<
19652 Handle<String>, Handle<Object>, HandleValueHash<String>,
19653 StringHandleEqual,
19654 zone_allocator<std::pair<const Handle<String>, Handle<Object>>>> {
19655 public:
19656 explicit UnorderedStringMap(Zone* zone)
19657 : std::unordered_map<
19658 Handle<String>, Handle<Object>, HandleValueHash<String>,
19659 StringHandleEqual,
19660 zone_allocator<std::pair<const Handle<String>, Handle<Object>>>>(
19661 2 /* bucket count */, HandleValueHash<String>(),
19662 StringHandleEqual(),
19663 zone_allocator<std::pair<const Handle<String>, Handle<Object>>>(
19664 zone)) {}
19665 };
19666
19618 } // anonymous namespace 19667 } // anonymous namespace
19619 19668
19620 class Module::ResolveSet 19669 class Module::ResolveSet
19621 : public std::unordered_map< 19670 : public std::unordered_map<
19622 Handle<Module>, UnorderedStringSet*, HandleValueHash<Module>, 19671 Handle<Module>, UnorderedStringSet*, HandleValueHash<Module>,
19623 ModuleHandleEqual, zone_allocator<std::pair<const Handle<Module>, 19672 ModuleHandleEqual, zone_allocator<std::pair<const Handle<Module>,
19624 UnorderedStringSet*>>> { 19673 UnorderedStringSet*>>> {
19625 public: 19674 public:
19626 explicit ResolveSet(Zone* zone) 19675 explicit ResolveSet(Zone* zone)
19627 : std::unordered_map<Handle<Module>, UnorderedStringSet*, 19676 : std::unordered_map<Handle<Module>, UnorderedStringSet*,
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after
19931 Handle<Module> import(Module::cast(requested_modules->get(i)), isolate); 19980 Handle<Module> import(Module::cast(requested_modules->get(i)), isolate);
19932 RETURN_ON_EXCEPTION(isolate, Evaluate(import), Object); 19981 RETURN_ON_EXCEPTION(isolate, Evaluate(import), Object);
19933 } 19982 }
19934 19983
19935 // Evaluation of module body. 19984 // Evaluation of module body.
19936 Handle<JSFunction> resume( 19985 Handle<JSFunction> resume(
19937 isolate->native_context()->generator_next_internal(), isolate); 19986 isolate->native_context()->generator_next_internal(), isolate);
19938 return Execution::Call(isolate, resume, generator, 0, nullptr); 19987 return Execution::Call(isolate, resume, generator, 0, nullptr);
19939 } 19988 }
19940 19989
19990 namespace {
19991
19992 void FetchStarExports(Handle<Module> module, Zone* zone,
19993 UnorderedModuleSet* visited) {
19994 DCHECK(module->code()->IsJSFunction()); // Instantiated.
19995
19996 bool cycle = !visited->insert(module).second;
19997 if (cycle) return;
19998
19999 Isolate* isolate = module->GetIsolate();
20000 Handle<ObjectHashTable> exports(module->exports(), isolate);
20001 UnorderedStringMap more_exports(zone);
20002
20003 // TODO(neis): Only allocate more_exports if there are star exports.
20004 // Maybe split special_exports into indirect_exports and star_exports.
20005
20006 Handle<FixedArray> special_exports(module->info()->special_exports(),
20007 isolate);
20008 for (int i = 0, n = special_exports->length(); i < n; ++i) {
20009 Handle<ModuleInfoEntry> entry(
20010 ModuleInfoEntry::cast(special_exports->get(i)), isolate);
20011 if (!entry->export_name()->IsUndefined(isolate)) {
20012 continue; // Indirect export.
20013 }
20014
20015 int module_request = Smi::cast(entry->module_request())->value();
20016 Handle<Module> requested_module(
20017 Module::cast(module->requested_modules()->get(module_request)),
20018 isolate);
20019
20020 // Recurse.
20021 FetchStarExports(requested_module, zone, visited);
20022
20023 // Collect all of [requested_module]'s exports that must be added to
20024 // [module]'s exports (i.e. to [exports]). We record these in
20025 // [more_exports]. Ambiguities (conflicting exports) are marked by mapping
20026 // the name to undefined instead of a Cell.
20027 Handle<ObjectHashTable> requested_exports(requested_module->exports(),
20028 isolate);
20029 for (int i = 0, n = requested_exports->Capacity(); i < n; ++i) {
20030 Handle<Object> key(requested_exports->KeyAt(i), isolate);
20031 if (!requested_exports->IsKey(isolate, *key)) continue;
20032 Handle<String> name = Handle<String>::cast(key);
20033
20034 if (name->Equals(isolate->heap()->default_string())) continue;
20035 if (!exports->Lookup(name)->IsTheHole(isolate)) continue;
20036
20037 Handle<Cell> cell(Cell::cast(requested_exports->ValueAt(i)), isolate);
20038 auto insert_result = more_exports.insert(std::make_pair(name, cell));
20039 if (!insert_result.second) {
20040 auto it = insert_result.first;
20041 if (*it->second == *cell || it->second->IsUndefined(isolate)) {
20042 // We already recorded this mapping before, or the name is already
20043 // known to be ambiguous. In either case, there's nothing to do.
20044 } else {
20045 DCHECK(it->second->IsCell());
20046 // Different star exports provide different cells for this name, hence
20047 // mark the name as ambiguous.
20048 it->second = isolate->factory()->undefined_value();
20049 }
20050 }
20051 }
20052 }
20053
20054 // Copy [more_exports] into [exports].
20055 for (const auto& elem : more_exports) {
20056 if (elem.second->IsUndefined(isolate)) continue; // Ambiguous export.
20057 DCHECK(!elem.first->Equals(isolate->heap()->default_string()));
20058 DCHECK(elem.second->IsCell());
20059 exports = ObjectHashTable::Put(exports, elem.first, elem.second);
20060 }
20061 module->set_exports(*exports);
20062 }
20063
20064 } // anonymous namespace
20065
20066 Handle<JSModuleNamespace> Module::GetModuleNamespace(Handle<Module> module,
20067 int module_request) {
20068 Isolate* isolate = module->GetIsolate();
20069 Handle<Module> requested_module(
20070 Module::cast(module->requested_modules()->get(module_request)), isolate);
20071 return Module::GetModuleNamespace(requested_module);
20072 }
20073
20074 Handle<JSModuleNamespace> Module::GetModuleNamespace(Handle<Module> module) {
20075 Isolate* isolate = module->GetIsolate();
20076
20077 Handle<HeapObject> object(module->module_namespace(), isolate);
20078 if (!object->IsUndefined(isolate)) {
20079 // Namespace object already exists.
20080 return Handle<JSModuleNamespace>::cast(object);
20081 }
20082
20083 // Create the namespace object (initially empty).
20084 Handle<JSModuleNamespace> ns = isolate->factory()->NewJSModuleNamespace();
20085 ns->set_module(*module);
20086 module->set_module_namespace(*ns);
20087
20088 // Collect the export names.
20089 Zone zone(isolate->allocator());
20090 UnorderedModuleSet visited(&zone);
20091 FetchStarExports(module, &zone, &visited);
20092 Handle<ObjectHashTable> exports(module->exports(), isolate);
20093 ZoneVector<Handle<String>> names(&zone);
20094 names.reserve(exports->NumberOfElements());
20095 for (int i = 0, n = exports->Capacity(); i < n; ++i) {
20096 Handle<Object> key(exports->KeyAt(i), isolate);
20097 if (!exports->IsKey(isolate, *key)) continue;
20098 DCHECK(exports->ValueAt(i)->IsCell());
20099 names.push_back(Handle<String>::cast(key));
20100 }
20101 DCHECK_EQ(names.size(), exports->NumberOfElements());
20102
20103 // Sort them alphabetically.
20104 struct {
20105 bool operator()(Handle<String> a, Handle<String> b) {
20106 return String::Compare(a, b) == ComparisonResult::kLessThan;
20107 }
20108 } StringLess;
20109 std::sort(names.begin(), names.end(), StringLess);
20110
20111 // Create the corresponding properties in the namespace object.
20112 PropertyAttributes attr = DONT_DELETE;
20113 for (const auto& name : names) {
20114 JSObject::SetAccessor(
20115 ns, Accessors::ModuleNamespaceEntryInfo(isolate, name, attr))
20116 .Check();
20117 }
20118 JSObject::PreventExtensions(ns, THROW_ON_ERROR).ToChecked();
20119
20120 return ns;
20121 }
20122
19941 } // namespace internal 20123 } // namespace internal
19942 } // namespace v8 20124 } // namespace v8
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-body-descriptors-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698