Skip to content

Commit 9275d5b

Browse files
committed
feat: provide node:url polyfill
1 parent 74e4097 commit 9275d5b

File tree

1 file changed

+68
-5
lines changed

1 file changed

+68
-5
lines changed

test-app/runtime/src/main/cpp/ModuleInternalCallbacks.cpp

Lines changed: 68 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -235,12 +235,75 @@ v8::MaybeLocal<v8::Module> ResolveModuleCallback(v8::Local<v8::Context> context,
235235
// Check for Node.js built-in modules
236236
if (IsNodeBuiltinModule(spec)) {
237237
std::string builtinName = spec.substr(5); // Remove "node:" prefix
238-
std::string builtinPath = appPath + "/" + builtinName + ".mjs";
239238

240-
// For now, just throw an error - polyfill creation would need file system access
241-
std::string msg = "Node.js built-in modules not supported yet: " + spec;
242-
isolate->ThrowException(v8::Exception::Error(ArgConverter::ConvertToV8String(isolate, msg)));
243-
return v8::MaybeLocal<v8::Module>();
239+
// Create polyfill content for Node.js built-in modules
240+
std::string polyfillContent;
241+
242+
if (builtinName == "url") {
243+
// Create a polyfill for node:url with fileURLToPath
244+
polyfillContent = "// Polyfill for node:url\n"
245+
"export function fileURLToPath(url) {\n"
246+
" if (typeof url === 'string') {\n"
247+
" if (url.startsWith('file://')) {\n"
248+
" return decodeURIComponent(url.slice(7));\n"
249+
" }\n"
250+
" return url;\n"
251+
" }\n"
252+
" if (url && typeof url.href === 'string') {\n"
253+
" return fileURLToPath(url.href);\n"
254+
" }\n"
255+
" throw new Error('Invalid URL');\n"
256+
"}\n"
257+
"\n"
258+
"export function pathToFileURL(path) {\n"
259+
" return new URL('file://' + encodeURIComponent(path));\n"
260+
"}\n";
261+
} else {
262+
// Generic polyfill for other Node.js built-in modules
263+
polyfillContent = "// Polyfill for node:" + builtinName + "\n"
264+
"console.warn('Node.js built-in module \\'node:" + builtinName + "\\' is not fully supported in NativeScript');\n"
265+
"export default {};\n";
266+
}
267+
268+
// Create module source and compile it in-memory
269+
v8::Local<v8::String> sourceText = ArgConverter::ConvertToV8String(isolate, polyfillContent);
270+
271+
// Build URL for stack traces
272+
std::string moduleUrl = "node:" + builtinName;
273+
v8::Local<v8::String> urlString = ArgConverter::ConvertToV8String(isolate, moduleUrl);
274+
275+
v8::ScriptOrigin origin(isolate, urlString, 0, 0, false, -1, v8::Local<v8::Value>(), false, false, true /* is_module */);
276+
v8::ScriptCompiler::Source src(sourceText, origin);
277+
278+
v8::Local<v8::Module> polyfillModule;
279+
if (!v8::ScriptCompiler::CompileModule(isolate, &src).ToLocal(&polyfillModule)) {
280+
std::string msg = "Failed to compile polyfill for: " + spec;
281+
isolate->ThrowException(v8::Exception::Error(ArgConverter::ConvertToV8String(isolate, msg)));
282+
return v8::MaybeLocal<v8::Module>();
283+
}
284+
285+
// Store in registry before instantiation
286+
g_moduleRegistry[spec].Reset(isolate, polyfillModule);
287+
288+
// Instantiate the module
289+
if (!polyfillModule->InstantiateModule(context, ResolveModuleCallback).FromMaybe(false)) {
290+
g_moduleRegistry.erase(spec);
291+
std::string msg = "Failed to instantiate polyfill for: " + spec;
292+
isolate->ThrowException(v8::Exception::Error(ArgConverter::ConvertToV8String(isolate, msg)));
293+
return v8::MaybeLocal<v8::Module>();
294+
}
295+
296+
// Evaluate the module
297+
v8::MaybeLocal<v8::Value> evalResult = polyfillModule->Evaluate(context);
298+
if (evalResult.IsEmpty()) {
299+
g_moduleRegistry.erase(spec);
300+
std::string msg = "Failed to evaluate polyfill for: " + spec;
301+
isolate->ThrowException(v8::Exception::Error(ArgConverter::ConvertToV8String(isolate, msg)));
302+
return v8::MaybeLocal<v8::Module>();
303+
}
304+
305+
return v8::MaybeLocal<v8::Module>(polyfillModule);
306+
244307
} else if (tns::ModuleInternal::IsLikelyOptionalModule(spec)) {
245308
// For optional modules, create a placeholder
246309
std::string msg = "Optional module not found: " + spec;

0 commit comments

Comments
 (0)