mirror of
https://github.com/oven-sh/bun
synced 2026-02-15 05:12:29 +00:00
[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:
@@ -2,6 +2,10 @@ import { it, expect } from "bun:test";
|
||||
|
||||
const { path, dir } = import.meta;
|
||||
|
||||
it("import.meta.resolveSync", () => {
|
||||
expect(import.meta.resolveSync(import.meta.file, import.meta.dir)).toBe(path);
|
||||
});
|
||||
|
||||
it("import.meta.dir", () => {
|
||||
expect(dir.endsWith("/bun/integration/bunjs-only-snippets")).toBe(true);
|
||||
});
|
||||
|
||||
@@ -77,6 +77,8 @@ using namespace JSC;
|
||||
macro(put) \
|
||||
macro(read) \
|
||||
macro(relative) \
|
||||
macro(require) \
|
||||
macro(resolveSync) \
|
||||
macro(removeEventListener) \
|
||||
macro(resolve) \
|
||||
macro(resume) \
|
||||
|
||||
0
src/javascript/jsc/bindings/GlobalBuiltins.js
Normal file
0
src/javascript/jsc/bindings/GlobalBuiltins.js
Normal file
100
src/javascript/jsc/bindings/JSZigGlobalObjectBuiltins.cpp
Normal file
100
src/javascript/jsc/bindings/JSZigGlobalObjectBuiltins.cpp
Normal 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
|
||||
122
src/javascript/jsc/bindings/JSZigGlobalObjectBuiltins.h
Normal file
122
src/javascript/jsc/bindings/JSZigGlobalObjectBuiltins.h
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
62
src/javascript/jsc/bindings/builtins/js/JSZigGlobalObject.js
Normal file
62
src/javascript/jsc/bindings/builtins/js/JSZigGlobalObject.js
Normal 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}`);
|
||||
}
|
||||
@@ -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" },
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
@@ -2404,7 +2404,54 @@ pub const Parser = struct {
|
||||
}
|
||||
|
||||
const uses_dirname = p.symbols.items[p.dirname_ref.innerIndex()].use_count_estimate > 0;
|
||||
const uses_dynamic_require = p.options.features.dynamic_require and p.symbols.items[p.require_ref.innerIndex()].use_count_estimate > 0;
|
||||
const uses_filename = p.symbols.items[p.filename_ref.innerIndex()].use_count_estimate > 0;
|
||||
|
||||
if (uses_dynamic_require) {
|
||||
var declared_symbols = try p.allocator.alloc(js_ast.DeclaredSymbol, 1);
|
||||
var decls = p.allocator.alloc(G.Decl, 1) catch unreachable;
|
||||
var part_stmts = p.allocator.alloc(Stmt, 1) catch unreachable;
|
||||
var exprs = p.allocator.alloc(Expr, 1) catch unreachable;
|
||||
exprs[0] = p.e(E.ImportMeta{}, logger.Loc.Empty);
|
||||
// var require = import.meta.require.bind(import.meta)
|
||||
decls[0] = .{
|
||||
.binding = p.b(B.Identifier{ .ref = p.require_ref }, logger.Loc.Empty),
|
||||
.value = p.e(
|
||||
E.Call{
|
||||
.target = p.e(
|
||||
E.Dot{
|
||||
.target = p.e(
|
||||
E.Dot{
|
||||
.target = p.e(E.ImportMeta{}, logger.Loc.Empty),
|
||||
.name = "require",
|
||||
.name_loc = logger.Loc.Empty,
|
||||
},
|
||||
logger.Loc.Empty,
|
||||
),
|
||||
.name = "bind",
|
||||
.name_loc = logger.Loc.Empty,
|
||||
},
|
||||
logger.Loc.Empty,
|
||||
),
|
||||
.args = ExprNodeList.init(exprs),
|
||||
},
|
||||
logger.Loc.Empty,
|
||||
),
|
||||
};
|
||||
|
||||
declared_symbols[0] = .{ .ref = p.require_ref, .is_top_level = true };
|
||||
|
||||
part_stmts[0] = p.s(S.Local{
|
||||
.kind = .k_var,
|
||||
.decls = decls,
|
||||
}, logger.Loc.Empty);
|
||||
before.append(js_ast.Part{
|
||||
.stmts = part_stmts,
|
||||
.declared_symbols = declared_symbols,
|
||||
.tag = .dirname_filename,
|
||||
}) catch unreachable;
|
||||
}
|
||||
|
||||
if (uses_dirname or uses_filename) {
|
||||
const count = @as(usize, @boolToInt(uses_dirname)) + @as(usize, @boolToInt(uses_filename));
|
||||
var declared_symbols = try p.allocator.alloc(js_ast.DeclaredSymbol, count);
|
||||
@@ -2419,7 +2466,6 @@ pub const Parser = struct {
|
||||
),
|
||||
};
|
||||
declared_symbols[0] = .{ .ref = p.dirname_ref, .is_top_level = true };
|
||||
p.recordUsage(p.dirname_ref);
|
||||
}
|
||||
if (uses_filename) {
|
||||
decls[@as(usize, @boolToInt(uses_dirname))] = .{
|
||||
@@ -2430,7 +2476,6 @@ pub const Parser = struct {
|
||||
),
|
||||
};
|
||||
declared_symbols[@as(usize, @boolToInt(uses_dirname))] = .{ .ref = p.filename_ref, .is_top_level = true };
|
||||
p.recordUsage(p.filename_ref);
|
||||
}
|
||||
|
||||
// TODO: DeclaredSymbol
|
||||
@@ -2444,7 +2489,6 @@ pub const Parser = struct {
|
||||
.declared_symbols = declared_symbols,
|
||||
.tag = .dirname_filename,
|
||||
}) catch unreachable;
|
||||
|
||||
}
|
||||
|
||||
var did_import_fast_refresh = false;
|
||||
@@ -3570,6 +3614,15 @@ fn NewParser_(
|
||||
|
||||
const pathname = str.string(p.allocator) catch unreachable;
|
||||
|
||||
if (p.options.features.dynamic_require and
|
||||
!p.options.enable_bundling and
|
||||
(strings.endsWithComptime(pathname, ".json") or
|
||||
strings.endsWithComptime(pathname, ".toml") or
|
||||
strings.endsWithComptime(pathname, ".node")))
|
||||
{
|
||||
return arg;
|
||||
}
|
||||
|
||||
const import_record_index = p.addImportRecord(.require, arg.loc, pathname);
|
||||
p.import_records.items[import_record_index].handles_import_errors = p.fn_or_arrow_data_visit.try_body_count != 0;
|
||||
p.import_records_for_current_part.append(p.allocator, import_record_index) catch unreachable;
|
||||
@@ -13336,13 +13389,17 @@ fn NewParser_(
|
||||
// error from the unbundled require() call failing.
|
||||
if (e_.args.len == 1) {
|
||||
const first = e_.args.first_();
|
||||
if (first.data == .e_string) {
|
||||
// require(FOO) => require(FOO)
|
||||
return p.transposeRequire(first, null);
|
||||
} else if (first.data == .e_if) {
|
||||
// require(FOO ? '123' : '456') => FOO ? require('123') : require('456')
|
||||
// This makes static analysis later easier
|
||||
return p.require_transposer.maybeTransposeIf(first, null);
|
||||
switch (first.data) {
|
||||
.e_string => {
|
||||
// require(FOO) => require(FOO)
|
||||
return p.transposeRequire(first, null);
|
||||
},
|
||||
.e_if => {
|
||||
// require(FOO ? '123' : '456') => FOO ? require('123') : require('456')
|
||||
// This makes static analysis later easier
|
||||
return p.require_transposer.maybeTransposeIf(first, null);
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3588,15 +3588,11 @@ pub fn NewPrinter(
|
||||
const quotes = p.bestQuoteCharForString(import_record.path.text, true);
|
||||
p.print("var ");
|
||||
p.printSymbol(s.namespace_ref);
|
||||
p.print(" = ");
|
||||
|
||||
p.print(
|
||||
\\((path, cache, process) => {var mod = cache.get(path); if (mod) return mod.exports; mod = {exports: {}};process.dlopen(mod, path); cache.set(path, mod); return mod.exports;})(
|
||||
);
|
||||
p.print(" = import.meta.require(");
|
||||
p.print(quotes);
|
||||
p.printUTF8StringEscapedQuotes(import_record.path.text, quotes);
|
||||
p.print(quotes);
|
||||
p.print(", (globalThis[globalThis.Symbol.for('_dlcache')] ||= new globalThis.Map()), globalThis.process);");
|
||||
p.print(")");
|
||||
p.printSemicolonAfterStatement();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ const ResolveQueue = _bundler.ResolveQueue;
|
||||
const ResolverType = Resolver.Resolver;
|
||||
const Runtime = @import("./runtime.zig").Runtime;
|
||||
const URL = @import("url.zig").URL;
|
||||
const JSC = @import("javascript_core");
|
||||
pub const CSSResolveError = error{ResolveError};
|
||||
|
||||
pub const OnImportCallback = fn (resolve_result: *const Resolver.Result, import_record: *ImportRecord, origin: URL) void;
|
||||
@@ -261,26 +262,8 @@ pub const Linker = struct {
|
||||
}
|
||||
|
||||
if (comptime is_bun) {
|
||||
if (import_record.path.text.len > 5 and strings.eqlComptime(import_record.path.text[0.."node:".len], "node:")) {
|
||||
const is_fs = strings.eqlComptime(import_record.path.text[5..], "fs");
|
||||
|
||||
if (is_fs) {
|
||||
import_record.path.text = "node:fs";
|
||||
externals.append(record_index) catch unreachable;
|
||||
continue;
|
||||
}
|
||||
|
||||
const is_path = strings.eqlComptime(import_record.path.text[5..], "path");
|
||||
|
||||
if (is_path) {
|
||||
import_record.path.text = "node:path";
|
||||
externals.append(record_index) catch unreachable;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (strings.eqlComptime(import_record.path.text, "fs")) {
|
||||
import_record.path.text = "node:fs";
|
||||
if (JSC.HardcodedModule.LinkerMap.get(import_record.path.text)) |replacement| {
|
||||
import_record.path.text = replacement;
|
||||
externals.append(record_index) catch unreachable;
|
||||
continue;
|
||||
}
|
||||
@@ -290,12 +273,6 @@ pub const Linker = struct {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strings.eqlComptime(import_record.path.text, "path")) {
|
||||
import_record.path.text = "node:path";
|
||||
externals.append(record_index) catch unreachable;
|
||||
continue;
|
||||
}
|
||||
|
||||
// if (strings.eqlComptime(import_record.path.text, "process")) {
|
||||
// import_record.path.text = "node:process";
|
||||
// externals.append(record_index) catch unreachable;
|
||||
|
||||
@@ -277,6 +277,12 @@ pub const Runtime = struct {
|
||||
trim_unused_imports: bool = false,
|
||||
should_fold_numeric_constants: bool = false,
|
||||
|
||||
/// inject this at the top of the file?
|
||||
/// ```js
|
||||
/// var require = import.meta.require.bind(import.meta);
|
||||
/// ```
|
||||
dynamic_require: bool = false,
|
||||
|
||||
replace_exports: ReplaceableExport.Map = .{},
|
||||
|
||||
pub const ReplaceableExport = union(enum) {
|
||||
|
||||
Reference in New Issue
Block a user