mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 14:52:16 +00:00
Bug 1549785 - Implement Runtime.releaseObject. r=remote-protocol-reviewers,ato
Differential Revision: https://phabricator.services.mozilla.com/D30231 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
f5799d4034
commit
768c21fdb9
@ -70,6 +70,20 @@ class Runtime extends ContentProcessDomain {
|
||||
return context.evaluate(request.expression);
|
||||
}
|
||||
|
||||
releaseObject({ objectId }) {
|
||||
let context = null;
|
||||
for (const ctx of this.contexts.values()) {
|
||||
if (ctx.hasRemoteObject(objectId)) {
|
||||
context = ctx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!context) {
|
||||
throw new Error(`Unable to get execution context by ID: ${objectId}`);
|
||||
}
|
||||
context.releaseObject(objectId);
|
||||
}
|
||||
|
||||
callFunctionOn(request) {
|
||||
let context = null;
|
||||
// When an `objectId` is passed, we want to execute the function of a given object
|
||||
|
@ -48,6 +48,10 @@ class ExecutionContext {
|
||||
return this._remoteObjects.has(id);
|
||||
}
|
||||
|
||||
releaseObject(id) {
|
||||
return this._remoteObjects.delete(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate a Javascript expression.
|
||||
*
|
||||
|
@ -11,6 +11,7 @@ skip-if = debug || asan # bug 1546945
|
||||
[browser_page_frameNavigated.js]
|
||||
[browser_page_runtime_events.js]
|
||||
[browser_runtime_evaluate.js]
|
||||
[browser_runtime_remote_objects.js]
|
||||
[browser_runtime_callFunctionOn.js]
|
||||
[browser_runtime_executionContext.js]
|
||||
skip-if = os == "mac" || (verify && os == 'win') # bug 1547961
|
||||
|
101
remote/test/browser/browser_runtime_remote_objects.js
Normal file
101
remote/test/browser/browser_runtime_remote_objects.js
Normal file
@ -0,0 +1,101 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test the Runtime remote object
|
||||
|
||||
const TEST_URI = "data:text/html;charset=utf-8,default-test-page";
|
||||
|
||||
add_task(async function() {
|
||||
// Open a test page, to prevent debugging the random default page
|
||||
await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URI);
|
||||
|
||||
// Start the CDP server
|
||||
await RemoteAgent.listen(Services.io.newURI("http://localhost:9222"));
|
||||
|
||||
// Retrieve the chrome-remote-interface library object
|
||||
const CDP = await getCDP();
|
||||
|
||||
// Connect to the server
|
||||
const client = await CDP({
|
||||
target(list) {
|
||||
// Ensure debugging the right target, i.e. the one for our test tab.
|
||||
return list.find(target => target.url == TEST_URI);
|
||||
},
|
||||
});
|
||||
ok(true, "CDP client has been instantiated");
|
||||
|
||||
const firstContext = await testRuntimeEnable(client);
|
||||
const contextId = firstContext.id;
|
||||
|
||||
await testObjectRelease(client, contextId);
|
||||
|
||||
await client.close();
|
||||
ok(true, "The client is closed");
|
||||
|
||||
BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
|
||||
await RemoteAgent.close();
|
||||
});
|
||||
|
||||
async function testRuntimeEnable({ Runtime }) {
|
||||
// Enable watching for new execution context
|
||||
await Runtime.enable();
|
||||
ok(true, "Runtime domain has been enabled");
|
||||
|
||||
// Calling Runtime.enable will emit executionContextCreated for the existing contexts
|
||||
const { context } = await Runtime.executionContextCreated();
|
||||
ok(!!context.id, "The execution context has an id");
|
||||
ok(context.auxData.isDefault, "The execution context is the default one");
|
||||
ok(!!context.auxData.frameId, "The execution context has a frame id set");
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
async function testObjectRelease({ Runtime }, contextId) {
|
||||
const { result } = await Runtime.evaluate({ contextId, expression: "({ foo: 42 })" });
|
||||
is(result.subtype, null, "JS Object have no subtype");
|
||||
is(result.type, "object", "The type is correct");
|
||||
ok(!!result.objectId, "Got an object id");
|
||||
|
||||
const { result: result2 } = await Runtime.callFunctionOn({
|
||||
executionContextId: contextId,
|
||||
functionDeclaration: "obj => JSON.stringify(obj)",
|
||||
arguments: [{ objectId: result.objectId }],
|
||||
});
|
||||
is(result2.type, "string", "The type is correct");
|
||||
is(result2.value, JSON.stringify({ foo: 42 }), "Got the object's JSON");
|
||||
|
||||
const { result: result3 } = await Runtime.callFunctionOn({
|
||||
objectId: result.objectId,
|
||||
functionDeclaration: "function () { return this.foo; }",
|
||||
});
|
||||
is(result3.type, "number", "The type is correct");
|
||||
is(result3.value, 42, "Got the object's foo attribute");
|
||||
|
||||
await Runtime.releaseObject({
|
||||
objectId: result.objectId,
|
||||
});
|
||||
ok(true, "Object is released");
|
||||
|
||||
try {
|
||||
await Runtime.callFunctionOn({
|
||||
executionContextId: contextId,
|
||||
functionDeclaration: "() => {}",
|
||||
arguments: [{ objectId: result.objectId }],
|
||||
});
|
||||
ok(false, "callFunctionOn with a released object as argument should throw");
|
||||
} catch (e) {
|
||||
ok(e.message.includes("Cannot find object with ID:"), "callFunctionOn throws on released argument");
|
||||
}
|
||||
try {
|
||||
await Runtime.callFunctionOn({
|
||||
objectId: result.objectId,
|
||||
functionDeclaration: "() => {}",
|
||||
});
|
||||
ok(false, "callFunctionOn with a released object as target should throw");
|
||||
} catch (e) {
|
||||
ok(e.message.includes("Unable to get the context for object with id"), "callFunctionOn throws on released target");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user