Skip to content

Commit 53b9b6d

Browse files
authored
docs: document QuickJS ESModule entry path resolution behavior
1 parent 00fe842 commit 53b9b6d

2 files changed

Lines changed: 117 additions & 0 deletions

File tree

docs/apis/LanguageSupport.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,69 @@ Currently, LSE supports writing plugins in the following languages:
3030
- Use `jsdebug` command in the BDS console to enter and exit the QuickJs interactive command line environment. This
3131
feature facilitates some simple testing when writing plugins
3232

33+
### QuickJS ESModule Path Resolution Behavior
34+
35+
The **ScriptX** used by LegacyScriptEngine is forked from the upstream **Tencent/ScriptX** project, with additional features added on top of it (such as Python backend support).
36+
37+
In the QuickJS backend, ScriptX uses the default `module loader` provided in **quickjs-libc.h**.
38+
This loader causes the behavior of QuickJS ESModule when resolving the **entry module** to differ from the standard ESModule specification.
39+
40+
Specifically, when loading the **entry module**, the loader sets the module's base path to the **current working directory (CWD)** — which is typically the directory where the server executable is located — rather than the directory where the script file resides.
41+
42+
As a result, relative `import` paths in the entry file are resolved differently from standard ESModule behavior.
43+
44+
Assume the following plugin directory structure:
45+
46+
```
47+
c:/bds
48+
bedrock_server_mod.exe
49+
plugins/
50+
your_plugin/
51+
manifest.json
52+
index.js
53+
command/
54+
command.js
55+
```
56+
57+
Entry file **index.js**:
58+
```js
59+
import { initCommand } from "./command/command.js"
60+
61+
initCommand();
62+
```
63+
64+
In this case, QuickJS resolves the entry module's import.meta.url as:
65+
66+
```
67+
file:///c:/bds
68+
```
69+
70+
instead of:
71+
72+
```
73+
file:///c:/bds/plugins/your_plugin
74+
```
75+
76+
Therefore `./command/command.js` cannot be resolved correctly, causing the plugin to fail to load.
77+
78+
For example, QuickJS may produce an error similar to the following (original log output):
79+
```
80+
19:26:12.343 ERROR [LeviLamina] Failed to load plugin your_plugin: Unexpected token '{'
81+
19:26:12.343 ERROR [LeviLamina] at ./plugins/your_plugin\index.js:1:1
82+
```
83+
84+
To resolve this issue, use a path **relative to the current working directory (CWD)**:
85+
86+
```js
87+
import { initCommand } from "./plugins/your_plugin/command/command.js"
88+
```
89+
90+
This will allow the module to be loaded correctly.
91+
92+
!!! tip
93+
This issue **only affects the entry module specified in manifest.json**.
94+
After the entry module is loaded, module resolution between other modules follows the standard ESModule behavior.
95+
3396
## Lua language support description
3497

3598
- Use the CLua engine, support require

docs/apis/LanguageSupport.zh.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,60 @@
2424
- 暂不支持包管理机制,如果需要请使用 Node.js 进行插件开发,使用 npm 包管理
2525
- 在BDS控制台中使用`jsdebug`命令进入和退出 QuickJs 交互式命令行环境。此功能便于编写插件时进行一些简单的测试
2626

27+
### 关于 QuickJs ESModule 的路径解析行为
28+
29+
LegacyScriptEngine 使用的 ScriptX 来自上游 Tencent/ScriptX 项目的 fork,
30+
并在其基础上增加了一些功能(例如 Python 后端支持等)。
31+
32+
在 QuickJs 后端中,ScriptX 默认使用 **quickjs-libc.h** 中提供的 `module loader`
33+
该 loader 会导致 QuickJS ESModule 在解析入口模块时的行为与标准 ESModule 不完全一致。
34+
35+
具体表现为:
36+
该 loader 在加载 **入口模块** 时,会将模块的 base path 设为 **当前工作目录 (CWD),即服务器程序所在目录**,而不是脚本文件所在目录。
37+
因此入口文件中的相对 `import` 路径解析行为与标准 ESModule 不完全一致。
38+
39+
假设脚本插件的结构为:
40+
41+
```
42+
c:/bds
43+
bedrock_server_mod.exe
44+
plugins/
45+
your_plugin/
46+
manifest.json
47+
index.js
48+
command/
49+
command.js
50+
```
51+
52+
**index.js** 入口文件:
53+
```js
54+
import { initCommand } from "./command/command.js"
55+
56+
initCommand();
57+
```
58+
59+
此时 QuickJS 会将入口模块的 `import.meta.url` 解析为 `file:///c:/bds` 而不是 `file:///c:/bds/plugins/your_plugin`
60+
61+
因此 `./command/command.js` 会解析失败,导致插件加载失败。
62+
63+
例如 QuickJS 可能会抛出类似如下的错误(原始日志):
64+
```
65+
19:26:12.343 ERROR [LeviLamina] Failed to load plugin your_plugin: Unexpected token '{'
66+
19:26:12.343 ERROR [LeviLamina] at ./plugins/your_plugin\index.js:1:1
67+
```
68+
69+
解决方法是使用**相对于工作目录的路径**
70+
71+
```js
72+
import { initCommand } from "./plugins/your_plugin/command/command.js"
73+
```
74+
75+
即可正常加载模块。
76+
77+
!!! tip
78+
该问题**仅影响 manifest.json 指定的入口模块**
79+
入口模块加载完成后,其它模块之间的 `import` 行为均符合标准 ESModule 规则。
80+
2781
## Lua 语言支持说明
2882

2983
- 使用 CLua 引擎,支持使用 require 进行简单的项目管理

0 commit comments

Comments
 (0)