Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion webmcp/declarative/executeTool-abort.https.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
const tool = tools.find(t => t.name === 'submit_test');

const controller = new AbortController();
const executionPromise = document.modelContext.executeTool(tool, '{}', { signal: controller.signal });
const executionPromise = document.modelContext.executeTool(tool, {}, { signal: controller.signal });

await toolActivatedPromise;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
await promise_rejects_dom(
t,
'UnknownError',
document.modelContext.executeTool(tool, '{}'),
document.modelContext.executeTool(tool),
'executeTool() should reject with UnknownError when respondWith is passed a circular object'
);
}, 'Declarative tool executeTool() rejects when respondWith() receives a circular object');
Expand Down
6 changes: 3 additions & 3 deletions webmcp/declarative/execute_tool_change_event.https.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,16 @@
}
}

let inputArgs = JSON.stringify({
let inputObject = {
text: "regular text",
number: 42,
checkbox: true,
radio: "radio2",
textarea: "some text area content",
select: "opt2"
});
};

await document.modelContext.executeTool(tool, inputArgs);
await document.modelContext.executeTool(tool, inputObject);

assert_equals(document.getElementById('myinput').value, 'regular text');
assert_true(events['myinput'].inputFired, 'text input event should fire');
Expand Down
2 changes: 1 addition & 1 deletion webmcp/declarative/execute_tool_submit_from_js.https.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
});

// Call executeTool. If it throws, the test fails automatically.
await document.modelContext.executeTool(tool, '{}');
await document.modelContext.executeTool(tool);

assert_true(submitFired, 'submit event should have fired');
}, 'executeTool resolves successfully when submit handler calls form.submit()');
Expand Down
2 changes: 1 addition & 1 deletion webmcp/declarative/form_removal_submit_crash.https.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
// Execute the tool. This asynchronously fires the `submit` event at the form.
// The tool execution should resolve successfully even if the form is removed
// from the document during submission.
const promise = document.modelContext.executeTool(tool, '{}');
const promise = document.modelContext.executeTool(tool);
await promise;

assert_true(submitFired);
Expand Down
6 changes: 3 additions & 3 deletions webmcp/declarative/opaque-origin-tools.https.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
await promise_rejects_dom(
t,
'NotSupportedError',
document.modelContext.executeTool(tool, '{"param1":"value"}'),
document.modelContext.executeTool(tool, {"param1":"value"}),
'executeTool() must reject with NotSupportedError in opaque origin documents'
);
}, 'An opaque origin document can register but not execute its own declarative tools');
Expand All @@ -36,7 +36,7 @@
const tool = tools.find(t => t.name === 'opaque_tool');

let events = [];
const p = document.modelContext.executeTool(tool, '{}');
const p = document.modelContext.executeTool(tool);

// Since `executeTool()` synchronously rejects the Promise for opaque origins,
// the microtask to run the catch reaction is already queued before
Expand All @@ -49,7 +49,7 @@
await promise_rejects_dom(
t,
'NotSupportedError',
document.modelContext.executeTool(tool, '{"param1":"value"}'),
document.modelContext.executeTool(tool, {"param1":"value"}),
'executeTool() must reject with NotSupportedError in opaque origin documents'
);

Expand Down
6 changes: 3 additions & 3 deletions webmcp/declarative/select-multiple-events.https.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@
changeEventCount++;
});

let inputArgs = JSON.stringify({ fruits: ['apple', 'banana'] });
let inputObject = { fruits: ['apple', 'banana'] };

// This should dispatch events.
await document.modelContext.executeTool(tool, inputArgs);
await document.modelContext.executeTool(tool, inputObject);

assert_true(fruits.options[0].selected);
assert_false(fruits.options[1].selected);
Expand All @@ -50,7 +50,7 @@
assert_equals(changeEventCount, 1);

// Executing with the same arguments again does not trigger events.
await document.modelContext.executeTool(tool, inputArgs);
await document.modelContext.executeTool(tool, inputObject);

