[bun.js] Implement import.meta.require

This allows synchronous dynamic loading of `.node`, `.json`, and `.toml` files.

It is not a CommonJS require, but it can be used that way so long as the content is not JavaScript.
This commit is contained in:
Jarred Sumner
2022-05-11 00:56:35 -07:00
parent fd00950852
commit 3c87fbfd37
13 changed files with 538 additions and 157 deletions

View File

@@ -77,6 +77,8 @@ using namespace JSC;
macro(put) \
macro(read) \
macro(relative) \
macro(require) \
macro(resolveSync) \
macro(removeEventListener) \
macro(resolve) \
macro(resume) \

View File

@@ -0,0 +1,100 @@
/*
* Copyright (c) 2016 Apple Inc. All rights reserved.
* Copyright (c) 2022 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
*/
// DO NOT EDIT THIS FILE. It is automatically generated from JavaScript files for
// builtins by the script: Source/JavaScriptCore/Scripts/generate-js-builtins.py
#include "config.h"
#include "JSZigGlobalObjectBuiltins.h"
#include "WebCoreJSClientData.h"
#include <JavaScriptCore/HeapInlines.h>
#include <JavaScriptCore/IdentifierInlines.h>
#include <JavaScriptCore/Intrinsic.h>
#include <JavaScriptCore/JSCJSValueInlines.h>
#include <JavaScriptCore/JSCellInlines.h>
#include <JavaScriptCore/StructureInlines.h>
#include <JavaScriptCore/VM.h>
namespace WebCore {
const JSC::ConstructAbility s_jsZigGlobalObjectRequireCodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
const JSC::ConstructorKind s_jsZigGlobalObjectRequireCodeConstructorKind = JSC::ConstructorKind::None;
const int s_jsZigGlobalObjectRequireCodeLength = 1224;
static const JSC::Intrinsic s_jsZigGlobalObjectRequireCodeIntrinsic = JSC::NoIntrinsic;
const char* const s_jsZigGlobalObjectRequireCode =
"(function (name) {\n" \
" \"use strict\";\n" \
" if (typeof name !== \"string\") {\n" \
" @throwTypeError(\"require() expects a string as its argument\");\n" \
" }\n" \
"\n" \
" const resolved = this.resolveSync(name, this.path);\n" \
" var requireCache = (globalThis[Symbol.for(\"_requireCache\")] ||= new @Map);\n" \
" var cached = requireCache.@get(resolved);\n" \
" if (cached) {\n" \
" if (resolved.endsWith(\".node\")) {\n" \
" return cached.exports;\n" \
" }\n" \
"\n" \
" return cached;\n" \
" }\n" \
"\n" \
" //\n" \
" if (resolved.endsWith(\".json\")) {\n" \
" var fs = (globalThis[Symbol.for(\"_fs\")] ||= Bun.fs());\n" \
" var exports = JSON.parse(fs.readFileSync(resolved, \"utf8\"));\n" \
" requireCache.@set(resolved, exports);\n" \
" return cached;\n" \
" } else if (resolved.endsWith(\".node\")) {\n" \
" var module = { exports: {} };\n" \
" globalThis.process.dlopen(module, resolved);\n" \
" requireCache.@set(resolved, module);\n" \
" return module.exports;\n" \
" } else if (resolved.endsWith(\".toml\")) {\n" \
" var fs = (globalThis[Symbol.for(\"_fs\")] ||= Bun.fs());\n" \
" var exports = Bun.TOML.parse(fs.readFileSync(resolved, \"utf8\"));\n" \
" requireCache.@set(resolved, exports);\n" \
" return exports;\n" \
" }\n" \
"\n" \
" @throwTypeError(`Dynamic require isn't supported for file type: ${resolved.subsring(resolved.lastIndexOf(\".\") + 1) || resolved}`);\n" \
"})\n" \
;
#define DEFINE_BUILTIN_GENERATOR(codeName, functionName, overriddenName, argumentCount) \
JSC::FunctionExecutable* codeName##Generator(JSC::VM& vm) \
{\
JSVMClientData* clientData = static_cast<JSVMClientData*>(vm.clientData); \
return clientData->builtinFunctions().jsZigGlobalObjectBuiltins().codeName##Executable()->link(vm, nullptr, clientData->builtinFunctions().jsZigGlobalObjectBuiltins().codeName##Source(), std::nullopt, s_##codeName##Intrinsic); \
}
WEBCORE_FOREACH_JSZIGGLOBALOBJECT_BUILTIN_CODE(DEFINE_BUILTIN_GENERATOR)
#undef DEFINE_BUILTIN_GENERATOR
} // namespace WebCore

