Skip to content

Commit

Permalink
Support import with { type: "json" } and others (#16624)
Browse files Browse the repository at this point in the history
  • Loading branch information
pfgithub authored Mar 6, 2025
1 parent 7161326 commit d502df3
Show file tree
Hide file tree
Showing 19 changed files with 704 additions and 379 deletions.
6 changes: 6 additions & 0 deletions docs/bundler/loaders.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ The Bun bundler implements a set of default loaders out of the box. As a rule of

Bun uses the file extension to determine which built-in _loader_ should be used to parse the file. Every loader has a name, such as `js`, `tsx`, or `json`. These names are used when building [plugins](https://bun.sh/docs/bundler/plugins) that extend Bun with custom loaders.

You can explicitly specify which loader to use using the 'loader' import attribute.

```ts
import my_toml from "./my_file" with { loader: "toml" };
```

## Built-in loaders

### `js`
Expand Down
1 change: 1 addition & 0 deletions src/bake/DevServer.zig
Original file line number Diff line number Diff line change
Expand Up @@ -5096,6 +5096,7 @@ const DirectoryWatchStore = struct {
// loaders do not depend on importing other files.
.file,
.json,
.jsonc,
.toml,
.wasm,
.napi,
Expand Down
2 changes: 2 additions & 0 deletions src/bun.js/api/JSTranspiler.zig
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,8 @@ fn transformOptionsFromJSC(globalObject: JSC.C.JSContextRef, temp_allocator: std
&transpiler.log,
source,
allocator,
.json,
false,
) catch null) orelse break :macros;
transpiler.macro_map = PackageJSON.parseMacrosJSON(allocator, json, &transpiler.log, &source);
}
Expand Down
4 changes: 4 additions & 0 deletions src/bun.js/bindings/ZigGlobalObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4403,6 +4403,10 @@ JSC::JSInternalPromise* GlobalObject::moduleLoaderFetch(JSGlobalObject* globalOb

if (params.type() == ScriptFetchParameters::Type::HostDefined) {
typeAttributeString = params.hostDefinedImportType();
} else if (params.type() == ScriptFetchParameters::Type::JSON) {
typeAttributeString = "json"_s;
} else if (params.type() == ScriptFetchParameters::Type::WebAssembly) {
typeAttributeString = "webassembly"_s;
}
}
}
Expand Down
94 changes: 8 additions & 86 deletions src/bun.js/javascript.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2427,93 +2427,15 @@ pub const VirtualMachine = struct {

const specifier_clone = _specifier.toUTF8(bun.default_allocator);
defer specifier_clone.deinit();
const normalized_file_path_from_specifier, const specifier = ModuleLoader.normalizeSpecifier(jsc_vm, specifier_clone.slice());
const referrer_clone = referrer.toUTF8(bun.default_allocator);
defer referrer_clone.deinit();
var path = Fs.Path.init(normalized_file_path_from_specifier);

// For blobs.
var blob_source: ?JSC.WebCore.Blob = null;
var virtual_source_to_use: ?logger.Source = null;
defer {
if (blob_source) |*blob| {
blob.deinit();
}
}

const loader, const virtual_source = brk: {
if (jsc_vm.module_loader.eval_source) |eval_source| {
if (strings.endsWithComptime(specifier, bun.pathLiteral("/[eval]"))) {
break :brk .{ .tsx, eval_source };
}
if (strings.endsWithComptime(specifier, bun.pathLiteral("/[stdin]"))) {
break :brk .{ .tsx, eval_source };
}
}

var ext_for_loader = path.name.ext;

// Support errors within blob: URLs
// Be careful to handle Bun.file(), in addition to regular Blob/File objects
// Bun.file() should be treated the same as a file path.
if (JSC.WebCore.ObjectURLRegistry.isBlobURL(specifier)) {
if (JSC.WebCore.ObjectURLRegistry.singleton().resolveAndDupe(specifier["blob:".len..])) |blob| {
blob_source = blob;

if (blob.getFileName()) |filename| {
const current_path = Fs.Path.init(filename);
if (blob.needsToReadFile()) {
path = current_path;
}

ext_for_loader = current_path.name.ext;
} else if (blob.getMimeTypeOrContentType()) |mime_type| {
if (strings.hasPrefixComptime(mime_type.value, "application/javascript-jsx")) {
ext_for_loader = ".jsx";
} else if (strings.hasPrefixComptime(mime_type.value, "application/typescript-jsx")) {
ext_for_loader = ".tsx";
} else if (strings.hasPrefixComptime(mime_type.value, "application/javascript")) {
ext_for_loader = ".js";
} else if (strings.hasPrefixComptime(mime_type.value, "application/typescript")) {
ext_for_loader = ".ts";
} else if (strings.hasPrefixComptime(mime_type.value, "application/json")) {
ext_for_loader = ".json";
} else if (strings.hasPrefixComptime(mime_type.value, "application/json5")) {
ext_for_loader = ".jsonc";
} else if (strings.hasPrefixComptime(mime_type.value, "application/jsonc")) {
ext_for_loader = ".jsonc";
} else if (mime_type.category == .text) {
ext_for_loader = ".txt";
} else {
// Be maximally permissive.
ext_for_loader = ".tsx";
}
} else {
// Be maximally permissive.
ext_for_loader = ".tsx";
}

if (!blob.needsToReadFile()) {
virtual_source_to_use = logger.Source{
.path = path,
.contents = blob.sharedView(),
};
}
} else {
return error.ModuleNotFound;
}
}

break :brk .{
jsc_vm.transpiler.options.loaders.get(ext_for_loader) orelse brk2: {
if (strings.eqlLong(specifier, jsc_vm.main, true)) {
break :brk2 options.Loader.js;
}
break :brk2 options.Loader.file;
},
if (virtual_source_to_use) |*src| src else null,
};
var blob_to_deinit: ?JSC.WebCore.Blob = null;
const lr = options.getLoaderAndVirtualSource(specifier_clone.slice(), jsc_vm, &virtual_source_to_use, &blob_to_deinit, null) catch {
return error.ModuleNotFound;
};
defer if (blob_to_deinit) |*blob| blob.deinit();

// .print_source, which is used by exceptions avoids duplicating the entire source code
// but that means we have to be careful of the lifetime of the source code
Expand All @@ -2523,13 +2445,13 @@ pub const VirtualMachine = struct {

return try ModuleLoader.transpileSourceCode(
jsc_vm,
specifier,
lr.specifier,
referrer_clone.slice(),
_specifier,
path,
loader,
lr.path,
lr.loader orelse if (lr.is_main) .js else .file,
log,
virtual_source,
lr.virtual_source,
null,
VirtualMachine.source_code_printer.?,
globalObject,
Expand Down
Loading

0 comments on commit d502df3

Please sign in to comment.