aboutsummaryrefslogtreecommitdiff
path: root/src/bun.js/modules/NodeModuleModule.h
diff options
context:
space:
mode:
authorGravatar dave caruso <me@paperdave.net> 2023-08-02 16:27:36 -0700
committerGravatar GitHub <noreply@github.com> 2023-08-02 16:27:36 -0700
commitc2a77cf7ec9de9eadf938046bdf78e58561c8a6d (patch)
tree0f90f1b323061455875333c9f40592b303585973 /src/bun.js/modules/NodeModuleModule.h
parent7656b4b17e91f15b58eeab8f45b78c416ec6a045 (diff)
downloadbun-c2a77cf7ec9de9eadf938046bdf78e58561c8a6d.tar.gz
bun-c2a77cf7ec9de9eadf938046bdf78e58561c8a6d.tar.zst
bun-c2a77cf7ec9de9eadf938046bdf78e58561c8a6d.zip
Rewrite built-in modules to use CommonJS over ESM (#3814)
* stfdsafsd sadffdsa stuff finish commonjs stuff asdf not done but work not done but work not done yet but this is how far i am remove files lol update built files uncomment everything in events lol export default stuff * afdsafsd * its not perfect but almost done * okay * cool * remove temp file * finish rebase * revert settings.json * a * ch-ch-ch-ch-changes * okay * remove this check in release for now * sxdcfghnjm, * lkjhgf * fmt * filename can be null * Update NodeModuleModule.h * weee * fmt --------- Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
Diffstat (limited to 'src/bun.js/modules/NodeModuleModule.h')
-rw-r--r--src/bun.js/modules/NodeModuleModule.h324
1 files changed, 316 insertions, 8 deletions
diff --git a/src/bun.js/modules/NodeModuleModule.h b/src/bun.js/modules/NodeModuleModule.h
index 0aefdef12..e51f2ac86 100644
--- a/src/bun.js/modules/NodeModuleModule.h
+++ b/src/bun.js/modules/NodeModuleModule.h
@@ -1,12 +1,320 @@
-#include "../bindings/ZigGlobalObject.h"
-#include "JavaScriptCore/JSGlobalObject.h"
+#include "CommonJSModuleRecord.h"
+#include "ImportMetaObject.h"
+#include "JavaScriptCore/JSBoundFunction.h"
+#include "JavaScriptCore/ObjectConstructor.h"
+#include "_NativeModule.h"
+
+using namespace Zig;
+using namespace JSC;
+
+// This is a mix of bun's builtin module names and also the ones reported by
+// node v20.4.0
+static constexpr ASCIILiteral builtinModuleNames[] = {
+ "_http_agent"_s,
+ "_http_client"_s,
+ "_http_common"_s,
+ "_http_incoming"_s,
+ "_http_outgoing"_s,
+ "_http_server"_s,
+ "_stream_duplex"_s,
+ "_stream_passthrough"_s,
+ "_stream_readable"_s,
+ "_stream_transform"_s,
+ "_stream_wrap"_s,
+ "_stream_writable"_s,
+ "_tls_common"_s,
+ "_tls_wrap"_s,
+ "assert"_s,
+ "assert/strict"_s,
+ "async_hooks"_s,
+ "buffer"_s,
+ "bun"_s,
+ "bun:ffi"_s,
+ "bun:jsc"_s,
+ "bun:sqlite"_s,
+ "bun:wrap"_s,
+ "child_process"_s,
+ "cluster"_s,
+ "console"_s,
+ "constants"_s,
+ "crypto"_s,
+ "detect-libc"_s,
+ "dgram"_s,
+ "diagnostics_channel"_s,
+ "dns"_s,
+ "dns/promises"_s,
+ "domain"_s,
+ "events"_s,
+ "fs"_s,
+ "fs/promises"_s,
+ "http"_s,
+ "http2"_s,
+ "https"_s,
+ "inspector"_s,
+ "inspector/promises"_s,
+ "module"_s,
+ "net"_s,
+ "os"_s,
+ "path"_s,
+ "path/posix"_s,
+ "path/win32"_s,
+ "perf_hooks"_s,
+ "process"_s,
+ "punycode"_s,
+ "querystring"_s,
+ "readline"_s,
+ "readline/promises"_s,
+ "repl"_s,
+ "stream"_s,
+ "stream/consumers"_s,
+ "stream/promises"_s,
+ "stream/web"_s,
+ "string_decoder"_s,
+ "sys"_s,
+ "timers"_s,
+ "timers/promises"_s,
+ "tls"_s,
+ "trace_events"_s,
+ "tty"_s,
+ "undici"_s,
+ "url"_s,
+ "util"_s,
+ "util/types"_s,
+ "v8"_s,
+ "vm"_s,
+ "wasi"_s,
+ "worker_threads"_s,
+ "ws"_s,
+ "zlib"_s,
+};
+
+static bool isBuiltinModule(const String &namePossiblyWithNodePrefix) {
+ String name = namePossiblyWithNodePrefix;
+ if (name.startsWith("node:"_s))
+ name = name.substringSharingImpl(5);
+
+ for (auto &builtinModule : builtinModuleNames) {
+ if (name == builtinModule)
+ return true;
+ }
+ return false;
+}
+
+JSC_DEFINE_HOST_FUNCTION(jsFunctionNodeModuleModuleConstructor,
+ (JSC::JSGlobalObject * globalObject,
+ JSC::CallFrame *callFrame)) {
+ // In node, this is supposed to be the actual CommonJSModule constructor.
+ // We are cutting a huge corner by not doing all that work.
+ // This code is only to support babel.
+ JSC::VM &vm = globalObject->vm();
+ JSString *idString = JSC::jsString(vm, WTF::String("."_s));
+
+ JSString *dirname = jsEmptyString(vm);
+
+ // TODO: handle when JSGlobalObject !== Zig::GlobalObject, such as in node:vm
+ Structure *structure = static_cast<Zig::GlobalObject *>(globalObject)
+ ->CommonJSModuleObjectStructure();
+
+ // TODO: handle ShadowRealm, node:vm, new.target, subclasses
+ JSValue idValue = callFrame->argument(0);
+ JSValue parentValue = callFrame->argument(1);
+
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ if (idValue.isString()) {
+ idString = idValue.toString(globalObject);
+ RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(JSC::jsUndefined()));
+
+ auto index = idString->tryGetValue().reverseFind('/', idString->length());
+
+ if (index != WTF::notFound) {
+ dirname = JSC::jsSubstring(globalObject, idString, 0, index);
+ }
+ }
+
+ auto *out = Bun::JSCommonJSModule::create(vm, structure, idString, jsNull(),
+ dirname, nullptr);
+
+ if (!parentValue.isUndefined())
+ out->putDirect(vm, JSC::Identifier::fromString(vm, "parent"_s), parentValue,
+ 0);
+
+ return JSValue::encode(out);
+}
+
+JSC_DEFINE_HOST_FUNCTION(jsFunctionIsBuiltinModule,
+ (JSC::JSGlobalObject * globalObject,
+ JSC::CallFrame *callFrame)) {
+ JSC::VM &vm = globalObject->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ JSValue moduleName = callFrame->argument(0);
+ if (!moduleName.isString()) {
+ return JSValue::encode(jsBoolean(false));
+ }
+
+ auto moduleStr = moduleName.toWTFString(globalObject);
+ RETURN_IF_EXCEPTION(scope, JSValue::encode(jsBoolean(false)));
+
+ return JSValue::encode(jsBoolean(isBuiltinModule(moduleStr)));
+}
+
+JSC_DEFINE_HOST_FUNCTION(jsFunctionNodeModuleCreateRequire,
+ (JSC::JSGlobalObject * globalObject,
+ JSC::CallFrame *callFrame)) {
+ JSC::VM &vm = globalObject->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ if (callFrame->argumentCount() < 1) {
+ throwTypeError(globalObject, scope,
+ "createRequire() requires at least one argument"_s);
+ RELEASE_AND_RETURN(scope, JSC::JSValue::encode(JSC::jsUndefined()));
+ }
+
+ auto val = callFrame->uncheckedArgument(0).toWTFString(globalObject);
+ RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(JSC::jsUndefined()));
+ RELEASE_AND_RETURN(
+ scope, JSValue::encode(Bun::JSCommonJSModule::createBoundRequireFunction(
+ vm, globalObject, val)));
+}
+extern "C" EncodedJSValue Resolver__nodeModulePathsForJS(JSGlobalObject *,
+ CallFrame *);
+
+JSC_DEFINE_HOST_FUNCTION(jsFunctionFindSourceMap,
+ (JSGlobalObject * globalObject,
+ CallFrame *callFrame)) {
+ auto &vm = globalObject->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ throwException(globalObject, scope,
+ createError(globalObject, "Not implemented"_s));
+ return JSValue::encode(jsUndefined());
+}
+
+JSC_DEFINE_HOST_FUNCTION(jsFunctionSyncBuiltinExports,
+ (JSGlobalObject * globalObject,
+ CallFrame *callFrame)) {
+ return JSValue::encode(jsUndefined());
+}
+
+JSC_DEFINE_HOST_FUNCTION(jsFunctionSourceMap, (JSGlobalObject * globalObject,
+ CallFrame *callFrame)) {
+ auto &vm = globalObject->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ throwException(globalObject, scope,
+ createError(globalObject, "Not implemented"_s));
+ return JSValue::encode(jsUndefined());
+}
+
+JSC_DEFINE_HOST_FUNCTION(jsFunctionResolveFileName,
+ (JSC::JSGlobalObject * globalObject,
+ JSC::CallFrame *callFrame)) {
+ JSC::VM &vm = globalObject->vm();
+
+ switch (callFrame->argumentCount()) {
+ case 0: {
+ auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
+ // not "requires" because "require" could be confusing
+ JSC::throwTypeError(
+ globalObject, scope,
+ "Module._resolveFileName needs 2+ arguments (a string)"_s);
+ scope.release();
+ return JSC::JSValue::encode(JSC::JSValue{});
+ }
+ default: {
+ JSC::JSValue moduleName = callFrame->argument(0);
+
+ if (moduleName.isUndefinedOrNull()) {
+ auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
+ JSC::throwTypeError(globalObject, scope,
+ "Module._resolveFileName expects a string"_s);
+ scope.release();
+ return JSC::JSValue::encode(JSC::JSValue{});
+ }
+
+ auto result =
+ Bun__resolveSync(globalObject, JSC::JSValue::encode(moduleName),
+ JSValue::encode(callFrame->argument(1)), false);
+ auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
+
+ if (!JSC::JSValue::decode(result).isString()) {
+ JSC::throwException(globalObject, scope, JSC::JSValue::decode(result));
+ return JSC::JSValue::encode(JSC::JSValue{});
+ }
+
+ scope.release();
+ return result;
+ }
+ }
+}
+template <std::size_t N, class T> consteval std::size_t countof(T (&)[N]) {
+ return N;
+}
namespace Zig {
-// node:module
-void generateNodeModuleModule(JSC::JSGlobalObject *globalObject,
- JSC::Identifier moduleKey,
- Vector<JSC::Identifier, 4> &exportNames,
- JSC::MarkedArgumentBuffer &exportValues);
+DEFINE_NATIVE_MODULE(NodeModule) {
+ // the default object here is a function, so we cant use the INIT_NATIVE_MODULE helper
+
+ Zig::GlobalObject *globalObject = reinterpret_cast<Zig::GlobalObject *>(lexicalGlobalObject);
+ JSC::VM &vm = globalObject->vm();
+ JSC::JSObject *defaultObject = JSC::JSFunction::create(
+ vm, globalObject, 0, "Module"_s, jsFunctionNodeModuleModuleConstructor,
+ JSC::ImplementationVisibility::Public, JSC::NoIntrinsic,
+ jsFunctionNodeModuleModuleConstructor);
+ auto put = [&](JSC::Identifier name, JSC::JSValue value) {
+ defaultObject->putDirect(vm, name, value);
+ exportNames.append(name);
+ exportValues.append(value);
+ };
+ auto putNativeFn = [&](JSC::Identifier name, JSC::NativeFunction ptr) {
+ JSC::JSFunction *value = JSC::JSFunction::create(
+ vm, globalObject, 1, name.string(), ptr,
+ JSC::ImplementationVisibility::Public, JSC::NoIntrinsic, ptr);
+ defaultObject->putDirect(vm, name, value);
+ exportNames.append(name);
+ exportValues.append(value);
+ };
+ exportNames.reserveCapacity(13);
+ exportValues.ensureCapacity(13);
+ exportNames.append(vm.propertyNames->defaultKeyword);
+ exportValues.append(defaultObject);
+
+ putNativeFn(Identifier::fromString(vm, "createRequire"_s),
+ jsFunctionNodeModuleCreateRequire);
+ putNativeFn(Identifier::fromString(vm, "paths"_s),
+ Resolver__nodeModulePathsForJS);
+ putNativeFn(Identifier::fromString(vm, "findSourceMap"_s),
+ jsFunctionFindSourceMap);
+ putNativeFn(Identifier::fromString(vm, "syncBuiltinExports"_s),
+ jsFunctionSyncBuiltinExports);
+ putNativeFn(Identifier::fromString(vm, "SourceMap"_s), jsFunctionSourceMap);
+ putNativeFn(Identifier::fromString(vm, "isBuiltin"_s),
+ jsFunctionIsBuiltinModule);
+ putNativeFn(Identifier::fromString(vm, "_resolveFilename"_s),
+ jsFunctionResolveFileName);
+ putNativeFn(Identifier::fromString(vm, "_nodeModulePaths"_s),
+ Resolver__nodeModulePathsForJS);
+
+ put(Identifier::fromString(vm, "_cache"_s),
+ jsCast<Zig::GlobalObject *>(globalObject)->lazyRequireCacheObject());
+
+ put(Identifier::fromString(vm, "globalPaths"_s),
+ constructEmptyArray(globalObject, nullptr, 0));
+
+ put(Identifier::fromString(vm, "prototype"_s),
+ constructEmptyObject(globalObject));
+
+ JSC::JSArray *builtinModules = JSC::JSArray::create(
+ vm,
+ globalObject->arrayStructureForIndexingTypeDuringAllocation(
+ ArrayWithContiguous),
+ countof(builtinModuleNames));
+
+ for (unsigned i = 0; i < countof(builtinModuleNames); ++i) {
+ builtinModules->putDirectIndex(
+ globalObject, i, JSC::jsString(vm, String(builtinModuleNames[i])));
+ }
+
+ put(JSC::Identifier::fromString(vm, "builtinModules"_s), builtinModules);
+
+ RETURN_NATIVE_MODULE();
+}
-} // namespace Zig \ No newline at end of file
+} // namespace Zig