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