diff options
author | 2023-04-04 16:49:33 -0700 | |
---|---|---|
committer | 2023-04-04 16:49:33 -0700 | |
commit | a369fc8c8969b0f2d823bed5a7565d245311345b (patch) | |
tree | 1b8c16d0d5506d9fd6c3510e472588684e718030 | |
parent | 54d6f95f43774f92dddcbd91a669eec4a9f24d38 (diff) | |
download | bun-a369fc8c8969b0f2d823bed5a7565d245311345b.tar.gz bun-a369fc8c8969b0f2d823bed5a7565d245311345b.tar.zst bun-a369fc8c8969b0f2d823bed5a7565d245311345b.zip |
Implement `import.meta.main` (#2556)
* Implement `import.meta.main`
* Update main-test-1.js
* Update fs.test.ts
---------
Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
-rw-r--r-- | packages/bun-types/globals.d.ts | 27 | ||||
-rw-r--r-- | src/bun.js/bindings/ImportMetaObject.cpp | 11 | ||||
-rw-r--r-- | src/bun.js/builtins/cpp/ImportMetaObjectBuiltins.cpp | 11 | ||||
-rw-r--r-- | src/bun.js/builtins/cpp/ImportMetaObjectBuiltins.h | 9 | ||||
-rw-r--r-- | src/bun.js/builtins/cpp/ProcessObjectInternalsBuiltins.cpp | 5 | ||||
-rw-r--r-- | src/bun.js/builtins/js/ImportMetaObject.js | 7 | ||||
-rw-r--r-- | test/js/bun/resolve/import-meta.test.js | 14 | ||||
-rw-r--r-- | test/js/bun/resolve/main-test-1.js | 5 | ||||
-rw-r--r-- | test/js/bun/resolve/main-test-script.js | 7 | ||||
-rw-r--r-- | test/js/node/fs/fs.test.ts | 1 |
10 files changed, 89 insertions, 8 deletions
diff --git a/packages/bun-types/globals.d.ts b/packages/bun-types/globals.d.ts index 6ff2e9970..a9fdc01a1 100644 --- a/packages/bun-types/globals.d.ts +++ b/packages/bun-types/globals.d.ts @@ -234,21 +234,21 @@ interface ImportMeta { * "file:///Users/me/projects/my-app/src/my-app.ts" * ``` */ - url: string; + readonly url: string; /** * Absolute path to the source file */ - path: string; + readonly path: string; /** * Absolute path to the directory containing the source file. * * Does not have a trailing slash */ - dir: string; + readonly dir: string; /** * Filename of the source file */ - file: string; + readonly file: string; /** * Resolve a module ID the same as if you imported it * @@ -284,6 +284,25 @@ interface ImportMeta { * relevant. */ require: NodeJS.Require; + + /** + * Did the current file start the process? + * + * @example + * ```ts + * if (import.meta.main) { + * console.log("I started the process!"); + * } + * ``` + * + * @example + * ```ts + * console.log( + * import.meta.main === (import.meta.path === Bun.main) + * ) + * ``` + */ + readonly main: boolean; } /** diff --git a/src/bun.js/bindings/ImportMetaObject.cpp b/src/bun.js/bindings/ImportMetaObject.cpp index f8b6d0f9b..7831cf881 100644 --- a/src/bun.js/bindings/ImportMetaObject.cpp +++ b/src/bun.js/bindings/ImportMetaObject.cpp @@ -39,6 +39,7 @@ #include "JSDOMURL.h" #include "JavaScriptCore/JSNativeStdFunction.h" +#include "JavaScriptCore/GetterSetter.h" namespace Zig { using namespace JSC; @@ -84,7 +85,7 @@ static EncodedJSValue functionRequireResolve(JSC::JSGlobalObject* globalObject, // require.resolve also supports a paths array // we only support a single path if (!fromValue.isUndefinedOrNull() && fromValue.isObject()) { - if (JSValue pathsValue = fromValue.getObject()->getIfPropertyExists(globalObject, JSC::Identifier::fromString(vm, "paths"_s))) { + if (JSValue pathsValue = fromValue.getObject()->getIfPropertyExists(globalObject, JSC::Identifier::fromString(vm, "paths"_s))) { if (JSC::JSArray* array = JSC::jsDynamicCast<JSC::JSArray*>(pathsValue)) { if (array->length() > 0) { fromValue = array->getIndex(globalObject, 0); @@ -413,7 +414,13 @@ void ImportMetaObjectPrototype::finishCreation(VM& vm, JSGlobalObject* globalObj this->putDirect(vm, builtinNames.dirPublicName(), jsEmptyString(vm), 0); this->putDirect(vm, builtinNames.pathPublicName(), jsEmptyString(vm), 0); this->putDirect(vm, builtinNames.urlPublicName(), jsEmptyString(vm), 0); - this->putDirect(vm, builtinNames.mainPublicName(), jsBoolean(false), 0); + + this->putDirect( + vm, + builtinNames.mainPublicName(), + GetterSetter::create(vm, globalObject, JSFunction::create(vm, importMetaObjectMainCodeGenerator(vm), globalObject), nullptr), + JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::Accessor | JSC::PropertyAttribute::Builtin | 0); + this->putDirect(vm, Identifier::fromString(vm, "primordials"_s), jsUndefined(), JSC::PropertyAttribute::DontEnum | 0); String requireString = "[[require]]"_s; diff --git a/src/bun.js/builtins/cpp/ImportMetaObjectBuiltins.cpp b/src/bun.js/builtins/cpp/ImportMetaObjectBuiltins.cpp index d014618c3..a9ce25b04 100644 --- a/src/bun.js/builtins/cpp/ImportMetaObjectBuiltins.cpp +++ b/src/bun.js/builtins/cpp/ImportMetaObjectBuiltins.cpp @@ -255,6 +255,17 @@ const char* const s_importMetaObjectRequireCode = "})\n" \ ; +const JSC::ConstructAbility s_importMetaObjectMainCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; +const JSC::ConstructorKind s_importMetaObjectMainCodeConstructorKind = JSC::ConstructorKind::None; +const JSC::ImplementationVisibility s_importMetaObjectMainCodeImplementationVisibility = JSC::ImplementationVisibility::Public; +const int s_importMetaObjectMainCodeLength = 52; +static const JSC::Intrinsic s_importMetaObjectMainCodeIntrinsic = JSC::NoIntrinsic; +const char* const s_importMetaObjectMainCode = + "(function () {\n" \ + " return this.path === @Bun.main;\n" \ + "})\n" \ +; + #define DEFINE_BUILTIN_GENERATOR(codeName, functionName, overriddenName, argumentCount) \ JSC::FunctionExecutable* codeName##Generator(JSC::VM& vm) \ diff --git a/src/bun.js/builtins/cpp/ImportMetaObjectBuiltins.h b/src/bun.js/builtins/cpp/ImportMetaObjectBuiltins.h index d47c86980..1a7c5d844 100644 --- a/src/bun.js/builtins/cpp/ImportMetaObjectBuiltins.h +++ b/src/bun.js/builtins/cpp/ImportMetaObjectBuiltins.h @@ -67,27 +67,36 @@ extern const int s_importMetaObjectRequireCodeLength; extern const JSC::ConstructAbility s_importMetaObjectRequireCodeConstructAbility; extern const JSC::ConstructorKind s_importMetaObjectRequireCodeConstructorKind; extern const JSC::ImplementationVisibility s_importMetaObjectRequireCodeImplementationVisibility; +extern const char* const s_importMetaObjectMainCode; +extern const int s_importMetaObjectMainCodeLength; +extern const JSC::ConstructAbility s_importMetaObjectMainCodeConstructAbility; +extern const JSC::ConstructorKind s_importMetaObjectMainCodeConstructorKind; +extern const JSC::ImplementationVisibility s_importMetaObjectMainCodeImplementationVisibility; #define WEBCORE_FOREACH_IMPORTMETAOBJECT_BUILTIN_DATA(macro) \ macro(loadCJS2ESM, importMetaObjectLoadCJS2ESM, 1) \ macro(requireESM, importMetaObjectRequireESM, 1) \ macro(internalRequire, importMetaObjectInternalRequire, 1) \ macro(require, importMetaObjectRequire, 1) \ + macro(main, importMetaObjectMain, 0) \ #define WEBCORE_BUILTIN_IMPORTMETAOBJECT_LOADCJS2ESM 1 #define WEBCORE_BUILTIN_IMPORTMETAOBJECT_REQUIREESM 1 #define WEBCORE_BUILTIN_IMPORTMETAOBJECT_INTERNALREQUIRE 1 #define WEBCORE_BUILTIN_IMPORTMETAOBJECT_REQUIRE 1 +#define WEBCORE_BUILTIN_IMPORTMETAOBJECT_MAIN 1 #define WEBCORE_FOREACH_IMPORTMETAOBJECT_BUILTIN_CODE(macro) \ macro(importMetaObjectLoadCJS2ESMCode, loadCJS2ESM, ASCIILiteral(), s_importMetaObjectLoadCJS2ESMCodeLength) \ macro(importMetaObjectRequireESMCode, requireESM, ASCIILiteral(), s_importMetaObjectRequireESMCodeLength) \ macro(importMetaObjectInternalRequireCode, internalRequire, ASCIILiteral(), s_importMetaObjectInternalRequireCodeLength) \ macro(importMetaObjectRequireCode, require, ASCIILiteral(), s_importMetaObjectRequireCodeLength) \ + macro(importMetaObjectMainCode, main, "get main"_s, s_importMetaObjectMainCodeLength) \ #define WEBCORE_FOREACH_IMPORTMETAOBJECT_BUILTIN_FUNCTION_NAME(macro) \ macro(internalRequire) \ macro(loadCJS2ESM) \ + macro(main) \ macro(require) \ macro(requireESM) \ diff --git a/src/bun.js/builtins/cpp/ProcessObjectInternalsBuiltins.cpp b/src/bun.js/builtins/cpp/ProcessObjectInternalsBuiltins.cpp index c2276138e..bd496deff 100644 --- a/src/bun.js/builtins/cpp/ProcessObjectInternalsBuiltins.cpp +++ b/src/bun.js/builtins/cpp/ProcessObjectInternalsBuiltins.cpp @@ -51,7 +51,7 @@ namespace WebCore { const JSC::ConstructAbility s_processObjectInternalsBindingCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; const JSC::ConstructorKind s_processObjectInternalsBindingCodeConstructorKind = JSC::ConstructorKind::None; const JSC::ImplementationVisibility s_processObjectInternalsBindingCodeImplementationVisibility = JSC::ImplementationVisibility::Public; -const int s_processObjectInternalsBindingCodeLength = 688; +const int s_processObjectInternalsBindingCodeLength = 709; static const JSC::Intrinsic s_processObjectInternalsBindingCodeIntrinsic = JSC::NoIntrinsic; const char* const s_processObjectInternalsBindingCode = "(function (bindingName) {\n" \ @@ -64,6 +64,9 @@ const char* const s_processObjectInternalsBindingCode = " var cache = globalThis.Symbol.for(\"process.bindings.constants\");\n" \ " var constants = globalThis[cache];\n" \ " if (!constants) {\n" \ + " //\n" \ + " //\n" \ + " //\n" \ " const {constants: fs} = globalThis[globalThis.Symbol.for(\"Bun.lazy\")](\n" \ " \"createImportMeta\",\n" \ " \"node:process\"\n" \ diff --git a/src/bun.js/builtins/js/ImportMetaObject.js b/src/bun.js/builtins/js/ImportMetaObject.js index 82701554d..b8d7900c0 100644 --- a/src/bun.js/builtins/js/ImportMetaObject.js +++ b/src/bun.js/builtins/js/ImportMetaObject.js @@ -202,4 +202,9 @@ function require(name) { } return @internalRequire(@resolveSync(name, from)); -}
\ No newline at end of file +} + +@getter +function main() { + return this.path === @Bun.main; +} diff --git a/test/js/bun/resolve/import-meta.test.js b/test/js/bun/resolve/import-meta.test.js index a95b1a0ea..c4bbdb1a6 100644 --- a/test/js/bun/resolve/import-meta.test.js +++ b/test/js/bun/resolve/import-meta.test.js @@ -2,6 +2,9 @@ import { it, expect } from "bun:test"; import { mkdirSync, rmSync, writeFileSync } from "node:fs"; import * as Module from "node:module"; import sync from "./require-json.json"; +import { spawnSync } from "bun"; +import { bunEnv, bunExe } from "harness"; +import { join } from "node:path"; const { path, dir } = import.meta; @@ -9,6 +12,17 @@ it("primordials are not here!", () => { expect(import.meta.primordials === undefined).toBe(true); }); +it("import.meta.main", () => { + const { exitCode } = spawnSync({ + cmd: [bunExe(), "run", join(import.meta.dir, "./main-test-script.js")], + env: bunEnv, + stderr: "inherit", + stdout: "inherit", + stdin: null, + }); + expect(exitCode).toBe(0); +}); + it("import.meta.resolveSync", () => { expect(import.meta.resolveSync("./" + import.meta.file, import.meta.path)).toBe(path); const require = Module.createRequire(import.meta.path); diff --git a/test/js/bun/resolve/main-test-1.js b/test/js/bun/resolve/main-test-1.js new file mode 100644 index 000000000..8e83d65e1 --- /dev/null +++ b/test/js/bun/resolve/main-test-1.js @@ -0,0 +1,5 @@ +if (import.meta.main) { + process.exit(1); +} + +export const pass = true; diff --git a/test/js/bun/resolve/main-test-script.js b/test/js/bun/resolve/main-test-script.js new file mode 100644 index 000000000..d5b0cb67a --- /dev/null +++ b/test/js/bun/resolve/main-test-script.js @@ -0,0 +1,7 @@ +import "./main-test-1"; + +if (!import.meta.main) { + process.exit(1); +} + +process.exit(0); diff --git a/test/js/node/fs/fs.test.ts b/test/js/node/fs/fs.test.ts index fa27ab246..f7b343539 100644 --- a/test/js/node/fs/fs.test.ts +++ b/test/js/node/fs/fs.test.ts @@ -38,6 +38,7 @@ import { ReadStream as ReadStreamStar_, WriteStream as WriteStreamStar_ } from " const Buffer = globalThis.Buffer || Uint8Array; if (!import.meta.dir) { + //@ts-expect-error import.meta.dir = "."; } |