GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
#include "module_wrap.h" |
||
2 |
|||
3 |
#include "env.h" |
||
4 |
#include "memory_tracker-inl.h" |
||
5 |
#include "node_contextify.h" |
||
6 |
#include "node_errors.h" |
||
7 |
#include "node_internals.h" |
||
8 |
#include "node_process-inl.h" |
||
9 |
#include "node_url.h" |
||
10 |
#include "node_watchdog.h" |
||
11 |
#include "util-inl.h" |
||
12 |
|||
13 |
#include <sys/stat.h> // S_IFDIR |
||
14 |
|||
15 |
#include <algorithm> |
||
16 |
|||
17 |
namespace node { |
||
18 |
namespace loader { |
||
19 |
|||
20 |
using errors::TryCatchScope; |
||
21 |
|||
22 |
using node::contextify::ContextifyContext; |
||
23 |
using node::url::URL; |
||
24 |
using node::url::URL_FLAGS_FAILED; |
||
25 |
using v8::Array; |
||
26 |
using v8::ArrayBufferView; |
||
27 |
using v8::Context; |
||
28 |
using v8::EscapableHandleScope; |
||
29 |
using v8::FixedArray; |
||
30 |
using v8::Function; |
||
31 |
using v8::FunctionCallbackInfo; |
||
32 |
using v8::FunctionTemplate; |
||
33 |
using v8::HandleScope; |
||
34 |
using v8::Int32; |
||
35 |
using v8::Integer; |
||
36 |
using v8::IntegrityLevel; |
||
37 |
using v8::Isolate; |
||
38 |
using v8::Local; |
||
39 |
using v8::MaybeLocal; |
||
40 |
using v8::MicrotaskQueue; |
||
41 |
using v8::Module; |
||
42 |
using v8::ModuleRequest; |
||
43 |
using v8::Number; |
||
44 |
using v8::Object; |
||
45 |
using v8::PrimitiveArray; |
||
46 |
using v8::Promise; |
||
47 |
using v8::ScriptCompiler; |
||
48 |
using v8::ScriptOrigin; |
||
49 |
using v8::ScriptOrModule; |
||
50 |
using v8::String; |
||
51 |
using v8::UnboundModuleScript; |
||
52 |
using v8::Undefined; |
||
53 |
using v8::Value; |
||
54 |
|||
55 |
45218 |
ModuleWrap::ModuleWrap(Environment* env, |
|
56 |
Local<Object> object, |
||
57 |
Local<Module> module, |
||
58 |
45218 |
Local<String> url) |
|
59 |
: BaseObject(env, object), |
||
60 |
module_(env->isolate(), module), |
||
61 |
90436 |
id_(env->get_next_module_id()) { |
|
62 |
45218 |
env->id_to_module_map.emplace(id_, this); |
|
63 |
|||
64 |
90436 |
Local<Value> undefined = Undefined(env->isolate()); |
|
65 |
45218 |
object->SetInternalField(kURLSlot, url); |
|
66 |
45218 |
object->SetInternalField(kSyntheticEvaluationStepsSlot, undefined); |
|
67 |
45218 |
object->SetInternalField(kContextObjectSlot, undefined); |
|
68 |
45218 |
} |
|
69 |
|||
70 |
250614 |
ModuleWrap::~ModuleWrap() { |
|
71 |
167076 |
HandleScope scope(env()->isolate()); |
|
72 |
83538 |
Local<Module> module = module_.Get(env()->isolate()); |
|
73 |
83538 |
env()->id_to_module_map.erase(id_); |
|
74 |
83538 |
auto range = env()->hash_to_module_map.equal_range(module->GetIdentityHash()); |
|
75 |
✓✗ | 83538 |
for (auto it = range.first; it != range.second; ++it) { |
76 |
✓✗ | 83538 |
if (it->second == this) { |
77 |
83538 |
env()->hash_to_module_map.erase(it); |
|
78 |
83538 |
break; |
|
79 |
} |
||
80 |
} |
||
81 |
167076 |
} |
|
82 |
|||
83 |
90509 |
Local<Context> ModuleWrap::context() const { |
|
84 |
271527 |
Local<Value> obj = object()->GetInternalField(kContextObjectSlot); |
|
85 |
✗✓ | 90509 |
if (obj.IsEmpty()) return {}; |
86 |
181018 |
return obj.As<Object>()->GetCreationContext().ToLocalChecked(); |
|
87 |
} |
||
88 |
|||
89 |
45416 |
ModuleWrap* ModuleWrap::GetFromModule(Environment* env, |
|
90 |
Local<Module> module) { |
||
91 |
45416 |
auto range = env->hash_to_module_map.equal_range(module->GetIdentityHash()); |
|
92 |
✓✗ | 45416 |
for (auto it = range.first; it != range.second; ++it) { |
93 |
✗✓✓✗ |
90832 |
if (it->second->module_ == module) { |
94 |
45416 |
return it->second; |
|
95 |
} |
||
96 |
} |
||
97 |
return nullptr; |
||
98 |
} |
||
99 |
|||
100 |
156 |
ModuleWrap* ModuleWrap::GetFromID(Environment* env, uint32_t id) { |
|
101 |
156 |
auto module_wrap_it = env->id_to_module_map.find(id); |
|
102 |
✗✓ | 156 |
if (module_wrap_it == env->id_to_module_map.end()) { |
103 |
return nullptr; |
||
104 |
} |
||
105 |
156 |
return module_wrap_it->second; |
|
106 |
} |
||
107 |
|||
108 |
// new ModuleWrap(url, context, source, lineOffset, columnOffset) |
||
109 |
// new ModuleWrap(url, context, exportNames, syntheticExecutionFunction) |
||
110 |
45225 |
void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) { |
|
111 |
✗✓ | 45225 |
CHECK(args.IsConstructCall()); |
112 |
✗✓ | 45225 |
CHECK_GE(args.Length(), 3); |
113 |
|||
114 |
45225 |
Environment* env = Environment::GetCurrent(args); |
|
115 |
45225 |
Isolate* isolate = env->isolate(); |
|
116 |
|||
117 |
✓✗ | 45225 |
Local<Object> that = args.This(); |
118 |
|||
119 |
✗✓ | 90450 |
CHECK(args[0]->IsString()); |
120 |
✓✗ | 90450 |
Local<String> url = args[0].As<String>(); |
121 |
|||
122 |
Local<Context> context; |
||
123 |
✓✗ | 45225 |
ContextifyContext* contextify_context = nullptr; |
124 |
✓✓ | 90450 |
if (args[1]->IsUndefined()) { |
125 |
90406 |
context = that->GetCreationContext().ToLocalChecked(); |
|
126 |
} else { |
||
127 |
✗✓ | 22 |
CHECK(args[1]->IsObject()); |
128 |
44 |
contextify_context = ContextifyContext::ContextFromContextifiedSandbox( |
|
129 |
44 |
env, args[1].As<Object>()); |
|
130 |
✗✓ | 22 |
CHECK_NOT_NULL(contextify_context); |
131 |
22 |
context = contextify_context->context(); |
|
132 |
} |
||
133 |
|||
134 |
45225 |
int line_offset = 0; |
|
135 |
✓✗ | 45225 |
int column_offset = 0; |
136 |
|||
137 |
45225 |
bool synthetic = args[2]->IsArray(); |
|
138 |
✓✓ | 45225 |
if (synthetic) { |
139 |
// new ModuleWrap(url, context, exportNames, syntheticExecutionFunction) |
||
140 |
✗✓ | 44670 |
CHECK(args[3]->IsFunction()); |
141 |
} else { |
||
142 |
// new ModuleWrap(url, context, source, lineOffset, columOffset, cachedData) |
||
143 |
✗✓ | 1110 |
CHECK(args[2]->IsString()); |
144 |
✗✓ | 555 |
CHECK(args[3]->IsNumber()); |
145 |
✓✗ | 1110 |
line_offset = args[3].As<Int32>()->Value(); |
146 |
✗✓ | 555 |
CHECK(args[4]->IsNumber()); |
147 |
1110 |
column_offset = args[4].As<Int32>()->Value(); |
|
148 |
} |
||
149 |
|||
150 |
Local<PrimitiveArray> host_defined_options = |
||
151 |
45225 |
PrimitiveArray::New(isolate, HostDefinedOptions::kLength); |
|
152 |
90450 |
host_defined_options->Set(isolate, HostDefinedOptions::kType, |
|
153 |
Number::New(isolate, ScriptType::kModule)); |
||
154 |
|||
155 |
45225 |
ShouldNotAbortOnUncaughtScope no_abort_scope(env); |
|
156 |
45225 |
TryCatchScope try_catch(env); |
|
157 |
|||
158 |
Local<Module> module; |
||
159 |
|||
160 |
{ |
||
161 |
45225 |
Context::Scope context_scope(context); |
|
162 |
✓✓ | 45225 |
if (synthetic) { |
163 |
✗✓ | 44670 |
CHECK(args[2]->IsArray()); |
164 |
89340 |
Local<Array> export_names_arr = args[2].As<Array>(); |
|
165 |
|||
166 |
44670 |
uint32_t len = export_names_arr->Length(); |
|
167 |
89340 |
std::vector<Local<String>> export_names(len); |
|
168 |
✓✓ | 1438733 |
for (uint32_t i = 0; i < len; i++) { |
169 |
Local<Value> export_name_val = |
||
170 |
2788126 |
export_names_arr->Get(context, i).ToLocalChecked(); |
|
171 |
✗✓ | 2788126 |
CHECK(export_name_val->IsString()); |
172 |
2788126 |
export_names[i] = export_name_val.As<String>(); |
|
173 |
} |
||
174 |
|||
175 |
module = Module::CreateSyntheticModule(isolate, url, export_names, |
||
176 |
44670 |
SyntheticModuleEvaluationStepsCallback); |
|
177 |
} else { |
||
178 |
✓✗ | 555 |
ScriptCompiler::CachedData* cached_data = nullptr; |
179 |
✓✓ | 1110 |
if (!args[5]->IsUndefined()) { |
180 |
✗✓ | 2 |
CHECK(args[5]->IsArrayBufferView()); |
181 |
4 |
Local<ArrayBufferView> cached_data_buf = args[5].As<ArrayBufferView>(); |
|
182 |
uint8_t* data = static_cast<uint8_t*>( |
||
183 |
4 |
cached_data_buf->Buffer()->GetBackingStore()->Data()); |
|
184 |
2 |
cached_data = |
|
185 |
2 |
new ScriptCompiler::CachedData(data + cached_data_buf->ByteOffset(), |
|
186 |
2 |
cached_data_buf->ByteLength()); |
|
187 |
} |
||
188 |
|||
189 |
1110 |
Local<String> source_text = args[2].As<String>(); |
|
190 |
ScriptOrigin origin(isolate, |
||
191 |
url, |
||
192 |
line_offset, |
||
193 |
column_offset, |
||
194 |
true, // is cross origin |
||
195 |
-1, // script id |
||
196 |
Local<Value>(), // source map URL |
||
197 |
false, // is opaque (?) |
||
198 |
false, // is WASM |
||
199 |
true, // is ES Module |
||
200 |
✓✗ | 1110 |
host_defined_options); |
201 |
555 |
ScriptCompiler::Source source(source_text, origin, cached_data); |
|
202 |
ScriptCompiler::CompileOptions options; |
||
203 |
✓✓ | 555 |
if (source.GetCachedData() == nullptr) { |
204 |
553 |
options = ScriptCompiler::kNoCompileOptions; |
|
205 |
} else { |
||
206 |
2 |
options = ScriptCompiler::kConsumeCodeCache; |
|
207 |
} |
||
208 |
555 |
if (!ScriptCompiler::CompileModule(isolate, &source, options) |
|
209 |
✓✓ | 555 |
.ToLocal(&module)) { |
210 |
✓✗✓✗ ✓✗ |
6 |
if (try_catch.HasCaught() && !try_catch.HasTerminated()) { |
211 |
✗✓ | 12 |
CHECK(!try_catch.Message().IsEmpty()); |
212 |
✗✓ | 12 |
CHECK(!try_catch.Exception().IsEmpty()); |
213 |
6 |
AppendExceptionLine(env, try_catch.Exception(), try_catch.Message(), |
|
214 |
ErrorHandlingMode::MODULE_ERROR); |
||
215 |
6 |
try_catch.ReThrow(); |
|
216 |
} |
||
217 |
6 |
return; |
|
218 |
} |
||
219 |
✓✓✓✓ |
551 |
if (options == ScriptCompiler::kConsumeCodeCache && |
220 |
✓✓ | 2 |
source.GetCachedData()->rejected) { |
221 |
1 |
THROW_ERR_VM_MODULE_CACHED_DATA_REJECTED( |
|
222 |
env, "cachedData buffer was rejected"); |
||
223 |
1 |
try_catch.ReThrow(); |
|
224 |
1 |
return; |
|
225 |
} |
||
226 |
} |
||
227 |
} |
||
228 |
|||
229 |
✓✗✗✓ |
135654 |
if (!that->Set(context, env->url_string(), url).FromMaybe(false)) { |
230 |
return; |
||
231 |
} |
||
232 |
|||
233 |
45218 |
ModuleWrap* obj = new ModuleWrap(env, that, module, url); |
|
234 |
|||
235 |
✓✓ | 45218 |
if (synthetic) { |
236 |
44670 |
obj->synthetic_ = true; |
|
237 |
✓✗ | 134010 |
obj->object()->SetInternalField(kSyntheticEvaluationStepsSlot, args[3]); |
238 |
} |
||
239 |
|||
240 |
// Use the extras object as an object whose GetCreationContext() will be the |
||
241 |
// original `context`, since the `Context` itself strictly speaking cannot |
||
242 |
// be stored in an internal field. |
||
243 |
135654 |
obj->object()->SetInternalField(kContextObjectSlot, |
|
244 |
context->GetExtrasBindingObject()); |
||
245 |
45218 |
obj->contextify_context_ = contextify_context; |
|
246 |
|||
247 |
45218 |
env->hash_to_module_map.emplace(module->GetIdentityHash(), obj); |
|
248 |
|||
249 |
90436 |
host_defined_options->Set(isolate, HostDefinedOptions::kID, |
|
250 |
45218 |
Number::New(isolate, obj->id())); |
|
251 |
|||
252 |
45218 |
that->SetIntegrityLevel(context, IntegrityLevel::kFrozen); |
|
253 |
90436 |
args.GetReturnValue().Set(that); |
|
254 |
} |
||
255 |
|||
256 |
824 |
void ModuleWrap::Link(const FunctionCallbackInfo<Value>& args) { |
|
257 |
824 |
Environment* env = Environment::GetCurrent(args); |
|
258 |
824 |
Isolate* isolate = args.GetIsolate(); |
|
259 |
|||
260 |
✗✓ | 824 |
CHECK_EQ(args.Length(), 1); |
261 |
✗✓ | 824 |
CHECK(args[0]->IsFunction()); |
262 |
|||
263 |
824 |
Local<Object> that = args.This(); |
|
264 |
|||
265 |
ModuleWrap* obj; |
||
266 |
✗✓ | 827 |
ASSIGN_OR_RETURN_UNWRAP(&obj, that); |
267 |
|||
268 |
✓✓ | 824 |
if (obj->linked_) |
269 |
3 |
return; |
|
270 |
✓✗ | 821 |
obj->linked_ = true; |
271 |
|||
272 |
821 |
Local<Function> resolver_arg = args[0].As<Function>(); |
|
273 |
|||
274 |
821 |
Local<Context> mod_context = obj->context(); |
|
275 |
✗✓ | 1642 |
Local<Module> module = obj->module_.Get(isolate); |
276 |
|||
277 |
821 |
Local<FixedArray> module_requests = module->GetModuleRequests(); |
|
278 |
821 |
const int module_requests_length = module_requests->Length(); |
|
279 |
821 |
MaybeStackBuffer<Local<Value>, 16> promises(module_requests_length); |
|
280 |
|||
281 |
// call the dependency resolve callbacks |
||
282 |
✓✓ | 1511 |
for (int i = 0; i < module_requests_length; i++) { |
283 |
Local<ModuleRequest> module_request = |
||
284 |
1380 |
module_requests->Get(env->context(), i).As<ModuleRequest>(); |
|
285 |
690 |
Local<String> specifier = module_request->GetSpecifier(); |
|
286 |
690 |
Utf8Value specifier_utf8(env->isolate(), specifier); |
|
287 |
1380 |
std::string specifier_std(*specifier_utf8, specifier_utf8.length()); |
|
288 |
|||
289 |
690 |
Local<FixedArray> raw_assertions = module_request->GetImportAssertions(); |
|
290 |
Local<Object> assertions = |
||
291 |
1380 |
Object::New(isolate, v8::Null(env->isolate()), nullptr, nullptr, 0); |
|
292 |
✓✓ | 1382 |
for (int i = 0; i < raw_assertions->Length(); i += 3) { |
293 |
assertions |
||
294 |
2 |
->Set(env->context(), |
|
295 |
Local<String>::Cast(raw_assertions->Get(env->context(), i)), |
||
296 |
8 |
Local<Value>::Cast(raw_assertions->Get(env->context(), i + 1))) |
|
297 |
.ToChecked(); |
||
298 |
} |
||
299 |
|||
300 |
Local<Value> argv[] = { |
||
301 |
specifier, |
||
302 |
assertions, |
||
303 |
690 |
}; |
|
304 |
|||
305 |
MaybeLocal<Value> maybe_resolve_return_value = |
||
306 |
690 |
resolver_arg->Call(mod_context, that, arraysize(argv), argv); |
|
307 |
✗✓ | 690 |
if (maybe_resolve_return_value.IsEmpty()) { |
308 |
return; |
||
309 |
} |
||
310 |
Local<Value> resolve_return_value = |
||
311 |
690 |
maybe_resolve_return_value.ToLocalChecked(); |
|
312 |
✗✓ | 690 |
if (!resolve_return_value->IsPromise()) { |
313 |
THROW_ERR_VM_MODULE_LINK_FAILURE( |
||
314 |
env, "request for '%s' did not return promise", specifier_std); |
||
315 |
return; |
||
316 |
} |
||
317 |
690 |
Local<Promise> resolve_promise = resolve_return_value.As<Promise>(); |
|
318 |
690 |
obj->resolve_cache_[specifier_std].Reset(env->isolate(), resolve_promise); |
|
319 |
|||
320 |
690 |
promises[i] = resolve_promise; |
|
321 |
} |
||
322 |
|||
323 |
1642 |
args.GetReturnValue().Set( |
|
324 |
Array::New(isolate, promises.out(), promises.length())); |
||
325 |
} |
||
326 |
|||
327 |
44844 |
void ModuleWrap::Instantiate(const FunctionCallbackInfo<Value>& args) { |
|
328 |
44844 |
Environment* env = Environment::GetCurrent(args); |
|
329 |
44844 |
Isolate* isolate = args.GetIsolate(); |
|
330 |
ModuleWrap* obj; |
||
331 |
✗✓ | 44857 |
ASSIGN_OR_RETURN_UNWRAP(&obj, args.This()); |
332 |
44844 |
Local<Context> context = obj->context(); |
|
333 |
✗✓ | 44844 |
Local<Module> module = obj->module_.Get(isolate); |
334 |
44844 |
TryCatchScope try_catch(env); |
|
335 |
44844 |
USE(module->InstantiateModule(context, ResolveModuleCallback)); |
|
336 |
|||
337 |
// clear resolve cache on instantiate |
||
338 |
44844 |
obj->resolve_cache_.clear(); |
|
339 |
|||
340 |
✓✓✓✗ ✓✓ |
44844 |
if (try_catch.HasCaught() && !try_catch.HasTerminated()) { |
341 |
✗✓ | 26 |
CHECK(!try_catch.Message().IsEmpty()); |
342 |
✗✓ | 26 |
CHECK(!try_catch.Exception().IsEmpty()); |
343 |
13 |
AppendExceptionLine(env, try_catch.Exception(), try_catch.Message(), |
|
344 |
ErrorHandlingMode::MODULE_ERROR); |
||
345 |
13 |
try_catch.ReThrow(); |
|
346 |
13 |
return; |
|
347 |
} |
||
348 |
} |
||
349 |
|||
350 |
44844 |
void ModuleWrap::Evaluate(const FunctionCallbackInfo<Value>& args) { |
|
351 |
44844 |
Environment* env = Environment::GetCurrent(args); |
|
352 |
44844 |
Isolate* isolate = env->isolate(); |
|
353 |
ModuleWrap* obj; |
||
354 |
✗✓ | 44853 |
ASSIGN_OR_RETURN_UNWRAP(&obj, args.This()); |
355 |
44844 |
Local<Context> context = obj->context(); |
|
356 |
✗✓ | 44844 |
Local<Module> module = obj->module_.Get(isolate); |
357 |
|||
358 |
44844 |
ContextifyContext* contextify_context = obj->contextify_context_; |
|
359 |
44844 |
std::shared_ptr<MicrotaskQueue> microtask_queue; |
|
360 |
✓✓ | 44844 |
if (contextify_context != nullptr) |
361 |
4 |
microtask_queue = contextify_context->microtask_queue(); |
|
362 |
|||
363 |
// module.evaluate(timeout, breakOnSigint) |
||
364 |
✗✓ | 44844 |
CHECK_EQ(args.Length(), 2); |
365 |
|||
366 |
✗✓ | 44844 |
CHECK(args[0]->IsNumber()); |
367 |
✓✗ | 89688 |
int64_t timeout = args[0]->IntegerValue(env->context()).FromJust(); |
368 |
|||
369 |
✗✓ | 44844 |
CHECK(args[1]->IsBoolean()); |
370 |
44844 |
bool break_on_sigint = args[1]->IsTrue(); |
|
371 |
|||
372 |
44844 |
ShouldNotAbortOnUncaughtScope no_abort_scope(env); |
|
373 |
44844 |
TryCatchScope try_catch(env); |
|
374 |
44844 |
Isolate::SafeForTerminationScope safe_for_termination(env->isolate()); |
|
375 |
|||
376 |
44844 |
bool timed_out = false; |
|
377 |
✗✓ | 44844 |
bool received_signal = false; |
378 |
MaybeLocal<Value> result; |
||
379 |
44844 |
auto run = [&]() { |
|
380 |
44844 |
MaybeLocal<Value> result = module->Evaluate(context); |
|
381 |
✓✓✓✓ ✓✓ |
44842 |
if (!result.IsEmpty() && microtask_queue) |
382 |
1 |
microtask_queue->PerformCheckpoint(isolate); |
|
383 |
44842 |
return result; |
|
384 |
44844 |
}; |
|
385 |
✗✓✗✗ |
44844 |
if (break_on_sigint && timeout != -1) { |
386 |
Watchdog wd(isolate, timeout, &timed_out); |
||
387 |
SigintWatchdog swd(isolate, &received_signal); |
||
388 |
result = run(); |
||
389 |
✗✓ | 44844 |
} else if (break_on_sigint) { |
390 |
SigintWatchdog swd(isolate, &received_signal); |
||
391 |
result = run(); |
||
392 |
✓✓ | 44844 |
} else if (timeout != -1) { |
393 |
6 |
Watchdog wd(isolate, timeout, &timed_out); |
|
394 |
3 |
result = run(); |
|
395 |
} else { |
||
396 |
44841 |
result = run(); |
|
397 |
} |
||
398 |
|||
399 |
✓✓ | 44842 |
if (result.IsEmpty()) { |
400 |
✗✓ | 3 |
CHECK(try_catch.HasCaught()); |
401 |
} |
||
402 |
|||
403 |
// Convert the termination exception into a regular exception. |
||
404 |
✓✓✗✓ |
44842 |
if (timed_out || received_signal) { |
405 |
✗✓✗✗ ✗✓ |
3 |
if (!env->is_main_thread() && env->is_stopping()) |
406 |
return; |
||
407 |
3 |
env->isolate()->CancelTerminateExecution(); |
|
408 |
// It is possible that execution was terminated by another timeout in |
||
409 |
// which this timeout is nested, so check whether one of the watchdogs |
||
410 |
// from this invocation is responsible for termination. |
||
411 |
✓✗ | 3 |
if (timed_out) { |
412 |
3 |
THROW_ERR_SCRIPT_EXECUTION_TIMEOUT(env, timeout); |
|
413 |
} else if (received_signal) { |
||
414 |
THROW_ERR_SCRIPT_EXECUTION_INTERRUPTED(env); |
||
415 |
} |
||
416 |
} |
||
417 |
|||
418 |
✓✓ | 44842 |
if (try_catch.HasCaught()) { |
419 |
✓✓ | 9 |
if (!try_catch.HasTerminated()) |
420 |
8 |
try_catch.ReThrow(); |
|
421 |
9 |
return; |
|
422 |
} |
||
423 |
|||
424 |
// If TLA is enabled, `result` is the evaluation's promise. |
||
425 |
// Otherwise, `result` is the last evaluated value of the module, |
||
426 |
// which could be a promise, which would result in it being incorrectly |
||
427 |
// unwrapped when the higher level code awaits the evaluation. |
||
428 |
✓✗ | 44833 |
if (env->isolate_data()->options()->experimental_top_level_await) { |
429 |
✗✓ | 89666 |
args.GetReturnValue().Set(result.ToLocalChecked()); |
430 |
} |
||
431 |
} |
||
432 |
|||
433 |
229 |
void ModuleWrap::GetNamespace(const FunctionCallbackInfo<Value>& args) { |
|
434 |
229 |
Environment* env = Environment::GetCurrent(args); |
|
435 |
229 |
Isolate* isolate = args.GetIsolate(); |
|
436 |
ModuleWrap* obj; |
||
437 |
✗✓ | 229 |
ASSIGN_OR_RETURN_UNWRAP(&obj, args.This()); |
438 |
|||
439 |
✗✓ | 458 |
Local<Module> module = obj->module_.Get(isolate); |
440 |
|||
441 |
✗✓✗ | 229 |
switch (module->GetStatus()) { |
442 |
case v8::Module::Status::kUninstantiated: |
||
443 |
case v8::Module::Status::kInstantiating: |
||
444 |
return env->ThrowError( |
||
445 |
"cannot get namespace, module has not been instantiated"); |
||
446 |
229 |
case v8::Module::Status::kInstantiated: |
|
447 |
case v8::Module::Status::kEvaluating: |
||
448 |
case v8::Module::Status::kEvaluated: |
||
449 |
case v8::Module::Status::kErrored: |
||
450 |
229 |
break; |
|
451 |
default: |
||
452 |
UNREACHABLE(); |
||
453 |
} |
||
454 |
|||
455 |
229 |
Local<Value> result = module->GetModuleNamespace(); |
|
456 |
458 |
args.GetReturnValue().Set(result); |
|
457 |
} |
||
458 |
|||
459 |
212 |
void ModuleWrap::GetStatus(const FunctionCallbackInfo<Value>& args) { |
|
460 |
212 |
Isolate* isolate = args.GetIsolate(); |
|
461 |
ModuleWrap* obj; |
||
462 |
✗✓ | 212 |
ASSIGN_OR_RETURN_UNWRAP(&obj, args.This()); |
463 |
|||
464 |
✗✓ | 424 |
Local<Module> module = obj->module_.Get(isolate); |
465 |
|||
466 |
424 |
args.GetReturnValue().Set(module->GetStatus()); |
|
467 |
} |
||
468 |
|||
469 |
2 |
void ModuleWrap::GetStaticDependencySpecifiers( |
|
470 |
const FunctionCallbackInfo<Value>& args) { |
||
471 |
2 |
Environment* env = Environment::GetCurrent(args); |
|
472 |
ModuleWrap* obj; |
||
473 |
✗✓ | 2 |
ASSIGN_OR_RETURN_UNWRAP(&obj, args.This()); |
474 |
|||
475 |
4 |
Local<Module> module = obj->module_.Get(env->isolate()); |
|
476 |
|||
477 |
2 |
Local<FixedArray> module_requests = module->GetModuleRequests(); |
|
478 |
2 |
int count = module_requests->Length(); |
|
479 |
|||
480 |
2 |
MaybeStackBuffer<Local<Value>, 16> specifiers(count); |
|
481 |
|||
482 |
✓✓ | 3 |
for (int i = 0; i < count; i++) { |
483 |
Local<ModuleRequest> module_request = |
||
484 |
2 |
module_requests->Get(env->context(), i).As<ModuleRequest>(); |
|
485 |
2 |
specifiers[i] = module_request->GetSpecifier(); |
|
486 |
} |
||
487 |
|||
488 |
4 |
args.GetReturnValue().Set( |
|
489 |
Array::New(env->isolate(), specifiers.out(), count)); |
||
490 |
} |
||
491 |
|||
492 |
1 |
void ModuleWrap::GetError(const FunctionCallbackInfo<Value>& args) { |
|
493 |
1 |
Isolate* isolate = args.GetIsolate(); |
|
494 |
ModuleWrap* obj; |
||
495 |
✗✓ | 1 |
ASSIGN_OR_RETURN_UNWRAP(&obj, args.This()); |
496 |
|||
497 |
✗✓ | 2 |
Local<Module> module = obj->module_.Get(isolate); |
498 |
2 |
args.GetReturnValue().Set(module->GetException()); |
|
499 |
} |
||
500 |
|||
501 |
669 |
MaybeLocal<Module> ModuleWrap::ResolveModuleCallback( |
|
502 |
Local<Context> context, |
||
503 |
Local<String> specifier, |
||
504 |
Local<FixedArray> import_assertions, |
||
505 |
Local<Module> referrer) { |
||
506 |
669 |
Environment* env = Environment::GetCurrent(context); |
|
507 |
✗✓ | 669 |
if (env == nullptr) { |
508 |
Isolate* isolate = context->GetIsolate(); |
||
509 |
THROW_ERR_EXECUTION_ENVIRONMENT_NOT_AVAILABLE(isolate); |
||
510 |
return MaybeLocal<Module>(); |
||
511 |
} |
||
512 |
|||
513 |
669 |
Isolate* isolate = env->isolate(); |
|
514 |
|||
515 |
1338 |
Utf8Value specifier_utf8(isolate, specifier); |
|
516 |
1338 |
std::string specifier_std(*specifier_utf8, specifier_utf8.length()); |
|
517 |
|||
518 |
669 |
ModuleWrap* dependent = GetFromModule(env, referrer); |
|
519 |
✗✓ | 669 |
if (dependent == nullptr) { |
520 |
THROW_ERR_VM_MODULE_LINK_FAILURE( |
||
521 |
env, "request for '%s' is from invalid module", specifier_std); |
||
522 |
return MaybeLocal<Module>(); |
||
523 |
} |
||
524 |
|||
525 |
✗✓ | 669 |
if (dependent->resolve_cache_.count(specifier_std) != 1) { |
526 |
THROW_ERR_VM_MODULE_LINK_FAILURE( |
||
527 |
env, "request for '%s' is not in cache", specifier_std); |
||
528 |
return MaybeLocal<Module>(); |
||
529 |
} |
||
530 |
|||
531 |
Local<Promise> resolve_promise = |
||
532 |
✗✓ | 1338 |
dependent->resolve_cache_[specifier_std].Get(isolate); |
533 |
|||
534 |
✗✓ | 669 |
if (resolve_promise->State() != Promise::kFulfilled) { |
535 |
THROW_ERR_VM_MODULE_LINK_FAILURE( |
||
536 |
env, "request for '%s' is not yet fulfilled", specifier_std); |
||
537 |
return MaybeLocal<Module>(); |
||
538 |
} |
||
539 |
|||
540 |
1338 |
Local<Object> module_object = resolve_promise->Result().As<Object>(); |
|
541 |
✓✗✗✓ ✗✓ |
1338 |
if (module_object.IsEmpty() || !module_object->IsObject()) { |
542 |
THROW_ERR_VM_MODULE_LINK_FAILURE( |
||
543 |
env, "request for '%s' did not return an object", specifier_std); |
||
544 |
return MaybeLocal<Module>(); |
||
545 |
} |
||
546 |
|||
547 |
ModuleWrap* module; |
||
548 |
✗✓ | 669 |
ASSIGN_OR_RETURN_UNWRAP(&module, module_object, MaybeLocal<Module>()); |
549 |
✗✓ | 1338 |
return module->module_.Get(isolate); |
550 |
} |
||
551 |
|||
552 |
234 |
static MaybeLocal<Promise> ImportModuleDynamically( |
|
553 |
Local<Context> context, |
||
554 |
Local<ScriptOrModule> referrer, |
||
555 |
Local<String> specifier, |
||
556 |
Local<FixedArray> import_assertions) { |
||
557 |
234 |
Isolate* isolate = context->GetIsolate(); |
|
558 |
234 |
Environment* env = Environment::GetCurrent(context); |
|
559 |
✗✓ | 234 |
if (env == nullptr) { |
560 |
THROW_ERR_EXECUTION_ENVIRONMENT_NOT_AVAILABLE(isolate); |
||
561 |
return MaybeLocal<Promise>(); |
||
562 |
} |
||
563 |
|||
564 |
234 |
EscapableHandleScope handle_scope(isolate); |
|
565 |
|||
566 |
Local<Function> import_callback = |
||
567 |
234 |
env->host_import_module_dynamically_callback(); |
|
568 |
|||
569 |
234 |
Local<PrimitiveArray> options = referrer->GetHostDefinedOptions(); |
|
570 |
✗✓ | 234 |
if (options->Length() != HostDefinedOptions::kLength) { |
571 |
Local<Promise::Resolver> resolver; |
||
572 |
if (!Promise::Resolver::New(context).ToLocal(&resolver)) return {}; |
||
573 |
resolver |
||
574 |
->Reject(context, |
||
575 |
v8::Exception::TypeError(FIXED_ONE_BYTE_STRING( |
||
576 |
context->GetIsolate(), "Invalid host defined options"))) |
||
577 |
.ToChecked(); |
||
578 |
return handle_scope.Escape(resolver->GetPromise()); |
||
579 |
} |
||
580 |
|||
581 |
Local<Value> object; |
||
582 |
|||
583 |
234 |
int type = options->Get(isolate, HostDefinedOptions::kType) |
|
584 |
234 |
.As<Number>() |
|
585 |
234 |
->Int32Value(context) |
|
586 |
234 |
.ToChecked(); |
|
587 |
234 |
uint32_t id = options->Get(isolate, HostDefinedOptions::kID) |
|
588 |
234 |
.As<Number>() |
|
589 |
234 |
->Uint32Value(context) |
|
590 |
234 |
.ToChecked(); |
|
591 |
✓✓ | 234 |
if (type == ScriptType::kScript) { |
592 |
7 |
contextify::ContextifyScript* wrap = env->id_to_script_map.find(id)->second; |
|
593 |
14 |
object = wrap->object(); |
|
594 |
✓✓ | 227 |
} else if (type == ScriptType::kModule) { |
595 |
156 |
ModuleWrap* wrap = ModuleWrap::GetFromID(env, id); |
|
596 |
312 |
object = wrap->object(); |
|
597 |
✓✗ | 71 |
} else if (type == ScriptType::kFunction) { |
598 |
71 |
auto it = env->id_to_function_map.find(id); |
|
599 |
✗✓ | 71 |
CHECK_NE(it, env->id_to_function_map.end()); |
600 |
142 |
object = it->second->object(); |
|
601 |
} else { |
||
602 |
UNREACHABLE(); |
||
603 |
} |
||
604 |
|||
605 |
Local<Value> import_args[] = { |
||
606 |
object, |
||
607 |
Local<Value>(specifier), |
||
608 |
234 |
}; |
|
609 |
|||
610 |
Local<Value> result; |
||
611 |
468 |
if (import_callback->Call( |
|
612 |
context, |
||
613 |
Undefined(isolate), |
||
614 |
234 |
arraysize(import_args), |
|
615 |
✓✗ | 702 |
import_args).ToLocal(&result)) { |
616 |
✗✓ | 234 |
CHECK(result->IsPromise()); |
617 |
234 |
return handle_scope.Escape(result.As<Promise>()); |
|
618 |
} |
||
619 |
|||
620 |
return MaybeLocal<Promise>(); |
||
621 |
} |
||
622 |
|||
623 |
5425 |
void ModuleWrap::SetImportModuleDynamicallyCallback( |
|
624 |
const FunctionCallbackInfo<Value>& args) { |
||
625 |
5425 |
Isolate* isolate = args.GetIsolate(); |
|
626 |
5425 |
Environment* env = Environment::GetCurrent(args); |
|
627 |
10850 |
HandleScope handle_scope(isolate); |
|
628 |
|||
629 |
✗✓ | 5425 |
CHECK_EQ(args.Length(), 1); |
630 |
✗✓ | 5425 |
CHECK(args[0]->IsFunction()); |
631 |
5425 |
Local<Function> import_callback = args[0].As<Function>(); |
|
632 |
5425 |
env->set_host_import_module_dynamically_callback(import_callback); |
|
633 |
|||
634 |
5425 |
isolate->SetHostImportModuleDynamicallyCallback(ImportModuleDynamically); |
|
635 |
5425 |
} |
|
636 |
|||
637 |
93 |
void ModuleWrap::HostInitializeImportMetaObjectCallback( |
|
638 |
Local<Context> context, Local<Module> module, Local<Object> meta) { |
||
639 |
93 |
Environment* env = Environment::GetCurrent(context); |
|
640 |
✗✓ | 93 |
if (env == nullptr) |
641 |
return; |
||
642 |
93 |
ModuleWrap* module_wrap = GetFromModule(env, module); |
|
643 |
|||
644 |
✗✓ | 93 |
if (module_wrap == nullptr) { |
645 |
return; |
||
646 |
} |
||
647 |
|||
648 |
93 |
Local<Object> wrap = module_wrap->object(); |
|
649 |
Local<Function> callback = |
||
650 |
93 |
env->host_initialize_import_meta_object_callback(); |
|
651 |
93 |
Local<Value> args[] = { wrap, meta }; |
|
652 |
186 |
TryCatchScope try_catch(env); |
|
653 |
93 |
USE(callback->Call( |
|
654 |
186 |
context, Undefined(env->isolate()), arraysize(args), args)); |
|
655 |
✗✓✗✗ ✗✓ |
93 |
if (try_catch.HasCaught() && !try_catch.HasTerminated()) { |
656 |
try_catch.ReThrow(); |
||
657 |
} |
||
658 |
} |
||
659 |
|||
660 |
5425 |
void ModuleWrap::SetInitializeImportMetaObjectCallback( |
|
661 |
const FunctionCallbackInfo<Value>& args) { |
||
662 |
5425 |
Environment* env = Environment::GetCurrent(args); |
|
663 |
5425 |
Isolate* isolate = env->isolate(); |
|
664 |
|||
665 |
✗✓ | 5425 |
CHECK_EQ(args.Length(), 1); |
666 |
✗✓ | 5425 |
CHECK(args[0]->IsFunction()); |
667 |
5425 |
Local<Function> import_meta_callback = args[0].As<Function>(); |
|
668 |
5425 |
env->set_host_initialize_import_meta_object_callback(import_meta_callback); |
|
669 |
|||
670 |
5425 |
isolate->SetHostInitializeImportMetaObjectCallback( |
|
671 |
HostInitializeImportMetaObjectCallback); |
||
672 |
5425 |
} |
|
673 |
|||
674 |
44654 |
MaybeLocal<Value> ModuleWrap::SyntheticModuleEvaluationStepsCallback( |
|
675 |
Local<Context> context, Local<Module> module) { |
||
676 |
44654 |
Environment* env = Environment::GetCurrent(context); |
|
677 |
44654 |
Isolate* isolate = env->isolate(); |
|
678 |
|||
679 |
44654 |
ModuleWrap* obj = GetFromModule(env, module); |
|
680 |
|||
681 |
89308 |
TryCatchScope try_catch(env); |
|
682 |
Local<Function> synthetic_evaluation_steps = |
||
683 |
133962 |
obj->object()->GetInternalField(kSyntheticEvaluationStepsSlot) |
|
684 |
44654 |
.As<Function>(); |
|
685 |
133962 |
obj->object()->SetInternalField( |
|
686 |
kSyntheticEvaluationStepsSlot, Undefined(isolate)); |
||
687 |
MaybeLocal<Value> ret = synthetic_evaluation_steps->Call(context, |
||
688 |
89308 |
obj->object(), 0, nullptr); |
|
689 |
✓✓ | 44654 |
if (ret.IsEmpty()) { |
690 |
✗✓ | 5 |
CHECK(try_catch.HasCaught()); |
691 |
} |
||
692 |
✓✓✓✗ ✓✓ |
44654 |
if (try_catch.HasCaught() && !try_catch.HasTerminated()) { |
693 |
✗✓ | 10 |
CHECK(!try_catch.Message().IsEmpty()); |
694 |
✗✓ | 10 |
CHECK(!try_catch.Exception().IsEmpty()); |
695 |
5 |
try_catch.ReThrow(); |
|
696 |
5 |
return MaybeLocal<Value>(); |
|
697 |
} |
||
698 |
|||
699 |
Local<Promise::Resolver> resolver; |
||
700 |
✗✓ | 89298 |
if (!Promise::Resolver::New(context).ToLocal(&resolver)) { |
701 |
return MaybeLocal<Value>(); |
||
702 |
} |
||
703 |
|||
704 |
133947 |
resolver->Resolve(context, Undefined(isolate)).ToChecked(); |
|
705 |
89298 |
return resolver->GetPromise(); |
|
706 |
} |
||
707 |
|||
708 |
3871454 |
void ModuleWrap::SetSyntheticExport(const FunctionCallbackInfo<Value>& args) { |
|
709 |
3871454 |
Isolate* isolate = args.GetIsolate(); |
|
710 |
3871454 |
Local<Object> that = args.This(); |
|
711 |
|||
712 |
ModuleWrap* obj; |
||
713 |
✗✓ | 3871454 |
ASSIGN_OR_RETURN_UNWRAP(&obj, that); |
714 |
|||
715 |
✗✓ | 3871454 |
CHECK(obj->synthetic_); |
716 |
|||
717 |
✗✓ | 3871454 |
CHECK_EQ(args.Length(), 2); |
718 |
|||
719 |
✗✓ | 7742908 |
CHECK(args[0]->IsString()); |
720 |
✓✗ | 7742908 |
Local<String> export_name = args[0].As<String>(); |
721 |
|||
722 |
3871454 |
Local<Value> export_value = args[1]; |
|
723 |
|||
724 |
✗✓ | 7742908 |
Local<Module> module = obj->module_.Get(isolate); |
725 |
3871454 |
USE(module->SetSyntheticModuleExport(isolate, export_name, export_value)); |
|
726 |
} |
||
727 |
|||
728 |
1 |
void ModuleWrap::CreateCachedData(const FunctionCallbackInfo<Value>& args) { |
|
729 |
1 |
Isolate* isolate = args.GetIsolate(); |
|
730 |
1 |
Local<Object> that = args.This(); |
|
731 |
|||
732 |
ModuleWrap* obj; |
||
733 |
✗✓ | 1 |
ASSIGN_OR_RETURN_UNWRAP(&obj, that); |
734 |
|||
735 |
✗✓ | 1 |
CHECK(!obj->synthetic_); |
736 |
|||
737 |
✗✓ | 2 |
Local<Module> module = obj->module_.Get(isolate); |
738 |
|||
739 |
✗✓ | 1 |
CHECK_LT(module->GetStatus(), v8::Module::Status::kEvaluating); |
740 |
|||
741 |
Local<UnboundModuleScript> unbound_module_script = |
||
742 |
1 |
module->GetUnboundModuleScript(); |
|
743 |
std::unique_ptr<ScriptCompiler::CachedData> cached_data( |
||
744 |
2 |
ScriptCompiler::CreateCodeCache(unbound_module_script)); |
|
745 |
1 |
Environment* env = Environment::GetCurrent(args); |
|
746 |
✗✓ | 1 |
if (!cached_data) { |
747 |
args.GetReturnValue().Set(Buffer::New(env, 0).ToLocalChecked()); |
||
748 |
} else { |
||
749 |
MaybeLocal<Object> buf = |
||
750 |
Buffer::Copy(env, |
||
751 |
2 |
reinterpret_cast<const char*>(cached_data->data), |
|
752 |
1 |
cached_data->length); |
|
753 |
✗✓ | 2 |
args.GetReturnValue().Set(buf.ToLocalChecked()); |
754 |
} |
||
755 |
} |
||
756 |
|||
757 |
5426 |
void ModuleWrap::Initialize(Local<Object> target, |
|
758 |
Local<Value> unused, |
||
759 |
Local<Context> context, |
||
760 |
void* priv) { |
||
761 |
5426 |
Environment* env = Environment::GetCurrent(context); |
|
762 |
|||
763 |
5426 |
Local<FunctionTemplate> tpl = env->NewFunctionTemplate(New); |
|
764 |
10852 |
tpl->InstanceTemplate()->SetInternalFieldCount( |
|
765 |
ModuleWrap::kInternalFieldCount); |
||
766 |
5426 |
tpl->Inherit(BaseObject::GetConstructorTemplate(env)); |
|
767 |
|||
768 |
5426 |
env->SetProtoMethod(tpl, "link", Link); |
|
769 |
5426 |
env->SetProtoMethod(tpl, "instantiate", Instantiate); |
|
770 |
5426 |
env->SetProtoMethod(tpl, "evaluate", Evaluate); |
|
771 |
5426 |
env->SetProtoMethod(tpl, "setExport", SetSyntheticExport); |
|
772 |
5426 |
env->SetProtoMethodNoSideEffect(tpl, "createCachedData", CreateCachedData); |
|
773 |
5426 |
env->SetProtoMethodNoSideEffect(tpl, "getNamespace", GetNamespace); |
|
774 |
5426 |
env->SetProtoMethodNoSideEffect(tpl, "getStatus", GetStatus); |
|
775 |
5426 |
env->SetProtoMethodNoSideEffect(tpl, "getError", GetError); |
|
776 |
5426 |
env->SetProtoMethodNoSideEffect(tpl, "getStaticDependencySpecifiers", |
|
777 |
GetStaticDependencySpecifiers); |
||
778 |
|||
779 |
5426 |
env->SetConstructorFunction(target, "ModuleWrap", tpl); |
|
780 |
|||
781 |
5426 |
env->SetMethod(target, |
|
782 |
"setImportModuleDynamicallyCallback", |
||
783 |
SetImportModuleDynamicallyCallback); |
||
784 |
5426 |
env->SetMethod(target, |
|
785 |
"setInitializeImportMetaObjectCallback", |
||
786 |
SetInitializeImportMetaObjectCallback); |
||
787 |
|||
788 |
#define V(name) \ |
||
789 |
target->Set(context, \ |
||
790 |
FIXED_ONE_BYTE_STRING(env->isolate(), #name), \ |
||
791 |
Integer::New(env->isolate(), Module::Status::name)) \ |
||
792 |
.FromJust() |
||
793 |
21704 |
V(kUninstantiated); |
|
794 |
21704 |
V(kInstantiating); |
|
795 |
21704 |
V(kInstantiated); |
|
796 |
21704 |
V(kEvaluating); |
|
797 |
21704 |
V(kEvaluated); |
|
798 |
16278 |
V(kErrored); |
|
799 |
#undef V |
||
800 |
5426 |
} |
|
801 |
|||
802 |
} // namespace loader |
||
803 |
} // namespace node |
||
804 |
|||
805 |
4926 |
NODE_MODULE_CONTEXT_AWARE_INTERNAL(module_wrap, |
|
806 |
node::loader::ModuleWrap::Initialize) |
Generated by: GCOVR (Version 4.2) |