Skip to content

Commit

Permalink
add ModuleDelegate.builtinModuleNames
Browse files Browse the repository at this point in the history
  • Loading branch information
suchipi committed Sep 9, 2024
1 parent 47d0781 commit 060187a
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 10 deletions.
66 changes: 60 additions & 6 deletions src/builtin-modules/quickjs-engine/quickjs-engine.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ static int js_userdefined_module_init(JSContext *ctx, JSModuleDef *m)
static JSValue js_engine_defineBuiltinModule(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
JSValueConst obj;
JSValueConst obj, name_val;
const char *name = NULL;
JSModuleDef *m = NULL;
QJUForEachPropertyState *foreach = NULL;
Expand All @@ -283,20 +283,21 @@ static JSValue js_engine_defineBuiltinModule(JSContext *ctx, JSValueConst this_v
goto end;
}

name = JS_ToCString(ctx, argv[0]);
name_val = argv[0];
obj = argv[1];

name = JS_ToCString(ctx, name_val);
if (name == NULL) {
ret = JS_EXCEPTION;
goto end;
}

if (!JS_IsObject(argv[1])) {
if (!JS_IsObject(obj)) {
JS_ThrowError(ctx, "Second argument to defineBuiltinModule must be an object.");
ret = JS_EXCEPTION;
goto end;
}

obj = argv[1];

m = JS_NewCModule(ctx, name, js_userdefined_module_init, &obj);
if (m == NULL) {
ret = JS_EXCEPTION;
Expand Down Expand Up @@ -334,7 +335,60 @@ static JSValue js_engine_defineBuiltinModule(JSContext *ctx, JSValueConst this_v
ret = JS_EXCEPTION;
goto end;
} else {
ret = JS_UNDEFINED;
// Add module name to ModuleDelegate.builtinModuleNames, if available.
JSValue module_loader_internals;

module_loader_internals = QJMS_GetModuleLoaderInternals(ctx);
if (JS_IsObject(module_loader_internals)) {
JSValue module_delegate, builtins_array, builtins_array_length_val;
int64_t builtins_array_length;

module_delegate = JS_GetPropertyStr(ctx, module_loader_internals,
"ModuleDelegate");
if (JS_IsException(module_delegate)) {
JS_FreeValue(ctx, module_loader_internals);
ret = JS_EXCEPTION;
goto end;
}

builtins_array = JS_GetPropertyStr(ctx, module_delegate,
"builtinModuleNames");
if (JS_IsException(builtins_array)) {
JS_FreeValue(ctx, module_delegate);
JS_FreeValue(ctx, module_loader_internals);
ret = JS_EXCEPTION;
goto end;
}

builtins_array_length_val = JS_GetPropertyStr(ctx, builtins_array, "length");
if (JS_IsException(builtins_array_length_val)) {
JS_FreeValue(ctx, builtins_array);
JS_FreeValue(ctx, module_delegate);
JS_FreeValue(ctx, module_loader_internals);
ret = JS_EXCEPTION;
goto end;
}

if (JS_ToInt64(ctx, &builtins_array_length, builtins_array_length_val)) {
JS_FreeValue(ctx, builtins_array_length_val);
JS_FreeValue(ctx, builtins_array);
JS_FreeValue(ctx, module_delegate);
JS_FreeValue(ctx, module_loader_internals);
ret = JS_EXCEPTION;
goto end;
}

if (JS_SetPropertyInt64(ctx, builtins_array, builtins_array_length,
JS_DupValue(ctx, name_val)) == -1) {
ret = JS_EXCEPTION;
// fall-through to frees
}

JS_FreeValue(ctx, builtins_array_length_val);
JS_FreeValue(ctx, builtins_array);
JS_FreeValue(ctx, module_delegate);
JS_FreeValue(ctx, module_loader_internals);
}
}

end:
Expand Down
10 changes: 10 additions & 0 deletions src/quickjs-modulesys/module-impl.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,16 @@ import * as os from "quickjs:os";
}
};

ModuleDelegate.builtinModuleNames = [
"quickjs:std",
"quickjs:os",
"quickjs:bytecode",
"quickjs:context",
"quickjs:pointer",
"quickjs:engine",
"quickjs:encoding",
];

function isAbsolute(path) {
return path[0] === "/" || /[A-Za-z]:[/\\]/.test(path);
}
Expand Down
9 changes: 9 additions & 0 deletions src/quickjs-modulesys/quickjs-modulesys.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,15 @@ interface ModuleDelegate {
[extensionWithDot: string]: (filename: string, content: string) => string;
};

/**
* An Array containing the names of all the built-in modules, such as
* "quickjs:std", "quickjs:bytecode", etc.
*
* `quickjs:engine`'s `defineBuiltinModule` function adds to the end of this
* array.
*/
builtinModuleNames: Array<string>;

/**
* Resolves a require/import request from `fromFile` into a canonicalized
* path.
Expand Down
21 changes: 17 additions & 4 deletions tests/module-define.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@ test("defineBuiltinModule - basic test", async () => {
"-m",
"-e",
`
import { defineBuiltinModule } from "quickjs:engine";
import { defineBuiltinModule, ModuleDelegate } from "quickjs:engine";
console.log("builtins contains mymodule:", ModuleDelegate.builtinModuleNames.includes("mymodule"));
defineBuiltinModule("mymodule", {
something: 5,
somethingElse: () => 6
});
console.log("builtins contains mymodule:", ModuleDelegate.builtinModuleNames.includes("mymodule"));
const mod = require("mymodule");
console.log(mod.something);
console.log(mod.somethingElse());
Expand All @@ -23,7 +28,9 @@ test("defineBuiltinModule - basic test", async () => {
"code": 0,
"error": false,
"stderr": "",
"stdout": "5
"stdout": "builtins contains mymodule: false
builtins contains mymodule: true
5
6
",
}
Expand All @@ -35,12 +42,16 @@ test("defineBuiltinModule - never imported", async () => {
"-m",
"-e",
`
import { defineBuiltinModule } from "quickjs:engine";
import { defineBuiltinModule, ModuleDelegate } from "quickjs:engine";
console.log("builtins contains mymodule:", ModuleDelegate.builtinModuleNames.includes("mymodule"));
defineBuiltinModule("mymodule", {
something: 5,
somethingElse: () => 6
});
console.log("builtins contains mymodule:", ModuleDelegate.builtinModuleNames.includes("mymodule"));
`,
]);
await run.completion;
Expand All @@ -49,7 +60,9 @@ test("defineBuiltinModule - never imported", async () => {
"code": 0,
"error": false,
"stderr": "",
"stdout": "",
"stdout": "builtins contains mymodule: false
builtins contains mymodule: true
",
}
`);
});

0 comments on commit 060187a

Please sign in to comment.