• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)71 bool SyntheticModule::PrepareInstantiate(Isolate* isolate,
72                                          Handle<SyntheticModule> module,
73                                          v8::Local<v8::Context> context) {
74   Handle<ObjectHashTable> exports(module->exports(), isolate);
75   Handle<FixedArray> export_names(module->export_names(), isolate);
76   // Spec step 7: For each export_name in module->export_names...
77   for (int i = 0, n = export_names->length(); i < n; ++i) {
78     // Spec step 7.1: Create a new mutable binding for export_name.
79     // Spec step 7.2: Initialize the new mutable binding to undefined.
80     Handle<Cell> cell =
81         isolate->factory()->NewCell(isolate->factory()->undefined_value());
82     Handle<String> name(String::cast(export_names->get(i)), isolate);
83     CHECK(exports->Lookup(name).IsTheHole(isolate));
84     exports = ObjectHashTable::Put(exports, name, cell);
85   }
86   module->set_exports(*exports);
87   return true;
88 }
89 
90 // Second step of module instantiation.  No real work to do for SyntheticModule
91 // as there are no imports or indirect exports to resolve;
92 // just update status.
FinishInstantiate(Isolate * isolate,Handle<SyntheticModule> module)93 bool SyntheticModule::FinishInstantiate(Isolate* isolate,
94                                         Handle<SyntheticModule> module) {
95   module->SetStatus(kLinked);
96   return true;
97 }
98 
99 // Implements Synthetic Module Record's Evaluate concrete method:
100 // https://heycam.github.io/webidl/#smr-evaluate
Evaluate(Isolate * isolate,Handle<SyntheticModule> module)101 MaybeHandle<Object> SyntheticModule::Evaluate(Isolate* isolate,
102                                               Handle<SyntheticModule> module) {
103   module->SetStatus(kEvaluating);
104 
105   v8::Module::SyntheticModuleEvaluationSteps evaluation_steps =
106       FUNCTION_CAST<v8::Module::SyntheticModuleEvaluationSteps>(
107           module->evaluation_steps().foreign_address());
108   v8::Local<v8::Value> result;
109   if (!evaluation_steps(
110            Utils::ToLocal(Handle<Context>::cast(isolate->native_context())),
111            Utils::ToLocal(Handle<Module>::cast(module)))
112            .ToLocal(&result)) {
113     isolate->PromoteScheduledException();
114     Module::RecordErrorUsingPendingException(isolate, module);
115     return MaybeHandle<Object>();
116   }
117 
118   module->SetStatus(kEvaluated);
119 
120   Handle<Object> result_from_callback = Utils::OpenHandle(*result);
121 
122   Handle<JSPromise> capability;
123   if (result_from_callback->IsJSPromise()) {
124     capability = Handle<JSPromise>::cast(result_from_callback);
125   } else {
126     // The host's evaluation steps should have returned a resolved Promise,
127     // but as an allowance to hosts that have not yet finished the migration
128     // to top-level await, create a Promise if the callback result didn't give
129     // us one.
130     capability = isolate->factory()->NewJSPromise();
131     JSPromise::Resolve(capability, isolate->factory()->undefined_value())
132         .ToHandleChecked();
133   }
134 
135   module->set_top_level_capability(*capability);
136 
137   return result_from_callback;
138 }
139 
140 }  // namespace internal
141 }  // namespace v8
142