assert_equals(inputEventCount, 1);
assert_equals(changeEventCount, 1);
Expand Down
4 changes: 2 additions & 2 deletions webmcp/declarative/unregister-during-executeTool.https.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
const tool = tools.find(t => t.name === 'endless_tool');
assert_true(!!tool, 'Tool should be registered');

const execute_promise = document.modelContext.executeTool(tool, '{}');
const execute_promise = document.modelContext.executeTool(tool);

// Wait deterministically for the form to submit and call respondWith().
await submitted_promise;
Expand Down Expand Up @@ -79,7 +79,7 @@
const tool = tools.find(t => t.name === 'endless_tool_attr');
assert_true(!!tool, 'Tool should be registered');

const execute_promise = document.modelContext.executeTool(tool, '{}');
const execute_promise = document.modelContext.executeTool(tool);

// Wait deterministically for the form to submit and call respondWith().
await submitted_promise;
Expand Down
4 changes: 2 additions & 2 deletions webmcp/imperative/cancel-reentrancy-crash.https.html
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@
const regA = tools.find(t => t.name === 'toolA');
const regB = tools.find(t => t.name === 'toolB');

document.modelContext.executeTool(regA, '{}', { signal: controllerA.signal });
document.modelContext.executeTool(regB, '{}');
document.modelContext.executeTool(regA, {}, { signal: controllerA.signal });
document.modelContext.executeTool(regB);

// Wait for both tool execute callbacks to run and return, ensuring they are
// inserted into pending_executions_.
Expand Down
2 changes: 1 addition & 1 deletion webmcp/imperative/detached-frame-executeTool.https.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
iframe.remove();

// Calling executeTool() should reject with InvalidStateError.
await promise_rejects_dom(t, 'InvalidStateError', iDOMException, iframe_modelContext.executeTool(tool, '{}'));
await promise_rejects_dom(t, 'InvalidStateError', iDOMException, iframe_modelContext.executeTool(tool));
}, 'executeTool() throws `InvalidStateError` in detached frame');
</script>
</body>
Expand Down
12 changes: 6 additions & 6 deletions webmcp/imperative/executeTool-abort.https.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
}, { signal: regController.signal });

const [tool] = await document.modelContext.getTools();
const result = await document.modelContext.executeTool(tool, '{}');
const result = await document.modelContext.executeTool(tool);
assert_equals(result, 'success');
assert_true(received_signal instanceof AbortSignal, 'options.signal should be an AbortSignal instance');
assert_false(received_signal.aborted, 'signal should not be aborted');
Expand Down Expand Up @@ -63,7 +63,7 @@
const [tool] = await document.modelContext.getTools();

const controller = new AbortController();
const executionPromise = document.modelContext.executeTool(tool, '{}', { signal: controller.signal });
const executionPromise = document.modelContext.executeTool(tool, {}, { signal: controller.signal });

const { promise: toolCancelPromise, resolve: resolveToolCancel } = Promise.withResolvers();
window.addEventListener('toolcancel', e => {
Expand Down Expand Up @@ -103,7 +103,7 @@
const [tool] = await document.modelContext.getTools();
const signal = AbortSignal.abort('already aborted');
let executionRejectionValue = null;
document.modelContext.executeTool(tool, '{}', { signal }).catch(e => executionRejectionValue = e);
document.modelContext.executeTool(tool, {}, { signal }).catch(e => executionRejectionValue = e);

// Await a Promise that resolved synchronously, so that we guarantee that in
// the next microtask, `execute_promise` has already rejected. This asserts
Expand Down Expand Up @@ -133,7 +133,7 @@
const [tool] = await document.modelContext.getTools();
const controller = new AbortController();
const executePromise =
document.modelContext.executeTool(tool, '{}', { signal: controller.signal });
document.modelContext.executeTool(tool, {}, { signal: controller.signal });

// By the time this `abort()` is processed, the tool will have already started
// running and the abort handler will have already been registered.
Expand Down Expand Up @@ -184,8 +184,8 @@
const c1 = new AbortController();
const c2 = new AbortController();

const execPromise1 = document.modelContext.executeTool(tool, '{}', { signal: c1.signal });
const execPromise2 = document.modelContext.executeTool(tool, '{}', { signal: c2.signal });
const execPromise1 = document.modelContext.executeTool(tool, {}, { signal: c1.signal });
const execPromise2 = document.modelContext.executeTool(tool, {}, { signal: c2.signal });

await Promise.all([exec1Started, exec2Started]);

Expand Down
2 changes: 1 addition & 1 deletion webmcp/imperative/executeTool-across-trees.https.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@

const [tool] = await windowB.document.modelContext.getTools();
assert_equals(tool.window, windowB);
const execute_promise = document.modelContext.executeTool(tool, '{}');
const execute_promise = document.modelContext.executeTool(tool);

await promise_rejects_dom(t, 'UnknownError', execute_promise);
}, 'executeTool() rejects when the tool is hosted in another frame tree');
Expand Down
4 changes: 2 additions & 2 deletions webmcp/imperative/executeTool-error-window-onerror.https.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