View File

@@ -0,0 +1,122 @@
/*
* Copyright (c) 2016 Apple Inc. All rights reserved.
* Copyright (c) 2022 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
*/
// DO NOT EDIT THIS FILE. It is automatically generated from JavaScript files for
// builtins by the script: Source/JavaScriptCore/Scripts/generate-js-builtins.py
#pragma once
#include <JavaScriptCore/BuiltinUtils.h>
#include <JavaScriptCore/Identifier.h>
#include <JavaScriptCore/JSFunction.h>
#include <JavaScriptCore/UnlinkedFunctionExecutable.h>
namespace JSC {
class FunctionExecutable;
}
namespace WebCore {
/* JSZigGlobalObject */
extern const char* const s_jsZigGlobalObjectRequireCode;
extern const int s_jsZigGlobalObjectRequireCodeLength;
extern const JSC::ConstructAbility s_jsZigGlobalObjectRequireCodeConstructAbility;
extern const JSC::ConstructorKind s_jsZigGlobalObjectRequireCodeConstructorKind;
#define WEBCORE_FOREACH_JSZIGGLOBALOBJECT_BUILTIN_DATA(macro) \
macro(require, jsZigGlobalObjectRequire, 1) \
#define WEBCORE_BUILTIN_JSZIGGLOBALOBJECT_REQUIRE 1
#define WEBCORE_FOREACH_JSZIGGLOBALOBJECT_BUILTIN_CODE(macro) \
macro(jsZigGlobalObjectRequireCode, require, ASCIILiteral(), s_jsZigGlobalObjectRequireCodeLength) \
#define WEBCORE_FOREACH_JSZIGGLOBALOBJECT_BUILTIN_FUNCTION_NAME(macro) \
macro(require) \
#define DECLARE_BUILTIN_GENERATOR(codeName, functionName, overriddenName, argumentCount) \
JSC::FunctionExecutable* codeName##Generator(JSC::VM&);
WEBCORE_FOREACH_JSZIGGLOBALOBJECT_BUILTIN_CODE(DECLARE_BUILTIN_GENERATOR)
#undef DECLARE_BUILTIN_GENERATOR
class JSZigGlobalObjectBuiltinsWrapper : private JSC::WeakHandleOwner {
public:
explicit JSZigGlobalObjectBuiltinsWrapper(JSC::VM& vm)
: m_vm(vm)
WEBCORE_FOREACH_JSZIGGLOBALOBJECT_BUILTIN_FUNCTION_NAME(INITIALIZE_BUILTIN_NAMES)
#define INITIALIZE_BUILTIN_SOURCE_MEMBERS(name, functionName, overriddenName, length) , m_##name##Source(JSC::makeSource(StringImpl::createWithoutCopying(s_##name, length), { }))
WEBCORE_FOREACH_JSZIGGLOBALOBJECT_BUILTIN_CODE(INITIALIZE_BUILTIN_SOURCE_MEMBERS)
#undef INITIALIZE_BUILTIN_SOURCE_MEMBERS
{
}
#define EXPOSE_BUILTIN_EXECUTABLES(name, functionName, overriddenName, length) \
JSC::UnlinkedFunctionExecutable* name##Executable(); \
const JSC::SourceCode& name##Source() const { return m_##name##Source; }
WEBCORE_FOREACH_JSZIGGLOBALOBJECT_BUILTIN_CODE(EXPOSE_BUILTIN_EXECUTABLES)
#undef EXPOSE_BUILTIN_EXECUTABLES
WEBCORE_FOREACH_JSZIGGLOBALOBJECT_BUILTIN_FUNCTION_NAME(DECLARE_BUILTIN_IDENTIFIER_ACCESSOR)
void exportNames();
private:
JSC::VM& m_vm;
WEBCORE_FOREACH_JSZIGGLOBALOBJECT_BUILTIN_FUNCTION_NAME(DECLARE_BUILTIN_NAMES)
#define DECLARE_BUILTIN_SOURCE_MEMBERS(name, functionName, overriddenName, length) \
JSC::SourceCode m_##name##Source;\
JSC::Weak<JSC::UnlinkedFunctionExecutable> m_##name##Executable;
WEBCORE_FOREACH_JSZIGGLOBALOBJECT_BUILTIN_CODE(DECLARE_BUILTIN_SOURCE_MEMBERS)
#undef DECLARE_BUILTIN_SOURCE_MEMBERS
};
#define DEFINE_BUILTIN_EXECUTABLES(name, functionName, overriddenName, length) \
inline JSC::UnlinkedFunctionExecutable* JSZigGlobalObjectBuiltinsWrapper::name##Executable() \
{\
if (!m_##name##Executable) {\
JSC::Identifier executableName = functionName##PublicName();\
if (overriddenName)\
executableName = JSC::Identifier::fromString(m_vm, overriddenName);\
m_##name##Executable = JSC::Weak<JSC::UnlinkedFunctionExecutable>(JSC::createBuiltinExecutable(m_vm, m_##name##Source, executableName, s_##name##ConstructorKind, s_##name##ConstructAbility), this, &m_##name##Executable);\
}\
return m_##name##Executable.get();\
}
WEBCORE_FOREACH_JSZIGGLOBALOBJECT_BUILTIN_CODE(DEFINE_BUILTIN_EXECUTABLES)
#undef DEFINE_BUILTIN_EXECUTABLES
inline void JSZigGlobalObjectBuiltinsWrapper::exportNames()
{
#define EXPORT_FUNCTION_NAME(name) m_vm.propertyNames->appendExternalName(name##PublicName(), name##PrivateName());
WEBCORE_FOREACH_JSZIGGLOBALOBJECT_BUILTIN_FUNCTION_NAME(EXPORT_FUNCTION_NAME)
#undef EXPORT_FUNCTION_NAME
}
} // namespace WebCore

