OLD | NEW |
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> |
| 11 #include <unordered_map> |
| 12 #include <unordered_set> |
11 | 13 |
12 #include "src/objects-inl.h" | 14 #include "src/objects-inl.h" |
13 | 15 |
14 #include "src/accessors.h" | 16 #include "src/accessors.h" |
15 #include "src/allocation-site-scopes.h" | 17 #include "src/allocation-site-scopes.h" |
16 #include "src/api-arguments-inl.h" | 18 #include "src/api-arguments-inl.h" |
17 #include "src/api-natives.h" | 19 #include "src/api-natives.h" |
18 #include "src/api.h" | 20 #include "src/api.h" |
19 #include "src/base/bits.h" | 21 #include "src/base/bits.h" |
20 #include "src/base/utils/random-number-generator.h" | 22 #include "src/base/utils/random-number-generator.h" |
(...skipping 19552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
19573 | 19575 |
19574 bool JSReceiver::HasProxyInPrototype(Isolate* isolate) { | 19576 bool JSReceiver::HasProxyInPrototype(Isolate* isolate) { |
19575 for (PrototypeIterator iter(isolate, this, kStartAtReceiver, | 19577 for (PrototypeIterator iter(isolate, this, kStartAtReceiver, |
19576 PrototypeIterator::END_AT_NULL); | 19578 PrototypeIterator::END_AT_NULL); |
19577 !iter.IsAtEnd(); iter.AdvanceIgnoringProxies()) { | 19579 !iter.IsAtEnd(); iter.AdvanceIgnoringProxies()) { |
19578 if (iter.GetCurrent<Object>()->IsJSProxy()) return true; | 19580 if (iter.GetCurrent<Object>()->IsJSProxy()) return true; |
19579 } | 19581 } |
19580 return false; | 19582 return false; |
19581 } | 19583 } |
19582 | 19584 |
| 19585 namespace { |
| 19586 |
| 19587 template <typename T> |
| 19588 struct HandleValueHash { |
| 19589 V8_INLINE size_t operator()(Handle<T> handle) const { return handle->Hash(); } |
| 19590 }; |
| 19591 |
| 19592 struct ModuleHandleEqual { |
| 19593 V8_INLINE bool operator()(Handle<Module> lhs, Handle<Module> rhs) const { |
| 19594 return *lhs == *rhs; |
| 19595 } |
| 19596 }; |
| 19597 |
| 19598 struct StringHandleEqual { |
| 19599 V8_INLINE bool operator()(Handle<String> lhs, Handle<String> rhs) const { |
| 19600 return lhs->Equals(*rhs); |
| 19601 } |
| 19602 }; |
| 19603 |
| 19604 class UnorderedStringSet |
| 19605 : public std::unordered_set<Handle<String>, HandleValueHash<String>, |
| 19606 StringHandleEqual, |
| 19607 zone_allocator<Handle<String>>> { |
| 19608 public: |
| 19609 explicit UnorderedStringSet(Zone* zone) |
| 19610 : std::unordered_set<Handle<String>, HandleValueHash<String>, |
| 19611 StringHandleEqual, zone_allocator<Handle<String>>>( |
| 19612 2 /* bucket count */, HandleValueHash<String>(), |
| 19613 StringHandleEqual(), zone_allocator<Handle<String>>(zone)) {} |
| 19614 }; |
| 19615 |
| 19616 } // anonymous namespace |
| 19617 |
| 19618 class Module::ResolveSet |
| 19619 : public std::unordered_map< |
| 19620 Handle<Module>, UnorderedStringSet*, HandleValueHash<Module>, |
| 19621 ModuleHandleEqual, zone_allocator<std::pair<const Handle<Module>, |
| 19622 UnorderedStringSet*>>> { |
| 19623 public: |
| 19624 explicit ResolveSet(Zone* zone) |
| 19625 : std::unordered_map<Handle<Module>, UnorderedStringSet*, |
| 19626 HandleValueHash<Module>, ModuleHandleEqual, |
| 19627 zone_allocator<std::pair<const Handle<Module>, |
| 19628 UnorderedStringSet*>>>( |
| 19629 2 /* bucket count */, HandleValueHash<Module>(), |
| 19630 ModuleHandleEqual(), |
| 19631 zone_allocator< |
| 19632 std::pair<const Handle<Module>, UnorderedStringSet*>>(zone)), |
| 19633 zone_(zone) {} |
| 19634 |
| 19635 Zone* zone() const { return zone_; } |
| 19636 |
| 19637 private: |
| 19638 Zone* zone_; |
| 19639 }; |
| 19640 |
19583 void Module::CreateIndirectExport(Handle<Module> module, Handle<String> name, | 19641 void Module::CreateIndirectExport(Handle<Module> module, Handle<String> name, |
19584 Handle<ModuleInfoEntry> entry) { | 19642 Handle<ModuleInfoEntry> entry) { |
19585 Isolate* isolate = module->GetIsolate(); | 19643 Isolate* isolate = module->GetIsolate(); |
19586 Handle<ObjectHashTable> exports(module->exports(), isolate); | 19644 Handle<ObjectHashTable> exports(module->exports(), isolate); |
19587 DCHECK(exports->Lookup(name)->IsTheHole(isolate)); | 19645 DCHECK(exports->Lookup(name)->IsTheHole(isolate)); |
19588 exports = ObjectHashTable::Put(exports, name, entry); | 19646 exports = ObjectHashTable::Put(exports, name, entry); |
19589 module->set_exports(*exports); | 19647 module->set_exports(*exports); |
19590 } | 19648 } |
19591 | 19649 |
19592 void Module::CreateExport(Handle<Module> module, Handle<FixedArray> names) { | 19650 void Module::CreateExport(Handle<Module> module, Handle<FixedArray> names) { |
(...skipping 30 matching lines...) Expand all Loading... |
19623 Handle<Object> Module::LoadImport(Handle<Module> module, Handle<String> name, | 19681 Handle<Object> Module::LoadImport(Handle<Module> module, Handle<String> name, |
19624 int module_request) { | 19682 int module_request) { |
19625 Isolate* isolate = module->GetIsolate(); | 19683 Isolate* isolate = module->GetIsolate(); |
19626 Handle<Module> requested_module( | 19684 Handle<Module> requested_module( |
19627 Module::cast(module->requested_modules()->get(module_request)), isolate); | 19685 Module::cast(module->requested_modules()->get(module_request)), isolate); |
19628 return Module::LoadExport(requested_module, name); | 19686 return Module::LoadExport(requested_module, name); |
19629 } | 19687 } |
19630 | 19688 |
19631 MaybeHandle<Cell> Module::ResolveImport(Handle<Module> module, | 19689 MaybeHandle<Cell> Module::ResolveImport(Handle<Module> module, |
19632 Handle<String> name, int module_request, | 19690 Handle<String> name, int module_request, |
19633 bool must_resolve) { | 19691 bool must_resolve, |
| 19692 Module::ResolveSet* resolve_set) { |
19634 Isolate* isolate = module->GetIsolate(); | 19693 Isolate* isolate = module->GetIsolate(); |
19635 Handle<Module> requested_module( | 19694 Handle<Module> requested_module( |
19636 Module::cast(module->requested_modules()->get(module_request)), isolate); | 19695 Module::cast(module->requested_modules()->get(module_request)), isolate); |
19637 return Module::ResolveExport(requested_module, name, must_resolve); | 19696 return Module::ResolveExport(requested_module, name, must_resolve, |
| 19697 resolve_set); |
19638 } | 19698 } |
19639 | 19699 |
19640 MaybeHandle<Cell> Module::ResolveExport(Handle<Module> module, | 19700 MaybeHandle<Cell> Module::ResolveExport(Handle<Module> module, |
19641 Handle<String> name, | 19701 Handle<String> name, bool must_resolve, |
19642 bool must_resolve) { | 19702 Module::ResolveSet* resolve_set) { |
19643 // TODO(neis): Detect cycles. | |
19644 | |
19645 Isolate* isolate = module->GetIsolate(); | 19703 Isolate* isolate = module->GetIsolate(); |
19646 Handle<Object> object(module->exports()->Lookup(name), isolate); | 19704 Handle<Object> object(module->exports()->Lookup(name), isolate); |
19647 | |
19648 if (object->IsCell()) { | 19705 if (object->IsCell()) { |
19649 // Already resolved (e.g. because it's a local export). | 19706 // Already resolved (e.g. because it's a local export). |
19650 return Handle<Cell>::cast(object); | 19707 return Handle<Cell>::cast(object); |
19651 } | 19708 } |
19652 | 19709 |
| 19710 // Must be an indirect export of some sort, so we need to detect cycles. |
| 19711 { |
| 19712 // Attempt insertion with a null string set. |
| 19713 auto result = resolve_set->insert({module, nullptr}); |
| 19714 UnorderedStringSet*& name_set = result.first->second; |
| 19715 bool did_insert = result.second; |
| 19716 if (did_insert) { |
| 19717 // |module| wasn't in the map previously, so allocate a new name set. |
| 19718 Zone* zone = resolve_set->zone(); |
| 19719 name_set = |
| 19720 new (zone->New(sizeof(UnorderedStringSet))) UnorderedStringSet(zone); |
| 19721 } else if (name_set->count(name)) { |
| 19722 // TODO(adamk): Throwing here is incorrect in the case of star exports. |
| 19723 THROW_NEW_ERROR( |
| 19724 isolate, |
| 19725 NewSyntaxError(MessageTemplate::kCyclicModuleDependency, name), Cell); |
| 19726 } |
| 19727 name_set->insert(name); |
| 19728 } |
| 19729 |
19653 if (object->IsModuleInfoEntry()) { | 19730 if (object->IsModuleInfoEntry()) { |
19654 // Not yet resolved indirect export. | 19731 // Not yet resolved indirect export. |
19655 Handle<ModuleInfoEntry> entry = Handle<ModuleInfoEntry>::cast(object); | 19732 Handle<ModuleInfoEntry> entry = Handle<ModuleInfoEntry>::cast(object); |
19656 int module_request = Smi::cast(entry->module_request())->value(); | 19733 int module_request = Smi::cast(entry->module_request())->value(); |
19657 Handle<String> import_name(String::cast(entry->import_name()), isolate); | 19734 Handle<String> import_name(String::cast(entry->import_name()), isolate); |
19658 | 19735 |
19659 Handle<Cell> cell; | 19736 Handle<Cell> cell; |
19660 if (!ResolveImport(module, import_name, module_request, true) | 19737 if (!ResolveImport(module, import_name, module_request, true, resolve_set) |
19661 .ToHandle(&cell)) { | 19738 .ToHandle(&cell)) { |
19662 DCHECK(isolate->has_pending_exception()); | 19739 DCHECK(isolate->has_pending_exception()); |
19663 return MaybeHandle<Cell>(); | 19740 return MaybeHandle<Cell>(); |
19664 } | 19741 } |
19665 | 19742 |
19666 // The export table may have changed but the entry in question should be | 19743 // The export table may have changed but the entry in question should be |
19667 // unchanged. | 19744 // unchanged. |
19668 Handle<ObjectHashTable> exports(module->exports(), isolate); | 19745 Handle<ObjectHashTable> exports(module->exports(), isolate); |
19669 DCHECK(exports->Lookup(name)->IsModuleInfoEntry()); | 19746 DCHECK(exports->Lookup(name)->IsModuleInfoEntry()); |
19670 | 19747 |
19671 exports = ObjectHashTable::Put(exports, name, cell); | 19748 exports = ObjectHashTable::Put(exports, name, cell); |
19672 module->set_exports(*exports); | 19749 module->set_exports(*exports); |
19673 return cell; | 19750 return cell; |
19674 } | 19751 } |
19675 | 19752 |
19676 DCHECK(object->IsTheHole(isolate)); | 19753 DCHECK(object->IsTheHole(isolate)); |
19677 return Module::ResolveExportUsingStarExports(module, name, must_resolve); | 19754 return Module::ResolveExportUsingStarExports(module, name, must_resolve, |
| 19755 resolve_set); |
19678 } | 19756 } |
19679 | 19757 |
19680 MaybeHandle<Cell> Module::ResolveExportUsingStarExports(Handle<Module> module, | 19758 MaybeHandle<Cell> Module::ResolveExportUsingStarExports( |
19681 Handle<String> name, | 19759 Handle<Module> module, Handle<String> name, bool must_resolve, |
19682 bool must_resolve) { | 19760 Module::ResolveSet* resolve_set) { |
19683 Isolate* isolate = module->GetIsolate(); | 19761 Isolate* isolate = module->GetIsolate(); |
19684 if (!name->Equals(isolate->heap()->default_string())) { | 19762 if (!name->Equals(isolate->heap()->default_string())) { |
19685 // Go through all star exports looking for the given name. If multiple star | 19763 // Go through all star exports looking for the given name. If multiple star |
19686 // exports provide the name, make sure they all map it to the same cell. | 19764 // exports provide the name, make sure they all map it to the same cell. |
19687 Handle<Cell> unique_cell; | 19765 Handle<Cell> unique_cell; |
19688 Handle<FixedArray> special_exports(module->info()->special_exports(), | 19766 Handle<FixedArray> special_exports(module->info()->special_exports(), |
19689 isolate); | 19767 isolate); |
19690 for (int i = 0, n = special_exports->length(); i < n; ++i) { | 19768 for (int i = 0, n = special_exports->length(); i < n; ++i) { |
19691 i::Handle<i::ModuleInfoEntry> entry( | 19769 i::Handle<i::ModuleInfoEntry> entry( |
19692 i::ModuleInfoEntry::cast(special_exports->get(i)), isolate); | 19770 i::ModuleInfoEntry::cast(special_exports->get(i)), isolate); |
19693 if (!entry->export_name()->IsUndefined(isolate)) { | 19771 if (!entry->export_name()->IsUndefined(isolate)) { |
19694 continue; // Indirect export. | 19772 continue; // Indirect export. |
19695 } | 19773 } |
19696 int module_request = Smi::cast(entry->module_request())->value(); | 19774 int module_request = Smi::cast(entry->module_request())->value(); |
19697 | 19775 |
19698 Handle<Cell> cell; | 19776 Handle<Cell> cell; |
19699 if (ResolveImport(module, name, module_request, false).ToHandle(&cell)) { | 19777 if (ResolveImport(module, name, module_request, false, resolve_set) |
| 19778 .ToHandle(&cell)) { |
19700 if (unique_cell.is_null()) unique_cell = cell; | 19779 if (unique_cell.is_null()) unique_cell = cell; |
19701 if (*unique_cell != *cell) { | 19780 if (*unique_cell != *cell) { |
19702 THROW_NEW_ERROR( | 19781 THROW_NEW_ERROR( |
19703 isolate, NewSyntaxError(MessageTemplate::kAmbiguousExport, name), | 19782 isolate, NewSyntaxError(MessageTemplate::kAmbiguousExport, name), |
19704 Cell); | 19783 Cell); |
19705 } | 19784 } |
19706 } else if (isolate->has_pending_exception()) { | 19785 } else if (isolate->has_pending_exception()) { |
19707 return MaybeHandle<Cell>(); | 19786 return MaybeHandle<Cell>(); |
19708 } | 19787 } |
19709 } | 19788 } |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
19782 isolate->ThrowIllegalOperation(); | 19861 isolate->ThrowIllegalOperation(); |
19783 return false; | 19862 return false; |
19784 } | 19863 } |
19785 Handle<Module> requested_module = Utils::OpenHandle(*api_requested_module); | 19864 Handle<Module> requested_module = Utils::OpenHandle(*api_requested_module); |
19786 module->requested_modules()->set(i, *requested_module); | 19865 module->requested_modules()->set(i, *requested_module); |
19787 if (!Instantiate(requested_module, context, callback, callback_data)) { | 19866 if (!Instantiate(requested_module, context, callback, callback_data)) { |
19788 return false; | 19867 return false; |
19789 } | 19868 } |
19790 } | 19869 } |
19791 | 19870 |
| 19871 Zone zone(isolate->allocator()); |
| 19872 |
19792 // Resolve imports. | 19873 // Resolve imports. |
19793 Handle<FixedArray> regular_imports(module_info->regular_imports(), isolate); | 19874 Handle<FixedArray> regular_imports(module_info->regular_imports(), isolate); |
19794 for (int i = 0, n = regular_imports->length(); i < n; ++i) { | 19875 for (int i = 0, n = regular_imports->length(); i < n; ++i) { |
19795 Handle<ModuleInfoEntry> entry( | 19876 Handle<ModuleInfoEntry> entry( |
19796 ModuleInfoEntry::cast(regular_imports->get(i)), isolate); | 19877 ModuleInfoEntry::cast(regular_imports->get(i)), isolate); |
19797 Handle<String> name(String::cast(entry->import_name()), isolate); | 19878 Handle<String> name(String::cast(entry->import_name()), isolate); |
19798 int module_request = Smi::cast(entry->module_request())->value(); | 19879 int module_request = Smi::cast(entry->module_request())->value(); |
19799 if (ResolveImport(module, name, module_request, true).is_null()) { | 19880 ResolveSet resolve_set(&zone); |
| 19881 if (ResolveImport(module, name, module_request, true, &resolve_set) |
| 19882 .is_null()) { |
19800 return false; | 19883 return false; |
19801 } | 19884 } |
19802 } | 19885 } |
19803 | 19886 |
19804 // Resolve indirect exports. | 19887 // Resolve indirect exports. |
19805 for (int i = 0, n = special_exports->length(); i < n; ++i) { | 19888 for (int i = 0, n = special_exports->length(); i < n; ++i) { |
19806 Handle<ModuleInfoEntry> entry( | 19889 Handle<ModuleInfoEntry> entry( |
19807 ModuleInfoEntry::cast(special_exports->get(i)), isolate); | 19890 ModuleInfoEntry::cast(special_exports->get(i)), isolate); |
19808 Handle<Object> name(entry->export_name(), isolate); | 19891 Handle<Object> name(entry->export_name(), isolate); |
19809 if (name->IsUndefined(isolate)) continue; // Star export. | 19892 if (name->IsUndefined(isolate)) continue; // Star export. |
19810 if (ResolveExport(module, Handle<String>::cast(name), true).is_null()) { | 19893 ResolveSet resolve_set(&zone); |
| 19894 if (ResolveExport(module, Handle<String>::cast(name), true, &resolve_set) |
| 19895 .is_null()) { |
19811 return false; | 19896 return false; |
19812 } | 19897 } |
19813 } | 19898 } |
19814 | 19899 |
19815 return true; | 19900 return true; |
19816 } | 19901 } |
19817 | 19902 |
19818 } // namespace internal | 19903 } // namespace internal |
19819 } // namespace v8 | 19904 } // namespace v8 |
OLD | NEW |