// `executeTool()` should reject since the tool execution failed.
await promise_rejects_dom(t, 'UnknownError',
document.modelContext.executeTool(tool, '{}'),
document.modelContext.executeTool(tool),
'executeTool() rejects when the tool execution throws');

assert_false(errorFired, 'window.onerror/error event should not be fired');
Expand Down Expand Up @@ -66,7 +66,7 @@

// `executeTool()` should reject since serializing the return value throws a TypeError.
await promise_rejects_dom(t, 'UnknownError',
document.modelContext.executeTool(tool, '{}'),
document.modelContext.executeTool(tool),
'executeTool() rejects when the tool execution returns a circular object');

assert_false(errorFired, 'window.onerror/error event should not be fired');
Expand Down
33 changes: 26 additions & 7 deletions webmcp/imperative/executeTool-invalid-dictionary.https.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
await promise_rejects_js(
t,
TypeError,
document.modelContext.executeTool(invalidTool, '{}'),
document.modelContext.executeTool(invalidTool),
"executeTool() must reject with TypeError if 'origin' member is omitted"
);
}, "executeTool() rejects with TypeError when the required 'origin' dictionary member is omitted");
Expand All @@ -47,13 +47,32 @@
const tool = tools.find(t => t.name === "json-test-tool");
assert_true(!!tool, "Legitimate tool must be successfully discovered");

await promise_rejects_dom(
const circularObject = {};
circularObject.self = circularObject;
await promise_rejects_js(
t,
"UnknownError",
document.modelContext.executeTool(tool, "invalid-json"),
"executeTool() must reject with UnknownError for invalid JSON input"
TypeError,
document.modelContext.executeTool(tool, circularObject),
"executeTool() must reject with TypeError for circular JSON input"
);

const undefinedToJSON = {
toJSON: () => undefined
};
await promise_rejects_js(
t,
TypeError,
document.modelContext.executeTool(tool, undefinedToJSON),
"executeTool() must reject with TypeError when toJSON returns undefined"
);

await promise_rejects_js(
t,
TypeError,
document.modelContext.executeTool(tool, BigInt(42)),
"executeTool() must reject with TypeError for non-serializable types JSON input"
);
}, "executeTool() rejects with UnknownError for invalid JSON arguments");
}, "executeTool() rejects with TypeError for invalid JSON arguments");

