1 // Copyright 2019 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/objects/synthetic-module.h"
6
7 #include "src/api/api-inl.h"
8 #include "src/builtins/accessors.h"
9 #include "src/objects/js-generator-inl.h"
10 #include "src/objects/module-inl.h"
11 #include "src/objects/objects-inl.h"
12 #include "src/objects/shared-function-info.h"
13 #include "src/objects/synthetic-module-inl.h"
14 #include "src/utils/ostreams.h"
15
16 namespace v8 {
17 namespace internal {
18
19 // Implements SetSyntheticModuleBinding:
20 // https://heycam.github.io/webidl/#setsyntheticmoduleexport
SetExport(Isolate * isolate,Handle<SyntheticModule> module,Handle<String> export_name,Handle<Object> export_value)21 Maybe<bool> SyntheticModule::SetExport(Isolate* isolate,
22 Handle<SyntheticModule> module,
23 Handle<String> export_name,
24 Handle<Object> export_value) {
25 Handle<ObjectHashTable> exports(module->exports(), isolate);
26 Handle<Object> export_object(exports->Lookup(export_name), isolate);
27
28 if (!export_object->IsCell()) {
29 isolate->Throw(*isolate->factory()->NewReferenceError(
30 MessageTemplate::kModuleExportUndefined, export_name));
31 return Nothing<bool>();
32 }
33
34 // Spec step 2: Set the mutable binding of export_name to export_value
35 Cell::cast(*export_object).set_value(*export_value);
36
37 return Just(true);
38 }
39
SetExportStrict(Isolate * isolate,Handle<SyntheticModule> module,Handle<String> export_name,Handle<Object> export_value)40 void SyntheticModule::SetExportStrict(Isolate* isolate,
41 Handle<SyntheticModule> module,
42 Handle<String> export_name,
43 Handle<Object> export_value) {
44 Handle<ObjectHashTable> exports(module->exports(), isolate);
45 Handle<Object> export_object(exports->Lookup(export_name), isolate);
46 CHECK(export_object->IsCell());
47 Maybe<bool> set_export_result =
48 SetExport(isolate, module, export_name, export_value);
49 CHECK(set_export_result.FromJust());
50 }
51
52 // Implements Synthetic Module Record's ResolveExport concrete method:
53 // https://heycam.github.io/webidl/#smr-resolveexport
ResolveExport(Isolate * isolate,Handle<SyntheticModule> module,Handle<String> module_specifier,Handle<String> export_name,MessageLocation loc,bool must_resolve)54 MaybeHandle<Cell> SyntheticModule::ResolveExport(
55 Isolate* isolate, Handle<SyntheticModule> module,
56 Handle<String> module_specifier, Handle<String> export_name,
57 MessageLocation loc, bool must_resolve) {
58 Handle<Object> object(module->exports().Lookup(export_name), isolate);
59 if (object->IsCell()) return Handle<Cell>::cast(object);
60
61 if (!must_resolve) return MaybeHandle<Cell>();
62
63 return isolate->ThrowAt<Cell>(
64 isolate->factory()->NewSyntaxError(MessageTemplate::kUnresolvableExport,
65 module_specifier, export_name),
66 &loc);
67 }
68
69 // Implements Synthetic Module Record's Instantiate concrete method :
70 // https://heycam.github.io/webidl/#smr-instantiate
PrepareInstantiate(Isolate * isolate,Handle<SyntheticModule> module,v8::Local<v8::Context> context,v8::Module::ResolveCallback callback)71 bool SyntheticModule::PrepareInstantiate(Isolate* isolate,
72 Handle<SyntheticModule> module,
73 v8::Local<v8::Context> context,
74 v8::Module::ResolveCallback callback) {
75 Handle<ObjectHashTable> exports(module->exports(), isolate);
76 Handle<FixedArray> export_names(module->export_names(), isolate);
77 // Spec step 7: For each export_name in module->export_names...
78 for (int i = 0, n = export_names->length(); i < n; ++i) {
79 // Spec step 7.1: Create a new mutable binding for export_name.
80 // Spec step 7.2: Initialize the new mutable binding to undefined.
81 Handle<Cell> cell =
82 isolate->factory()->NewCell(isolate->factory()->undefined_value());
83 Handle<String> name(String::cast(export_names->get(i)), isolate);
84 CHECK(exports->Lookup(name).IsTheHole(isolate));
85 exports = ObjectHashTable::Put(exports, name, cell);
86 }
87 module->set_exports(*exports);
88 return true;
89 }
90
91 // Second step of module instantiation. No real work to do for SyntheticModule
92 // as there are no imports or indirect exports to resolve;
93 // just update status.
FinishInstantiate(Isolate * isolate,Handle<SyntheticModule> module)94 bool SyntheticModule::FinishInstantiate(Isolate* isolate,
95 Handle<SyntheticModule> module) {
96 module->SetStatus(kInstantiated);
97 return true;
98 }
99
100 // Implements Synthetic Module Record's Evaluate concrete method:
101 // https://heycam.github.io/webidl/#smr-evaluate
Evaluate(Isolate * isolate,Handle<SyntheticModule> module)102 MaybeHandle<Object> SyntheticModule::Evaluate(Isolate* isolate,
103 Handle<SyntheticModule> module) {
104 module->SetStatus(kEvaluating);
105
106 v8::Module::SyntheticModuleEvaluationSteps evaluation_steps =
107 FUNCTION_CAST<v8::Module::SyntheticModuleEvaluationSteps>(
108 module->evaluation_steps().foreign_address());
109 v8::Local<v8::Value> result;
110 if (!evaluation_steps(
111 Utils::ToLocal(Handle<Context>::cast(isolate->native_context())),
112 Utils::ToLocal(Handle<Module>::cast(module)))
113 .ToLocal(&result)) {
114 isolate->PromoteScheduledException();
115 Module::RecordErrorUsingPendingException(isolate, module);
116 return MaybeHandle<Object>();
117 }
118
119 module->SetStatus(kEvaluated);
120 return Utils::OpenHandle(*result);
121 }
122
123 } // namespace internal
124 } // namespace v8
125