diff options
author | 2023-09-10 22:15:35 -0800 | |
---|---|---|
committer | 2023-09-10 23:15:35 -0700 | |
commit | 51d3d4382281f789f8175079ed426a63529eb3e7 (patch) | |
tree | 14f6fe77a1e3b300488e9343d8e9d54f64bde376 /src/bun.js/bindings/ModuleLoader.cpp | |
parent | edea4f095a3bebf54f986c0fa038482316f4cde8 (diff) | |
download | bun-51d3d4382281f789f8175079ed426a63529eb3e7.tar.gz bun-51d3d4382281f789f8175079ed426a63529eb3e7.tar.zst bun-51d3d4382281f789f8175079ed426a63529eb3e7.zip |
Support named imports for json & toml files at runtime (#4783)
* Support named exports in json imports
* Support named imports for `*.json` files
* Remove stale comments
* Don't export arrays as non-default
* Add test for default exports
* Don't break webpack
---------
Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
Diffstat (limited to 'src/bun.js/bindings/ModuleLoader.cpp')
-rw-r--r-- | src/bun.js/bindings/ModuleLoader.cpp | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/src/bun.js/bindings/ModuleLoader.cpp b/src/bun.js/bindings/ModuleLoader.cpp index 4e2de9294..252c446b1 100644 --- a/src/bun.js/bindings/ModuleLoader.cpp +++ b/src/bun.js/bindings/ModuleLoader.cpp @@ -516,6 +516,29 @@ JSValue fetchCommonJSModule( RELEASE_AND_RETURN(scope, {}); } + // The JSONForObjectLoader tag is source code returned from Bun that needs + // to go through the JSON parser in JSC. + // + // We don't use JSON.parse directly in JS because we want the top-level keys of the JSON + // object to be accessible as named imports. + // + // We don't use Bun's JSON parser because JSON.parse is faster and + // handles stack overflow better. + // + // When parsing tsconfig.*.json or jsconfig.*.json, we go through Bun's JSON + // parser instead to support comments and trailing commas. + if (res->result.value.tag == SyntheticModuleType::JSONForObjectLoader) { + JSC::JSValue value = JSC::JSONParse(globalObject, Bun::toWTFString(res->result.value.source_code)); + if (!value) { + JSC::throwException(globalObject, scope, JSC::createSyntaxError(globalObject, "Failed to parse JSON"_s)); + RELEASE_AND_RETURN(scope, {}); + } + + target->putDirect(vm, WebCore::clientData(vm)->builtinNames().exportsPublicName(), value, value.isCell() && value.isCallable() ? JSC::PropertyAttribute::Function | 0 : 0); + target->hasEvaluated = true; + RELEASE_AND_RETURN(scope, target); + } + auto&& provider = Zig::SourceProvider::create(globalObject, res->result.value); globalObject->moduleLoader()->provideFetch(globalObject, specifierValue, JSC::SourceCode(provider)); RETURN_IF_EXCEPTION(scope, {}); @@ -647,6 +670,34 @@ static JSValue fetchESMSourceCode( return reject(exception); } + // The JSONForObjectLoader tag is source code returned from Bun that needs + // to go through the JSON parser in JSC. + // + // We don't use JSON.parse directly in JS because we want the top-level keys of the JSON + // object to be accessible as named imports. + // + // We don't use Bun's JSON parser because JSON.parse is faster and + // handles stack overflow better. + // + // When parsing tsconfig.*.json or jsconfig.*.json, we go through Bun's JSON + // parser instead to support comments and trailing commas. + if (res->result.value.tag == SyntheticModuleType::JSONForObjectLoader) { + JSC::JSValue value = JSC::JSONParse(globalObject, Bun::toWTFString(res->result.value.source_code)); + if (!value) { + return reject(JSC::JSValue(JSC::createSyntaxError(globalObject, "Failed to parse JSON"_s))); + } + + // JSON can become strings, null, numbers, booleans so we must handle "export default 123" + auto function = generateJSValueModuleSourceCode( + globalObject, + value); + auto source = JSC::SourceCode( + JSC::SyntheticSourceProvider::create(WTFMove(function), + JSC::SourceOrigin(), Bun::toWTFString(*specifier))); + JSC::ensureStillAliveHere(value); + return rejectOrResolve(JSSourceCode::create(globalObject->vm(), WTFMove(source))); + } + auto&& provider = Zig::SourceProvider::create(globalObject, res->result.value); return rejectOrResolve(JSC::JSSourceCode::create(vm, JSC::SourceCode(provider))); } |