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

Side by Side Diff: src/objects.cc

Issue 2388153003: [modules] Implement namespace imports. (Closed)
Patch Set: Fix verifier. 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
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 Object* JSModuleNamespace::Get(Handle<String> name) {
19591 Isolate* isolate = name->GetIsolate();
19592 Handle<Object> object(module()->exports()->Lookup(name), isolate);
19593 return object->IsTheHole(isolate) ? isolate->heap()->undefined_value()
19594 : Handle<Cell>::cast(object)->value();
19595 }
19596
19587 namespace { 19597 namespace {
19588 19598
19589 template <typename T> 19599 template <typename T>
19590 struct HandleValueHash { 19600 struct HandleValueHash {
19591 V8_INLINE size_t operator()(Handle<T> handle) const { return handle->Hash(); } 19601 V8_INLINE size_t operator()(Handle<T> handle) const { return handle->Hash(); }
19592 }; 19602 };
19593 19603
19594 struct ModuleHandleEqual { 19604 struct ModuleHandleEqual {
19595 V8_INLINE bool operator()(Handle<Module> lhs, Handle<Module> rhs) const { 19605 V8_INLINE bool operator()(Handle<Module> lhs, Handle<Module> rhs) const {
19596 return *lhs == *rhs; 19606 return *lhs == *rhs;
(...skipping 11 matching lines...) Expand all
19608 StringHandleEqual, 19618 StringHandleEqual,
19609 zone_allocator<Handle<String>>> { 19619 zone_allocator<Handle<String>>> {
19610 public: 19620 public:
19611 explicit UnorderedStringSet(Zone* zone) 19621 explicit UnorderedStringSet(Zone* zone)
19612 : std::unordered_set<Handle<String>, HandleValueHash<String>, 19622 : std::unordered_set<Handle<String>, HandleValueHash<String>,
19613 StringHandleEqual, zone_allocator<Handle<String>>>( 19623 StringHandleEqual, zone_allocator<Handle<String>>>(
19614 2 /* bucket count */, HandleValueHash<String>(), 19624 2 /* bucket count */, HandleValueHash<String>(),
19615 StringHandleEqual(), zone_allocator<Handle<String>>(zone)) {} 19625 StringHandleEqual(), zone_allocator<Handle<String>>(zone)) {}
19616 }; 19626 };
19617 19627
19628 class UnorderedModuleSet
19629 : public std::unordered_set<Handle<Module>, HandleValueHash<Module>,
19630 ModuleHandleEqual,
19631 zone_allocator<Handle<Module>>> {
19632 public:
19633 explicit UnorderedModuleSet(Zone* zone)
19634 : std::unordered_set<Handle<Module>, HandleValueHash<Module>,
19635 ModuleHandleEqual, zone_allocator<Handle<Module>>>(
19636 2 /* bucket count */, HandleValueHash<Module>(),
19637 ModuleHandleEqual(), zone_allocator<Handle<Module>>(zone)) {}
19638 };
19639
19640 class UnorderedStringMap
19641 : public std::unordered_map<
19642 Handle<String>, Handle<Object>, HandleValueHash<String>,
19643 StringHandleEqual,
19644 zone_allocator<std::pair<const Handle<String>, Handle<Object>>>> {
19645 public:
19646 explicit UnorderedStringMap(Zone* zone)
19647 : std::unordered_map<
19648 Handle<String>, Handle<Object>, HandleValueHash<String>,
19649 StringHandleEqual,
19650 zone_allocator<std::pair<const Handle<String>, Handle<Object>>>>(
19651 2 /* bucket count */, HandleValueHash<String>(),
19652 StringHandleEqual(),
19653 zone_allocator<std::pair<const Handle<String>, Handle<Object>>>(
19654 zone)) {}
19655 };
19656
19618 } // anonymous namespace 19657 } // anonymous namespace
19619 19658
19620 class Module::ResolveSet 19659 class Module::ResolveSet
19621 : public std::unordered_map< 19660 : public std::unordered_map<
19622 Handle<Module>, UnorderedStringSet*, HandleValueHash<Module>, 19661 Handle<Module>, UnorderedStringSet*, HandleValueHash<Module>,
19623 ModuleHandleEqual, zone_allocator<std::pair<const Handle<Module>, 19662 ModuleHandleEqual, zone_allocator<std::pair<const Handle<Module>,
19624 UnorderedStringSet*>>> { 19663 UnorderedStringSet*>>> {
19625 public: 19664 public:
19626 explicit ResolveSet(Zone* zone) 19665 explicit ResolveSet(Zone* zone)
19627 : std::unordered_map<Handle<Module>, UnorderedStringSet*, 19666 : 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); 19970 Handle<Module> import(Module::cast(requested_modules->get(i)), isolate);
19932 RETURN_ON_EXCEPTION(isolate, Evaluate(import), Object); 19971 RETURN_ON_EXCEPTION(isolate, Evaluate(import), Object);
19933 } 19972 }
19934 19973
19935 // Evaluation of module body. 19974 // Evaluation of module body.
19936 Handle<JSFunction> resume( 19975 Handle<JSFunction> resume(
19937 isolate->native_context()->generator_next_internal(), isolate); 19976 isolate->native_context()->generator_next_internal(), isolate);
19938 return Execution::Call(isolate, resume, generator, 0, nullptr); 19977 return Execution::Call(isolate, resume, generator, 0, nullptr);
19939 } 19978 }
19940 19979
19980 namespace {
adamk 2016/10/04 18:26:53 Please add a blank line after this (and before the
neis 2016/10/05 08:18:41 Done.
19981 void FetchStarExports(Handle<Module> module, Zone* zone,
19982 UnorderedModuleSet* visited) {
19983 DCHECK(module->code()->IsJSFunction()); // Instantiated.
19984
19985 bool cycle = !visited->insert(module).second;
19986 if (cycle) return;
19987
19988 Isolate* isolate = module->GetIsolate();
19989 Handle<ObjectHashTable> exports(module->exports(), isolate);
19990 UnorderedStringMap more_exports(zone);
19991
19992 // TODO(neis): Only allocate more_exports if there are star exports.
19993 // Maybe split special_exports into indirect_exports and star_exports.
19994
19995 Handle<FixedArray> special_exports(module->info()->special_exports(),
19996 isolate);
19997 for (int i = 0, n = special_exports->length(); i < n; ++i) {
19998 i::Handle<i::ModuleInfoEntry> entry(
adamk 2016/10/04 18:26:53 No need for i:: prefixes here (and below).
neis 2016/10/05 08:18:41 Done.
19999 i::ModuleInfoEntry::cast(special_exports->get(i)), isolate);
20000 if (!entry->export_name()->IsUndefined(isolate)) {
20001 continue; // Indirect export.
20002 }
20003
20004 int module_request = Smi::cast(entry->module_request())->value();
20005 Handle<Module> requested_module(
20006 Module::cast(module->requested_modules()->get(module_request)),
20007 isolate);
20008
20009 // Recurse.
20010 FetchStarExports(requested_module, zone, visited);
20011
20012 // Collect all of [requested_module]'s exports that must be added to
20013 // [module]'s exports (i.e. to [exports]). We record these in
20014 // [more_exports]. Ambiguities (conflicting exports) are marked by mapping
20015 // the name to undefined instead of a Cell.
20016 Handle<ObjectHashTable> requested_exports(requested_module->exports(),
20017 isolate);
20018 for (int i = 0, n = requested_exports->Capacity(); i < n; ++i) {
20019 Handle<Object> key(requested_exports->KeyAt(i), isolate);
20020 if (!requested_exports->IsKey(isolate, *key)) continue;
20021 if (Handle<String>::cast(key)->Equals(isolate->heap()->default_string()))
20022 continue;
20023 if (!exports->Lookup(key)->IsTheHole(isolate)) continue;
20024
20025 Handle<String> name = Handle<String>::cast(key);
20026 Handle<Cell> cell(Cell::cast(requested_exports->ValueAt(i)), isolate);
20027 auto it = more_exports.find(name);
20028 if (it == more_exports.end()) {
20029 more_exports.insert(std::make_pair(name, cell));
adamk 2016/10/04 18:26:53 Please change this code to only do a single lookup
neis 2016/10/05 08:18:41 Done.
20030 } else if (*it->second == *cell || it->second->IsUndefined(isolate)) {
20031 // We already recorded this mapping, or the name is ambiguous. In
20032 // either case, there's nothing to do.
20033 } else {
20034 DCHECK(it->second->IsCell());
20035 // Different star exports provide different cells for this name, hence
20036 // mark the name as ambiguous.
20037 it->second = isolate->factory()->undefined_value();
20038 }
20039 }
20040 }
20041
20042 // Copy [more_exports] into [exports].
20043 for (const auto& elem : more_exports) {
20044 if (elem.second->IsUndefined(isolate)) continue; // Ambiguous export.
20045 DCHECK(!elem.first->Equals(isolate->heap()->default_string()));
20046 DCHECK(elem.second->IsCell());
20047 exports = ObjectHashTable::Put(exports, elem.first, elem.second);
20048 }
20049 module->set_exports(*exports);
20050 }
20051 } // anonymous namespace
20052
20053 void Module::FetchStarExports(Handle<Module> module, Zone* zone) {
adamk 2016/10/04 18:26:53 Is this called anywhere other than below? Maybe ju
neis 2016/10/05 08:18:41 Ok, inlined it.
20054 UnorderedModuleSet visited(zone);
20055 return i::FetchStarExports(module, zone, &visited);
20056 }
20057
20058 Handle<JSModuleNamespace> Module::GetModuleNamespace(Handle<Module> module,
20059 int module_request) {
20060 Isolate* isolate = module->GetIsolate();
20061 Handle<Module> requested_module(
20062 Module::cast(module->requested_modules()->get(module_request)), isolate);
20063 return Module::GetModuleNamespace(requested_module);
20064 }
20065
20066 Handle<JSModuleNamespace> Module::GetModuleNamespace(Handle<Module> module) {
20067 Isolate* isolate = module->GetIsolate();
20068
20069 Handle<HeapObject> object(module->module_namespace(), isolate);
20070 if (!object->IsUndefined(isolate)) {
20071 // Namespace object already exists.
20072 return Handle<JSModuleNamespace>::cast(object);
20073 }
20074
20075 // Create the namespace object (initially empty).
20076 Handle<JSModuleNamespace> ns = isolate->factory()->NewJSModuleNamespace();
20077 ns->set_module(*module);
20078 module->set_module_namespace(*ns);
20079
20080 // Collect the export names.
20081 Zone zone(isolate->allocator());
20082 FetchStarExports(module, &zone);
20083 Handle<ObjectHashTable> exports(module->exports(), isolate);
20084 ZoneVector<Handle<String>> names(&zone);
20085 names.reserve(exports->NumberOfElements());
20086 for (int i = 0, n = exports->Capacity(); i < n; ++i) {
20087 Handle<Object> key(exports->KeyAt(i), isolate);
20088 if (!exports->IsKey(isolate, *key)) continue;
20089 DCHECK(exports->ValueAt(i)->IsCell());
20090 names.push_back(Handle<String>::cast(key));
20091 }
20092 DCHECK_EQ(names.size(), exports->NumberOfElements());
20093
20094 // Sort them alphabetically.
20095 struct {
20096 bool operator()(Handle<String> a, Handle<String> b) {
20097 return String::Compare(a, b) == ComparisonResult::kLessThan;
20098 }
20099 } StringLess;
20100 std::sort(names.begin(), names.end(), StringLess);
20101
20102 // Create the corresponding properties in the namespace object.
20103 PropertyAttributes attr = DONT_DELETE;
20104 for (const auto& name : names) {
20105 JSObject::SetAccessor(
20106 ns, Accessors::ModuleNamespaceEntryInfo(isolate, name, attr))
20107 .Check();
20108 }
20109 JSObject::PreventExtensions(ns, THROW_ON_ERROR).ToChecked();
20110
20111 return ns;
20112 }
20113
19941 } // namespace internal 20114 } // namespace internal
19942 } // namespace v8 20115 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698