View File

@@ -32,6 +32,7 @@
#include "JSBufferConstructorBuiltins.h"
#include "JSBufferPrototypeBuiltins.h"
#include "JSZigGlobalObjectBuiltins.h"
#include <JavaScriptCore/VM.h>
namespace WebCore {
@@ -42,16 +43,19 @@ public:
: m_vm(vm)
, m_jsBufferConstructorBuiltins(m_vm)
, m_jsBufferPrototypeBuiltins(m_vm)
, m_jsZigGlobalObjectBuiltins(m_vm)
{
}
JSBufferConstructorBuiltinsWrapper& jsBufferConstructorBuiltins() { return m_jsBufferConstructorBuiltins; }
JSBufferPrototypeBuiltinsWrapper& jsBufferPrototypeBuiltins() { return m_jsBufferPrototypeBuiltins; }
JSZigGlobalObjectBuiltinsWrapper& jsZigGlobalObjectBuiltins() { return m_jsZigGlobalObjectBuiltins; }
private:
JSC::VM& m_vm;
JSBufferConstructorBuiltinsWrapper m_jsBufferConstructorBuiltins;
JSBufferPrototypeBuiltinsWrapper m_jsBufferPrototypeBuiltins;
JSZigGlobalObjectBuiltinsWrapper m_jsZigGlobalObjectBuiltins;
};
} // namespace WebCore

View File

@@ -1173,7 +1173,7 @@ JSC::JSObject* GlobalObject::moduleLoaderCreateImportMetaProperties(JSGlobalObje
auto index = view.reverseFind('/', view.length());
if (index != WTF::notFound) {
metaProperties->putDirect(vm, clientData->builtinNames().dirPublicName(),
JSC::jsSubstring(globalObject, keyString, 0, index));
JSC::jsSubstring(globalObject, keyString, 0, index + 1));
metaProperties->putDirect(
vm, clientData->builtinNames().filePublicName(),
JSC::jsSubstring(globalObject, keyString, index + 1, keyString->length() - index - 1));
@@ -1191,6 +1191,9 @@ JSC::JSObject* GlobalObject::moduleLoaderCreateImportMetaProperties(JSGlobalObje
WTF::String("resolveSync"_s), functionImportMeta__resolveSync),
JSC::PropertyAttribute::Function | 0);
metaProperties->putDirectBuiltinFunction(vm, globalObject, clientData->builtinNames().requirePublicName(),
jsZigGlobalObjectRequireCodeGenerator(vm),
JSC::PropertyAttribute::Builtin | 0);
}
metaProperties->putDirect(vm, clientData->builtinNames().pathPublicName(), key);

