同步最新主干并修复 Godot 插件启动竞态
Project CI / AI game creator shell Rust shard 1/4 (push) Failing after 13s
Project CI / AI game creator shell Rust shard 2/4 (push) Failing after 12s
Project CI / AI game creator shell Rust shard 3/4 (push) Failing after 12s
Project CI / AI game creator shell Rust shard 4/4 (push) Failing after 13s
Project CI / AI game creator shell Rust smoke (push) Failing after 12s
Project CI / AI game creator shell Rust crates (push) Failing after 20s
Project CI / Backend tests (push) Failing after 23s
Project CI / Native shell tests (push) Failing after 12s
Project CI / Frontend tests (push) Failing after 5s
Project CI / Repository checks (push) Failing after 11s
Project CI / AI game creator shell web tests (push) Failing after 13s

合入主干 Rust 1.98.1 工具链及对应 CI 文档更新
Godot 插件先接收受控项目快照再注册命令和连接能力
补充启动竞态回归、失败回执诊断及插件启动合同
This commit is contained in:
kdletters
2026-09-20 17:46:53 +08:00
12 changed files with 139 additions and 21 deletions
+5 -5
View File
@@ -224,6 +224,11 @@ export function createGodotEditorPlugin({ send, timeoutMs = 85_000 }) {
}
async function start() {
const epoch = projectEpoch;
const result = await request('host.events.subscribe', {
type: 'project.changed',
});
if (epoch === projectEpoch) activeProjectPath = result?.projectPath ?? null;
await request('host.registerCommand', {
id: GODOT_EXECUTE_COMMAND_ID,
title: '执行 Godot GDScript',
@@ -233,11 +238,6 @@ export function createGodotEditorPlugin({ send, timeoutMs = 85_000 }) {
id: GODOT_CONNECTION_CAPABILITY_ID,
description: '当前 Godot 项目的编辑器连接与状态',
});
const epoch = projectEpoch;
const result = await request('host.events.subscribe', {
type: 'project.changed',
});
if (epoch === projectEpoch) activeProjectPath = result?.projectPath ?? null;
}
function dispose() {
+40 -1
View File
@@ -70,9 +70,9 @@ test('注册声明的命令与连接能力,并使用宿主提供的当前项
assert.deepEqual(
f.requests.slice(0, 3).map((item) => item.method),
[
'host.events.subscribe',
'host.registerCommand',
'host.registerCapability',
'host.events.subscribe',
],
);
assert.deepEqual((await f.call({ code: 'return 1 + 1;' })).result, success);
@@ -89,6 +89,45 @@ test('注册声明的命令与连接能力,并使用宿主提供的当前项
);
});
test('命令和能力公开时已绑定项目,立即执行无需等待后续启动请求', async (t) => {
const messages = [];
const plugin = createGodotEditorPlugin({
send(message) {
messages.push(message);
if (!message.method) return;
queueMicrotask(async () => {
if (message.method === 'host.registerCapability') {
await plugin.handleMessage({
jsonrpc: '2.0',
id: 1000,
method: GODOT_EXECUTE_COMMAND_ID,
params: { code: 'return 2' },
});
}
await plugin.handleMessage({
jsonrpc: '2.0',
id: message.id,
result:
message.method === 'host.events.subscribe'
? { projectPath: 'C:/Godot/Ready' }
: success,
});
});
},
});
t.after(() => plugin.dispose());
await plugin.start();
assert.deepEqual(
messages.find((message) => message.id === 1000).result,
success,
);
assert.equal(
messages.find((message) => message.method === 'host.rpc').params.params
.projectPath,
'C:/Godot/Ready',
);
});
test('显式项目、任意payload和非法代码在宿主派发前拒绝', async (t) => {
const f = await fixture(t);
for (const input of [