|
16 | 16 | #include "Helpers.h" // for tns::Exists |
17 | 17 | #include "ModuleInternal.h" // for LoadScript(...) |
18 | 18 | #include "NativeScriptException.h" |
| 19 | +#include "NsBuiltinModules.h" |
19 | 20 | #include "Runtime.h" // for GetAppConfigValue |
20 | 21 | #include "RuntimeConfig.h" |
21 | 22 |
|
@@ -715,6 +716,20 @@ static bool IsDocumentsPath(const std::string& path) { |
715 | 716 | return v8::MaybeLocal<v8::Module>(); |
716 | 717 | } |
717 | 718 |
|
| 719 | + // Builtin modules resolve before any path handling. Unshimmed "node:" names |
| 720 | + // fall through to the legacy node:url polyfill below. |
| 721 | + if (NsBuiltinModules::IsRegistered(rawSpec) || NsBuiltinModules::IsNsScheme(rawSpec)) { |
| 722 | + v8::Local<v8::Module> builtin; |
| 723 | + if (NsBuiltinModules::GetModule(context, rawSpec).ToLocal(&builtin)) { |
| 724 | + return v8::MaybeLocal<v8::Module>(builtin); |
| 725 | + } |
| 726 | + if (!NsBuiltinModules::IsRegistered(rawSpec)) { |
| 727 | + isolate->ThrowException(v8::Exception::Error( |
| 728 | + tns::ToV8String(isolate, NsBuiltinModules::NotFoundMessage(rawSpec)))); |
| 729 | + } |
| 730 | + return v8::MaybeLocal<v8::Module>(); |
| 731 | + } |
| 732 | + |
718 | 733 | std::string normalizedSpec = rawSpec; |
719 | 734 |
|
720 | 735 | // Normalize malformed HTTP(S) schemes that sometimes appear as 'http:/host' (single slash) |
@@ -1344,11 +1359,9 @@ static bool IsDocumentsPath(const std::string& path) { |
1344 | 1359 | " return new URL('file://' + encoded);\n" |
1345 | 1360 | "}\n"; |
1346 | 1361 | } else { |
1347 | | - // Generic polyfill for other Node.js built-in modules |
1348 | | - polyfillContent = "// In-memory polyfill for node:" + builtinName + "\n" + |
1349 | | - "console.warn('Node.js built-in module \\'node:" + builtinName + |
1350 | | - "\\' is not fully supported in NativeScript');\n" + |
1351 | | - "export default {};\n"; |
| 1362 | + isolate->ThrowException(v8::Exception::Error( |
| 1363 | + tns::ToV8String(isolate, NsBuiltinModules::NotFoundMessage(spec)))); |
| 1364 | + return v8::MaybeLocal<v8::Module>(); |
1352 | 1365 | } |
1353 | 1366 |
|
1354 | 1367 | v8::MaybeLocal<v8::Module> m = |
@@ -1862,6 +1875,29 @@ static bool IsDocumentsPath(const std::string& path) { |
1862 | 1875 | // Normalize spec: expand '@/'; only strip ?query/hash for non-HTTP specs so SFC HTTP keys keep |
1863 | 1876 | // version tags |
1864 | 1877 | std::string rawSpec = cSpec ? std::string(cSpec) : std::string(); |
| 1878 | + |
| 1879 | + // Builtin modules never reach the loader below; the namespace comes straight |
| 1880 | + // from the realm's synthetic module. |
| 1881 | + if (NsBuiltinModules::IsRegistered(rawSpec) || NsBuiltinModules::IsNsScheme(rawSpec)) { |
| 1882 | + v8::EscapableHandleScope builtinScope(isolate); |
| 1883 | + v8::Local<v8::Promise::Resolver> builtinResolver; |
| 1884 | + if (!v8::Promise::Resolver::New(context).ToLocal(&builtinResolver)) { |
| 1885 | + return v8::MaybeLocal<v8::Promise>(); |
| 1886 | + } |
| 1887 | + v8::TryCatch tc(isolate); |
| 1888 | + v8::Local<v8::Module> builtin; |
| 1889 | + if (NsBuiltinModules::GetModule(context, rawSpec).ToLocal(&builtin)) { |
| 1890 | + builtinResolver->Resolve(context, builtin->GetModuleNamespace()).FromMaybe(false); |
| 1891 | + } else { |
| 1892 | + v8::Local<v8::Value> error = tc.HasCaught() |
| 1893 | + ? tc.Exception() |
| 1894 | + : v8::Exception::Error(tns::ToV8String( |
| 1895 | + isolate, NsBuiltinModules::NotFoundMessage(rawSpec))); |
| 1896 | + builtinResolver->Reject(context, error).FromMaybe(false); |
| 1897 | + } |
| 1898 | + return builtinScope.Escape(builtinResolver->GetPromise()); |
| 1899 | + } |
| 1900 | + |
1865 | 1901 | std::string normalizedSpec = rawSpec; |
1866 | 1902 | // remove query/hash ONLY for non-HTTP specs |
1867 | 1903 | bool isHttpLike = (!normalizedSpec.empty() && (StartsWith(normalizedSpec, "http://") || |
|
0 commit comments