| 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 |