promise_test(async t => {
const dummyTool = {
Expand All @@ -66,7 +85,7 @@
await promise_rejects_dom(
t,
"UnknownError",
document.modelContext.executeTool(dummyTool, "{}"),
document.modelContext.executeTool(dummyTool),
"executeTool() must reject with UnknownError for non-existent tool object"
);
}, "executeTool() rejects with UnknownError when a non-existent tool object is supplied");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
t.add_cleanup(() => window.removeEventListener('message', message_handler));

const controller = new AbortController();
const execute_promise = document.modelContext.executeTool(tool, '{}', { signal: controller.signal });
const execute_promise = document.modelContext.executeTool(tool, {}, { signal: controller.signal });

await tool_started;
controller.abort('parent cross-origin abort reason');
Expand Down
4 changes: 2 additions & 2 deletions webmcp/imperative/executeTool-target-detachment.https.html
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
await promise_rejects_dom(
t,
'InvalidStateError',
document.modelContext.executeTool(tool, '{}'),
document.modelContext.executeTool(tool),
'Promise should be rejected with InvalidStateError when target frame is detached before execution'
);
}, 'executeTool() rejects when target frame is detached before execution');
Expand Down Expand Up @@ -95,7 +95,7 @@
assert_true(!!tool, 'Tool should be retrieved successfully');

// Execute the tool (hangs forever).
const execute_promise = document.modelContext.executeTool(tool, '{}');
const execute_promise = document.modelContext.executeTool(tool);

iframe.remove();

Expand Down
2 changes: 1 addition & 1 deletion webmcp/imperative/executeTool-target-navigation.https.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
// Invoke tool and immediately navigate iframe away.
const tools = await document.modelContext.getTools();
const tool = tools.find(t => t.name === 'iframe_tool');
const promise = document.modelContext.executeTool(tool, '{}');
const promise = document.modelContext.executeTool(tool);
iframe.src = 'about:blank';

// The promise should be rejected because the target document died.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
};

// Parent attempts to execute the unexposed tool directly. This should reject with UnknownError.
const promise = document.modelContext.executeTool(fake_tool, '{}');
const promise = document.modelContext.executeTool(fake_tool);
await promise_rejects_dom(t, 'UnknownError', promise, 'executeTool should reject with UnknownError when parent is not authorized to execute the iframe tool');
}, 'executeTool() rejects when parent frame attempts unauthorized execution of cross-origin iframe tool');
</script>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
}, {signal: ac.signal});

const [tool] = await document.modelContext.getTools();
const execute_promise = document.modelContext.executeTool(tool, '{}');
const execute_promise = document.modelContext.executeTool(tool);

const result = await execute_promise;
assert_equals(result, '{"status":"resolved"}');
Expand Down
2 changes: 1 addition & 1 deletion webmcp/imperative/exposedTo-cross-origin-child.https.html
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@
}), 'Tool details should match');

// Parent executes iframe's tool.
const result = await document.modelContext.executeTool(tool, '{}');
const result = await document.modelContext.executeTool(tool);
assert_equals(result, 'hello from iframe', 'Parent should get correct result from iframe tool');

// Tell the iframe to unregister its tool, and confirm that `toolchange` fires here.
Expand Down
4 changes: 2 additions & 2 deletions webmcp/imperative/exposedTo-defaults-same-origin.https.html
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@
}), 'Tool details should match');

// Parent executes iframe's tool.
const result = await document.modelContext.executeTool(tool, '{}');
const result = await document.modelContext.executeTool(tool);
assert_equals(result, 'hello from iframe', 'Parent should get correct result from iframe tool');

// Unregister tool.
Expand Down Expand Up @@ -182,7 +182,7 @@
}), 'Tool details should match');

// Parent executes iframe's tool.
const result = await document.modelContext.executeTool(tool, '{}');
const result = await document.modelContext.executeTool(tool);
assert_equals(result, 'hello from iframe', 'Parent should get correct result from iframe tool');

// Unregister tool.
Expand Down
2 changes: 1 addition & 1 deletion webmcp/imperative/exposedTo-invalid-origins.https.html
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@

// 6. Execute the cached RegisteredTool.
// This must execute callback2 and resolve to 'callback2', not callback3.
const result = await document.modelContext.executeTool(tool, '{}');
const result = await document.modelContext.executeTool(tool);
assert_equals(result, 'callback2', 'Executing the cached RegisteredTool must run callback2');
}, 'Aborting a signal from a rejected registration must not unregister a later valid tool with the same name');
</script>
Expand Down
Loading