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