View File

@@ -0,0 +1,62 @@
/*
* Copyright 2022 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
function require(name) {
"use strict";
if (typeof name !== "string") {
@throwTypeError("require() expects a string as its argument");
}
const resolved = this.resolveSync(name, this.path);
var requireCache = (globalThis[Symbol.for("_requireCache")] ||= new @Map);
var cached = requireCache.@get(resolved);
if (cached) {
if (resolved.endsWith(".node")) {
return cached.exports;
}
return cached;
}
// TODO: remove this hardcoding
if (resolved.endsWith(".json")) {
var fs = (globalThis[Symbol.for("_fs")] ||= Bun.fs());
var exports = JSON.parse(fs.readFileSync(resolved, "utf8"));
requireCache.@set(resolved, exports);
return cached;
} else if (resolved.endsWith(".node")) {
var module = { exports: {} };
globalThis.process.dlopen(module, resolved);
requireCache.@set(resolved, module);
return module.exports;
} else if (resolved.endsWith(".toml")) {
var fs = (globalThis[Symbol.for("_fs")] ||= Bun.fs());
var exports = Bun.TOML.parse(fs.readFileSync(resolved, "utf8"));
requireCache.@set(resolved, exports);
return exports;
}
@throwTypeError(`Dynamic require isn't supported for file type: ${resolved.subsring(resolved.lastIndexOf(".") + 1) || resolved}`);
}

View File

@@ -1048,83 +1048,132 @@ pub const VirtualMachine = struct {
.source_url = ZigString.init(Runtime.Runtime.Imports.Name),
.hash = Runtime.Runtime.versionHash(),
};
// This is all complicated because the imports have to be linked and we want to run the printer on it
// so it consistently handles bundled imports
// we can't take the shortcut of just directly importing the file, sadly.
} else if (strings.eqlComptime(_specifier, main_file_name)) {
if (comptime disable_transpilying) {
return ResolvedSource{
.allocator = null,
.source_code = ZigString.init(jsc_vm.entry_point.source.contents),
.specifier = ZigString.init(std.mem.span(main_file_name)),
.source_url = ZigString.init(std.mem.span(main_file_name)),
.hash = 0,
};
}
defer jsc_vm.transpiled_count += 1;
} else if (HardcodedModule.Map.get(_specifier)) |hardcoded| {
switch (hardcoded) {
// This is all complicated because the imports have to be linked and we want to run the printer on it
// so it consistently handles bundled imports
// we can't take the shortcut of just directly importing the file, sadly.
.@"bun:main" => {
if (comptime disable_transpilying) {
return ResolvedSource{
.allocator = null,
.source_code = ZigString.init(jsc_vm.entry_point.source.contents),
.specifier = ZigString.init(std.mem.span(main_file_name)),
.source_url = ZigString.init(std.mem.span(main_file_name)),
.hash = 0,
};
}
defer jsc_vm.transpiled_count += 1;
var bundler = &jsc_vm.bundler;
var old = jsc_vm.bundler.log;
jsc_vm.bundler.log = log;
jsc_vm.bundler.linker.log = log;
jsc_vm.bundler.resolver.log = log;
defer {
jsc_vm.bundler.log = old;
jsc_vm.bundler.linker.log = old;
jsc_vm.bundler.resolver.log = old;
}
var bundler = &jsc_vm.bundler;
var old = jsc_vm.bundler.log;
jsc_vm.bundler.log = log;
jsc_vm.bundler.linker.log = log;
jsc_vm.bundler.resolver.log = log;
defer {
jsc_vm.bundler.log = old;
jsc_vm.bundler.linker.log = old;
jsc_vm.bundler.resolver.log = old;
}
var jsx = bundler.options.jsx;
jsx.parse = false;
var opts = js_parser.Parser.Options.init(jsx, .js);
opts.enable_bundling = false;
opts.transform_require_to_import = true;
opts.can_import_from_bundle = bundler.options.node_modules_bundle != null;
opts.features.hot_module_reloading = false;
opts.features.react_fast_refresh = false;
opts.filepath_hash_for_hmr = 0;
opts.warn_about_unbundled_modules = false;
opts.macro_context = &jsc_vm.bundler.macro_context.?;
const main_ast = (bundler.resolver.caches.js.parse(jsc_vm.allocator, opts, bundler.options.define, bundler.log, &jsc_vm.entry_point.source) catch null) orelse {
return error.ParseError;
};
var parse_result = ParseResult{ .source = jsc_vm.entry_point.source, .ast = main_ast, .loader = .js, .input_fd = null };
var file_path = Fs.Path.init(bundler.fs.top_level_dir);
file_path.name.dir = bundler.fs.top_level_dir;
file_path.name.base = "bun:main";
try bundler.linker.link(
file_path,
&parse_result,
jsc_vm.origin,
.absolute_path,
false,
true,
);
var printer = source_code_printer.?.*;
var written: usize = undefined;
printer.ctx.reset();
{
defer source_code_printer.?.* = printer;
written = try jsc_vm.bundler.printWithSourceMap(
parse_result,
@TypeOf(&printer),
&printer,
.esm_ascii,
SavedSourceMap.SourceMapHandler.init(&jsc_vm.source_mappings),
);
}
var jsx = bundler.options.jsx;
jsx.parse = false;
var opts = js_parser.Parser.Options.init(jsx, .js);
opts.enable_bundling = false;
opts.transform_require_to_import = true;
opts.can_import_from_bundle = bundler.options.node_modules_bundle != null;
opts.features.hot_module_reloading = false;
opts.features.react_fast_refresh = false;
opts.filepath_hash_for_hmr = 0;
opts.warn_about_unbundled_modules = false;
opts.macro_context = &jsc_vm.bundler.macro_context.?;
const main_ast = (bundler.resolver.caches.js.parse(jsc_vm.allocator, opts, bundler.options.define, bundler.log, &jsc_vm.entry_point.source) catch null) orelse {
return error.ParseError;
};
var parse_result = ParseResult{ .source = jsc_vm.entry_point.source, .ast = main_ast, .loader = .js, .input_fd = null };
var file_path = Fs.Path.init(bundler.fs.top_level_dir);
file_path.name.dir = bundler.fs.top_level_dir;
file_path.name.base = "bun:main";
try bundler.linker.link(
file_path,
&parse_result,
jsc_vm.origin,
.absolute_path,
false,
true,
);
var printer = source_code_printer.?.*;
var written: usize = undefined;
printer.ctx.reset();
{
defer source_code_printer.?.* = printer;
written = try jsc_vm.bundler.printWithSourceMap(
parse_result,
@TypeOf(&printer),
&printer,
.esm_ascii,
SavedSourceMap.SourceMapHandler.init(&jsc_vm.source_mappings),
);
}
if (written == 0) {
return error.PrintingErrorWriteFailed;
}
if (written == 0) {
return error.PrintingErrorWriteFailed;
}
return ResolvedSource{
.allocator = null,
.source_code = ZigString.init(jsc_vm.allocator.dupe(u8, printer.ctx.written) catch unreachable),
.specifier = ZigString.init(std.mem.span(main_file_name)),
.source_url = ZigString.init(std.mem.span(main_file_name)),
.hash = 0,
};
return ResolvedSource{
.allocator = null,
.source_code = ZigString.init(jsc_vm.allocator.dupe(u8, printer.ctx.written) catch unreachable),
.specifier = ZigString.init(std.mem.span(main_file_name)),
.source_url = ZigString.init(std.mem.span(main_file_name)),
.hash = 0,
};
},
.@"node:fs" => {
return ResolvedSource{
.allocator = null,
.source_code = ZigString.init(@embedFile("fs.exports.js") ++ JSC.Node.fs.constants_string),
.specifier = ZigString.init("node:fs"),
.source_url = ZigString.init("node:fs"),
.hash = 0,
};
},
.@"node:path" => {
return ResolvedSource{
.allocator = null,
.source_code = ZigString.init(Node.Path.code),
.specifier = ZigString.init("node:path"),
.source_url = ZigString.init("node:path"),
.hash = 0,
};
},
.@"bun:ffi" => {
return ResolvedSource{
.allocator = null,
.source_code = ZigString.init(
"export const FFIType = " ++
JSC.FFI.ABIType.map_to_js_object ++
";\n\n" ++
"export const suffix = '" ++ shared_library_suffix ++ "';\n\n" ++
@embedFile("ffi.exports.js") ++
"\n",
),
.specifier = ZigString.init("bun:ffi"),
.source_url = ZigString.init("bun:ffi"),
.hash = 0,
};
},
.@"detect-libc" => {
return ResolvedSource{
.allocator = null,
.source_code = ZigString.init(
@as(string, @embedFile(if (Environment.isLinux) "detect-libc.linux.js" else "detect-libc.js")),
),
.specifier = ZigString.init("detect-libc"),
.source_url = ZigString.init("detect-libc"),
.hash = 0,
};
},
}
} else if (_specifier.len > js_ast.Macro.namespaceWithColon.len and
strings.eqlComptimeIgnoreLen(_specifier[0..js_ast.Macro.namespaceWithColon.len], js_ast.Macro.namespaceWithColon))
{
@@ -1139,37 +1188,6 @@ pub const VirtualMachine = struct {
};
}
}
} else if (strings.eqlComptime(_specifier, "node:fs")) {
return ResolvedSource{
.allocator = null,
.source_code = ZigString.init(@embedFile("fs.exports.js") ++ JSC.Node.fs.constants_string),
.specifier = ZigString.init("node:fs"),
.source_url = ZigString.init("node:fs"),
.hash = 0,
};
} else if (strings.eqlComptime(_specifier, "node:path")) {
return ResolvedSource{
.allocator = null,
.source_code = ZigString.init(Node.Path.code),
.specifier = ZigString.init("node:path"),
.source_url = ZigString.init("node:path"),
.hash = 0,
};
} else if (strings.eqlComptime(_specifier, "bun:ffi")) {
return ResolvedSource{
.allocator = null,
.source_code = ZigString.init(
"export const FFIType = " ++
JSC.FFI.ABIType.map_to_js_object ++
";\n\n" ++
"export const suffix = '" ++ shared_library_suffix ++ "';\n\n" ++
@embedFile("ffi.exports.js") ++
"\n",
),
.specifier = ZigString.init("bun:ffi"),
.source_url = ZigString.init("bun:ffi"),
.hash = 0,
};
}
const specifier = normalizeSpecifier(_specifier);
@@ -1393,17 +1411,9 @@ pub const VirtualMachine = struct {
ret.result = null;
ret.path = specifier;
return;
} else if (strings.eqlComptime(specifier, "node:fs")) {
} else if (HardcodedModule.Map.get(specifier)) |result| {
ret.result = null;
ret.path = "node:fs";
return;
} else if (strings.eqlComptime(specifier, "node:path")) {
ret.result = null;
ret.path = "node:path";
return;
} else if (strings.eqlComptime(specifier, "bun:ffi")) {
ret.result = null;
ret.path = "bun:ffi";
ret.path = std.mem.span(@tagName(result));
return;
}
@@ -2874,3 +2884,41 @@ pub const BuildError = struct {
};
pub const JSPrivateDataTag = JSPrivateDataPtr.Tag;
pub const HardcodedModule = enum {
@"bun:ffi",
@"bun:main",
@"node:fs",
@"node:path",
@"detect-libc",
pub const Map = bun.ComptimeStringMap(
HardcodedModule,
.{
.{ "bun:ffi", HardcodedModule.@"bun:ffi" },
.{ "ffi", HardcodedModule.@"bun:ffi" },
.{ "bun:main", HardcodedModule.@"bun:main" },
.{ "node:fs", HardcodedModule.@"node:fs" },
.{ "fs", HardcodedModule.@"node:fs" },
.{ "node:path", HardcodedModule.@"node:path" },
.{ "path", HardcodedModule.@"node:path" },
.{ "node:path/win32", HardcodedModule.@"node:path" },
.{ "node:path/posix", HardcodedModule.@"node:path" },
.{ "detect-libc", HardcodedModule.@"detect-libc" },
},
);
pub const LinkerMap = bun.ComptimeStringMap(
string,
.{
.{ "bun:ffi", "bun:ffi" },
.{ "detect-libc", "detect-libc" },
.{ "detect-libc/lib/detect-libc.js", "detect-libc" },
.{ "ffi", "bun:ffi" },
.{ "fs", "node:fs" },
.{ "node:fs", "node:fs" },
.{ "node:path", "node:path" },
.{ "path", "node:path" },
.{ "bun:wrap", "bun:wrap" },
},
);
};