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