зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1265722 - Decouple WalkerFront from WalkerActor;r=jryans
This commit is contained in:
Родитель
7f3fbd2eac
Коммит
c6ba11793c
|
@ -10,15 +10,19 @@ const {
|
|||
Front,
|
||||
FrontClassWithSpec,
|
||||
custom,
|
||||
preEvent,
|
||||
types
|
||||
} = require("devtools/shared/protocol.js");
|
||||
const { makeInfallible } = require("devtools/shared/DevToolsUtils");
|
||||
const {
|
||||
nodeSpec,
|
||||
nodeListSpec
|
||||
nodeListSpec,
|
||||
walkerSpec
|
||||
} = require("devtools/shared/specs/inspector");
|
||||
const promise = require("promise");
|
||||
const { Task } = require("resource://gre/modules/Task.jsm");
|
||||
const { Class } = require("sdk/core/heritage");
|
||||
const events = require("sdk/event/core");
|
||||
const object = require("sdk/util/object");
|
||||
|
||||
const HIDDEN_CLASS = "__fx-devtools-hide-shortcut__";
|
||||
|
@ -472,3 +476,452 @@ const NodeListFront = FrontClassWithSpec(nodeListSpec, {
|
|||
});
|
||||
|
||||
exports.NodeListFront = NodeListFront;
|
||||
|
||||
/**
|
||||
* Client side of the DOM walker.
|
||||
*/
|
||||
const WalkerFront = FrontClassWithSpec(walkerSpec, {
|
||||
// Set to true if cleanup should be requested after every mutation list.
|
||||
autoCleanup: true,
|
||||
|
||||
/**
|
||||
* This is kept for backward-compatibility reasons with older remote target.
|
||||
* Targets previous to bug 916443
|
||||
*/
|
||||
pick: custom(function () {
|
||||
return this._pick().then(response => {
|
||||
return response.node;
|
||||
});
|
||||
}, {impl: "_pick"}),
|
||||
|
||||
initialize: function (client, form) {
|
||||
this._createRootNodePromise();
|
||||
Front.prototype.initialize.call(this, client, form);
|
||||
this._orphaned = new Set();
|
||||
this._retainedOrphans = new Set();
|
||||
},
|
||||
|
||||
destroy: function () {
|
||||
Front.prototype.destroy.call(this);
|
||||
},
|
||||
|
||||
// Update the object given a form representation off the wire.
|
||||
form: function (json) {
|
||||
this.actorID = json.actor;
|
||||
this.rootNode = types.getType("domnode").read(json.root, this);
|
||||
this._rootNodeDeferred.resolve(this.rootNode);
|
||||
// FF42+ the actor starts exposing traits
|
||||
this.traits = json.traits || {};
|
||||
},
|
||||
|
||||
/**
|
||||
* Clients can use walker.rootNode to get the current root node of the
|
||||
* walker, but during a reload the root node might be null. This
|
||||
* method returns a promise that will resolve to the root node when it is
|
||||
* set.
|
||||
*/
|
||||
getRootNode: function () {
|
||||
return this._rootNodeDeferred.promise;
|
||||
},
|
||||
|
||||
/**
|
||||
* Create the root node promise, triggering the "new-root" notification
|
||||
* on resolution.
|
||||
*/
|
||||
_createRootNodePromise: function () {
|
||||
this._rootNodeDeferred = promise.defer();
|
||||
this._rootNodeDeferred.promise.then(() => {
|
||||
events.emit(this, "new-root");
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* When reading an actor form off the wire, we want to hook it up to its
|
||||
* parent front. The protocol guarantees that the parent will be seen
|
||||
* by the client in either a previous or the current request.
|
||||
* So if we've already seen this parent return it, otherwise create
|
||||
* a bare-bones stand-in node. The stand-in node will be updated
|
||||
* with a real form by the end of the deserialization.
|
||||
*/
|
||||
ensureParentFront: function (id) {
|
||||
let front = this.get(id);
|
||||
if (front) {
|
||||
return front;
|
||||
}
|
||||
|
||||
return types.getType("domnode").read({ actor: id }, this, "standin");
|
||||
},
|
||||
|
||||
/**
|
||||
* See the documentation for WalkerActor.prototype.retainNode for
|
||||
* information on retained nodes.
|
||||
*
|
||||
* From the client's perspective, `retainNode` can fail if the node in
|
||||
* question is removed from the ownership tree before the `retainNode`
|
||||
* request reaches the server. This can only happen if the client has
|
||||
* asked the server to release nodes but hasn't gotten a response
|
||||
* yet: Either a `releaseNode` request or a `getMutations` with `cleanup`
|
||||
* set is outstanding.
|
||||
*
|
||||
* If either of those requests is outstanding AND releases the retained
|
||||
* node, this request will fail with noSuchActor, but the ownership tree
|
||||
* will stay in a consistent state.
|
||||
*
|
||||
* Because the protocol guarantees that requests will be processed and
|
||||
* responses received in the order they were sent, we get the right
|
||||
* semantics by setting our local retained flag on the node only AFTER
|
||||
* a SUCCESSFUL retainNode call.
|
||||
*/
|
||||
retainNode: custom(function (node) {
|
||||
return this._retainNode(node).then(() => {
|
||||
node.retained = true;
|
||||
});
|
||||
}, {
|
||||
impl: "_retainNode",
|
||||
}),
|
||||
|
||||
unretainNode: custom(function (node) {
|
||||
return this._unretainNode(node).then(() => {
|
||||
node.retained = false;
|
||||
if (this._retainedOrphans.has(node)) {
|
||||
this._retainedOrphans.delete(node);
|
||||
this._releaseFront(node);
|
||||
}
|
||||
});
|
||||
}, {
|
||||
impl: "_unretainNode"
|
||||
}),
|
||||
|
||||
releaseNode: custom(function (node, options = {}) {
|
||||
// NodeFront.destroy will destroy children in the ownership tree too,
|
||||
// mimicking what the server will do here.
|
||||
let actorID = node.actorID;
|
||||
this._releaseFront(node, !!options.force);
|
||||
return this._releaseNode({ actorID: actorID });
|
||||
}, {
|
||||
impl: "_releaseNode"
|
||||
}),
|
||||
|
||||
findInspectingNode: custom(function () {
|
||||
return this._findInspectingNode().then(response => {
|
||||
return response.node;
|
||||
});
|
||||
}, {
|
||||
impl: "_findInspectingNode"
|
||||
}),
|
||||
|
||||
querySelector: custom(function (queryNode, selector) {
|
||||
return this._querySelector(queryNode, selector).then(response => {
|
||||
return response.node;
|
||||
});
|
||||
}, {
|
||||
impl: "_querySelector"
|
||||
}),
|
||||
|
||||
getNodeActorFromObjectActor: custom(function (objectActorID) {
|
||||
return this._getNodeActorFromObjectActor(objectActorID).then(response => {
|
||||
return response ? response.node : null;
|
||||
});
|
||||
}, {
|
||||
impl: "_getNodeActorFromObjectActor"
|
||||
}),
|
||||
|
||||
getStyleSheetOwnerNode: custom(function (styleSheetActorID) {
|
||||
return this._getStyleSheetOwnerNode(styleSheetActorID).then(response => {
|
||||
return response ? response.node : null;
|
||||
});
|
||||
}, {
|
||||
impl: "_getStyleSheetOwnerNode"
|
||||
}),
|
||||
|
||||
getNodeFromActor: custom(function (actorID, path) {
|
||||
return this._getNodeFromActor(actorID, path).then(response => {
|
||||
return response ? response.node : null;
|
||||
});
|
||||
}, {
|
||||
impl: "_getNodeFromActor"
|
||||
}),
|
||||
|
||||
/*
|
||||
* Incrementally search the document for a given string.
|
||||
* For modern servers, results will be searched with using the WalkerActor
|
||||
* `search` function (includes tag names, attributes, and text contents).
|
||||
* Only 1 result is sent back, and calling the method again with the same
|
||||
* query will send the next result. When there are no more results to be sent
|
||||
* back, null is sent.
|
||||
* @param {String} query
|
||||
* @param {Object} options
|
||||
* - "reverse": search backwards
|
||||
* - "selectorOnly": treat input as a selector string (don't search text
|
||||
* tags, attributes, etc)
|
||||
*/
|
||||
search: custom(Task.async(function* (query, options = { }) {
|
||||
let nodeList;
|
||||
let searchType;
|
||||
let searchData = this.searchData = this.searchData || { };
|
||||
let selectorOnly = !!options.selectorOnly;
|
||||
|
||||
// Backwards compat. Use selector only search if the new
|
||||
// search functionality isn't implemented, or if the caller (tests)
|
||||
// want it.
|
||||
if (selectorOnly || !this.traits.textSearch) {
|
||||
searchType = "selector";
|
||||
if (this.traits.multiFrameQuerySelectorAll) {
|
||||
nodeList = yield this.multiFrameQuerySelectorAll(query);
|
||||
} else {
|
||||
nodeList = yield this.querySelectorAll(this.rootNode, query);
|
||||
}
|
||||
} else {
|
||||
searchType = "search";
|
||||
let result = yield this._search(query, options);
|
||||
nodeList = result.list;
|
||||
}
|
||||
|
||||
// If this is a new search, start at the beginning.
|
||||
if (searchData.query !== query ||
|
||||
searchData.selectorOnly !== selectorOnly) {
|
||||
searchData.selectorOnly = selectorOnly;
|
||||
searchData.query = query;
|
||||
searchData.index = -1;
|
||||
}
|
||||
|
||||
if (!nodeList.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Move search result cursor and cycle if necessary.
|
||||
searchData.index = options.reverse ? searchData.index - 1 :
|
||||
searchData.index + 1;
|
||||
if (searchData.index >= nodeList.length) {
|
||||
searchData.index = 0;
|
||||
}
|
||||
if (searchData.index < 0) {
|
||||
searchData.index = nodeList.length - 1;
|
||||
}
|
||||
|
||||
// Send back the single node, along with any relevant search data
|
||||
let node = yield nodeList.item(searchData.index);
|
||||
return {
|
||||
type: searchType,
|
||||
node: node,
|
||||
resultsLength: nodeList.length,
|
||||
resultsIndex: searchData.index,
|
||||
};
|
||||
}), {
|
||||
impl: "_search"
|
||||
}),
|
||||
|
||||
_releaseFront: function (node, force) {
|
||||
if (node.retained && !force) {
|
||||
node.reparent(null);
|
||||
this._retainedOrphans.add(node);
|
||||
return;
|
||||
}
|
||||
|
||||
if (node.retained) {
|
||||
// Forcing a removal.
|
||||
this._retainedOrphans.delete(node);
|
||||
}
|
||||
|
||||
// Release any children
|
||||
for (let child of node.treeChildren()) {
|
||||
this._releaseFront(child, force);
|
||||
}
|
||||
|
||||
// All children will have been removed from the node by this point.
|
||||
node.reparent(null);
|
||||
node.destroy();
|
||||
},
|
||||
|
||||
/**
|
||||
* Get any unprocessed mutation records and process them.
|
||||
*/
|
||||
getMutations: custom(function (options = {}) {
|
||||
return this._getMutations(options).then(mutations => {
|
||||
let emitMutations = [];
|
||||
for (let change of mutations) {
|
||||
// The target is only an actorID, get the associated front.
|
||||
let targetID;
|
||||
let targetFront;
|
||||
|
||||
if (change.type === "newRoot") {
|
||||
this.rootNode = types.getType("domnode").read(change.target, this);
|
||||
this._rootNodeDeferred.resolve(this.rootNode);
|
||||
targetID = this.rootNode.actorID;
|
||||
targetFront = this.rootNode;
|
||||
} else {
|
||||
targetID = change.target;
|
||||
targetFront = this.get(targetID);
|
||||
}
|
||||
|
||||
if (!targetFront) {
|
||||
console.trace("Got a mutation for an unexpected actor: " + targetID +
|
||||
", please file a bug on bugzilla.mozilla.org!");
|
||||
continue;
|
||||
}
|
||||
|
||||
let emittedMutation = object.merge(change, { target: targetFront });
|
||||
|
||||
if (change.type === "childList" ||
|
||||
change.type === "nativeAnonymousChildList") {
|
||||
// Update the ownership tree according to the mutation record.
|
||||
let addedFronts = [];
|
||||
let removedFronts = [];
|
||||
for (let removed of change.removed) {
|
||||
let removedFront = this.get(removed);
|
||||
if (!removedFront) {
|
||||
console.error("Got a removal of an actor we didn't know about: " +
|
||||
removed);
|
||||
continue;
|
||||
}
|
||||
// Remove from the ownership tree
|
||||
removedFront.reparent(null);
|
||||
|
||||
// This node is orphaned unless we get it in the 'added' list
|
||||
// eventually.
|
||||
this._orphaned.add(removedFront);
|
||||
removedFronts.push(removedFront);
|
||||
}
|
||||
for (let added of change.added) {
|
||||
let addedFront = this.get(added);
|
||||
if (!addedFront) {
|
||||
console.error("Got an addition of an actor we didn't know " +
|
||||
"about: " + added);
|
||||
continue;
|
||||
}
|
||||
addedFront.reparent(targetFront);
|
||||
|
||||
// The actor is reconnected to the ownership tree, unorphan
|
||||
// it.
|
||||
this._orphaned.delete(addedFront);
|
||||
addedFronts.push(addedFront);
|
||||
}
|
||||
|
||||
if (change.singleTextChild) {
|
||||
targetFront.singleTextChild =
|
||||
types.getType("domnode").read(change.singleTextChild, this);
|
||||
} else {
|
||||
targetFront.singleTextChild = undefined;
|
||||
}
|
||||
|
||||
// Before passing to users, replace the added and removed actor
|
||||
// ids with front in the mutation record.
|
||||
emittedMutation.added = addedFronts;
|
||||
emittedMutation.removed = removedFronts;
|
||||
|
||||
// If this is coming from a DOM mutation, the actor's numChildren
|
||||
// was passed in. Otherwise, it is simulated from a frame load or
|
||||
// unload, so don't change the front's form.
|
||||
if ("numChildren" in change) {
|
||||
targetFront._form.numChildren = change.numChildren;
|
||||
}
|
||||
} else if (change.type === "frameLoad") {
|
||||
// Nothing we need to do here, except verify that we don't have any
|
||||
// document children, because we should have gotten a documentUnload
|
||||
// first.
|
||||
for (let child of targetFront.treeChildren()) {
|
||||
if (child.nodeType === Ci.nsIDOMNode.DOCUMENT_NODE) {
|
||||
console.trace("Got an unexpected frameLoad in the inspector, " +
|
||||
"please file a bug on bugzilla.mozilla.org!");
|
||||
}
|
||||
}
|
||||
} else if (change.type === "documentUnload") {
|
||||
if (targetFront === this.rootNode) {
|
||||
this._createRootNodePromise();
|
||||
}
|
||||
|
||||
// We try to give fronts instead of actorIDs, but these fronts need
|
||||
// to be destroyed now.
|
||||
emittedMutation.target = targetFront.actorID;
|
||||
emittedMutation.targetParent = targetFront.parentNode();
|
||||
|
||||
// Release the document node and all of its children, even retained.
|
||||
this._releaseFront(targetFront, true);
|
||||
} else if (change.type === "unretained") {
|
||||
// Retained orphans were force-released without the intervention of
|
||||
// client (probably a navigated frame).
|
||||
for (let released of change.nodes) {
|
||||
let releasedFront = this.get(released);
|
||||
this._retainedOrphans.delete(released);
|
||||
this._releaseFront(releasedFront, true);
|
||||
}
|
||||
} else {
|
||||
targetFront.updateMutation(change);
|
||||
}
|
||||
|
||||
emitMutations.push(emittedMutation);
|
||||
}
|
||||
|
||||
if (options.cleanup) {
|
||||
for (let node of this._orphaned) {
|
||||
// This will move retained nodes to this._retainedOrphans.
|
||||
this._releaseFront(node);
|
||||
}
|
||||
this._orphaned = new Set();
|
||||
}
|
||||
|
||||
events.emit(this, "mutations", emitMutations);
|
||||
});
|
||||
}, {
|
||||
impl: "_getMutations"
|
||||
}),
|
||||
|
||||
/**
|
||||
* Handle the `new-mutations` notification by fetching the
|
||||
* available mutation records.
|
||||
*/
|
||||
onMutations: preEvent("new-mutations", function () {
|
||||
// Fetch and process the mutations.
|
||||
this.getMutations({cleanup: this.autoCleanup}).catch(() => {});
|
||||
}),
|
||||
|
||||
isLocal: function () {
|
||||
return !!this.conn._transport._serverConnection;
|
||||
},
|
||||
|
||||
// XXX hack during transition to remote inspector: get a proper NodeFront
|
||||
// for a given local node. Only works locally.
|
||||
frontForRawNode: function (rawNode) {
|
||||
if (!this.isLocal()) {
|
||||
console.warn("Tried to use frontForRawNode on a remote connection.");
|
||||
return null;
|
||||
}
|
||||
let walkerActor = this.conn._transport._serverConnection
|
||||
.getActor(this.actorID);
|
||||
if (!walkerActor) {
|
||||
throw Error("Could not find client side for actor " + this.actorID);
|
||||
}
|
||||
let nodeActor = walkerActor._ref(rawNode);
|
||||
|
||||
// Pass the node through a read/write pair to create the client side actor.
|
||||
let nodeType = types.getType("domnode");
|
||||
let returnNode = nodeType.read(
|
||||
nodeType.write(nodeActor, walkerActor), this);
|
||||
let top = returnNode;
|
||||
let extras = walkerActor.parents(nodeActor, {sameTypeRootTreeItem: true});
|
||||
for (let extraActor of extras) {
|
||||
top = nodeType.read(nodeType.write(extraActor, walkerActor), this);
|
||||
}
|
||||
|
||||
if (top !== this.rootNode) {
|
||||
// Imported an already-orphaned node.
|
||||
this._orphaned.add(top);
|
||||
walkerActor._orphaned
|
||||
.add(this.conn._transport._serverConnection.getActor(top.actorID));
|
||||
}
|
||||
return returnNode;
|
||||
},
|
||||
|
||||
removeNode: custom(Task.async(function* (node) {
|
||||
let previousSibling = yield this.previousSibling(node);
|
||||
let nextSibling = yield this._removeNode(node);
|
||||
return {
|
||||
previousSibling: previousSibling,
|
||||
nextSibling: nextSibling,
|
||||
};
|
||||
}), {
|
||||
impl: "_removeNode"
|
||||
}),
|
||||
});
|
||||
|
||||
exports.WalkerFront = WalkerFront;
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -5,6 +5,7 @@
|
|||
|
||||
const {
|
||||
Arg,
|
||||
Option,
|
||||
RetVal,
|
||||
generateActorSpec,
|
||||
types
|
||||
|
@ -118,3 +119,302 @@ const nodeListSpec = generateActorSpec({
|
|||
});
|
||||
|
||||
exports.nodeListSpec = nodeListSpec;
|
||||
|
||||
// Some common request/response templates for the dom walker
|
||||
|
||||
var nodeArrayMethod = {
|
||||
request: {
|
||||
node: Arg(0, "domnode"),
|
||||
maxNodes: Option(1),
|
||||
center: Option(1, "domnode"),
|
||||
start: Option(1, "domnode"),
|
||||
whatToShow: Option(1)
|
||||
},
|
||||
response: RetVal(types.addDictType("domtraversalarray", {
|
||||
nodes: "array:domnode"
|
||||
}))
|
||||
};
|
||||
|
||||
var traversalMethod = {
|
||||
request: {
|
||||
node: Arg(0, "domnode"),
|
||||
whatToShow: Option(1)
|
||||
},
|
||||
response: {
|
||||
node: RetVal("nullable:domnode")
|
||||
}
|
||||
};
|
||||
|
||||
const walkerSpec = generateActorSpec({
|
||||
typeName: "domwalker",
|
||||
|
||||
events: {
|
||||
"new-mutations": {
|
||||
type: "newMutations"
|
||||
},
|
||||
"picker-node-picked": {
|
||||
type: "pickerNodePicked",
|
||||
node: Arg(0, "disconnectedNode")
|
||||
},
|
||||
"picker-node-hovered": {
|
||||
type: "pickerNodeHovered",
|
||||
node: Arg(0, "disconnectedNode")
|
||||
},
|
||||
"picker-node-canceled": {
|
||||
type: "pickerNodeCanceled"
|
||||
},
|
||||
"highlighter-ready": {
|
||||
type: "highlighter-ready"
|
||||
},
|
||||
"highlighter-hide": {
|
||||
type: "highlighter-hide"
|
||||
},
|
||||
"display-change": {
|
||||
type: "display-change",
|
||||
nodes: Arg(0, "array:domnode")
|
||||
},
|
||||
// The walker actor emits a useful "resize" event to its front to let
|
||||
// clients know when the browser window gets resized. This may be useful
|
||||
// for refreshing a DOM node's styles for example, since those may depend on
|
||||
// media-queries.
|
||||
"resize": {
|
||||
type: "resize"
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
release: {
|
||||
release: true
|
||||
},
|
||||
pick: {
|
||||
request: {},
|
||||
response: RetVal("disconnectedNode")
|
||||
},
|
||||
cancelPick: {},
|
||||
highlight: {
|
||||
request: {node: Arg(0, "nullable:domnode")}
|
||||
},
|
||||
document: {
|
||||
request: { node: Arg(0, "nullable:domnode") },
|
||||
response: { node: RetVal("domnode") },
|
||||
},
|
||||
documentElement: {
|
||||
request: { node: Arg(0, "nullable:domnode") },
|
||||
response: { node: RetVal("domnode") },
|
||||
},
|
||||
parents: {
|
||||
request: {
|
||||
node: Arg(0, "domnode"),
|
||||
sameDocument: Option(1),
|
||||
sameTypeRootTreeItem: Option(1)
|
||||
},
|
||||
response: {
|
||||
nodes: RetVal("array:domnode")
|
||||
},
|
||||
},
|
||||
retainNode: {
|
||||
request: { node: Arg(0, "domnode") },
|
||||
response: {}
|
||||
},
|
||||
unretainNode: {
|
||||
request: { node: Arg(0, "domnode") },
|
||||
response: {},
|
||||
},
|
||||
releaseNode: {
|
||||
request: {
|
||||
node: Arg(0, "domnode"),
|
||||
force: Option(1)
|
||||
}
|
||||
},
|
||||
children: nodeArrayMethod,
|
||||
siblings: nodeArrayMethod,
|
||||
nextSibling: traversalMethod,
|
||||
previousSibling: traversalMethod,
|
||||
findInspectingNode: {
|
||||
request: {},
|
||||
response: RetVal("disconnectedNode")
|
||||
},
|
||||
querySelector: {
|
||||
request: {
|
||||
node: Arg(0, "domnode"),
|
||||
selector: Arg(1)
|
||||
},
|
||||
response: RetVal("disconnectedNode")
|
||||
},
|
||||
querySelectorAll: {
|
||||
request: {
|
||||
node: Arg(0, "domnode"),
|
||||
selector: Arg(1)
|
||||
},
|
||||
response: {
|
||||
list: RetVal("domnodelist")
|
||||
}
|
||||
},
|
||||
multiFrameQuerySelectorAll: {
|
||||
request: {
|
||||
selector: Arg(0)
|
||||
},
|
||||
response: {
|
||||
list: RetVal("domnodelist")
|
||||
}
|
||||
},
|
||||
search: {
|
||||
request: {
|
||||
query: Arg(0),
|
||||
},
|
||||
response: {
|
||||
list: RetVal("searchresult"),
|
||||
}
|
||||
},
|
||||
getSuggestionsForQuery: {
|
||||
request: {
|
||||
query: Arg(0),
|
||||
completing: Arg(1),
|
||||
selectorState: Arg(2)
|
||||
},
|
||||
response: {
|
||||
list: RetVal("array:array:string")
|
||||
}
|
||||
},
|
||||
addPseudoClassLock: {
|
||||
request: {
|
||||
node: Arg(0, "domnode"),
|
||||
pseudoClass: Arg(1),
|
||||
parents: Option(2)
|
||||
},
|
||||
response: {}
|
||||
},
|
||||
hideNode: {
|
||||
request: { node: Arg(0, "domnode") }
|
||||
},
|
||||
unhideNode: {
|
||||
request: { node: Arg(0, "domnode") }
|
||||
},
|
||||
removePseudoClassLock: {
|
||||
request: {
|
||||
node: Arg(0, "domnode"),
|
||||
pseudoClass: Arg(1),
|
||||
parents: Option(2)
|
||||
},
|
||||
response: {}
|
||||
},
|
||||
clearPseudoClassLocks: {
|
||||
request: {
|
||||
node: Arg(0, "nullable:domnode")
|
||||
},
|
||||
response: {}
|
||||
},
|
||||
innerHTML: {
|
||||
request: {
|
||||
node: Arg(0, "domnode")
|
||||
},
|
||||
response: {
|
||||
value: RetVal("longstring")
|
||||
}
|
||||
},
|
||||
setInnerHTML: {
|
||||
request: {
|
||||
node: Arg(0, "domnode"),
|
||||
value: Arg(1, "string"),
|
||||
},
|
||||
response: {}
|
||||
},
|
||||
outerHTML: {
|
||||
request: {
|
||||
node: Arg(0, "domnode")
|
||||
},
|
||||
response: {
|
||||
value: RetVal("longstring")
|
||||
}
|
||||
},
|
||||
setOuterHTML: {
|
||||
request: {
|
||||
node: Arg(0, "domnode"),
|
||||
value: Arg(1, "string"),
|
||||
},
|
||||
response: {}
|
||||
},
|
||||
insertAdjacentHTML: {
|
||||
request: {
|
||||
node: Arg(0, "domnode"),
|
||||
position: Arg(1, "string"),
|
||||
value: Arg(2, "string")
|
||||
},
|
||||
response: RetVal("disconnectedNodeArray")
|
||||
},
|
||||
duplicateNode: {
|
||||
request: {
|
||||
node: Arg(0, "domnode")
|
||||
},
|
||||
response: {}
|
||||
},
|
||||
removeNode: {
|
||||
request: {
|
||||
node: Arg(0, "domnode")
|
||||
},
|
||||
response: {
|
||||
nextSibling: RetVal("nullable:domnode")
|
||||
}
|
||||
},
|
||||
removeNodes: {
|
||||
request: {
|
||||
node: Arg(0, "array:domnode")
|
||||
},
|
||||
response: {}
|
||||
},
|
||||
insertBefore: {
|
||||
request: {
|
||||
node: Arg(0, "domnode"),
|
||||
parent: Arg(1, "domnode"),
|
||||
sibling: Arg(2, "nullable:domnode")
|
||||
},
|
||||
response: {}
|
||||
},
|
||||
editTagName: {
|
||||
request: {
|
||||
node: Arg(0, "domnode"),
|
||||
tagName: Arg(1, "string")
|
||||
},
|
||||
response: {}
|
||||
},
|
||||
getMutations: {
|
||||
request: {
|
||||
cleanup: Option(0)
|
||||
},
|
||||
response: {
|
||||
mutations: RetVal("array:dommutation")
|
||||
}
|
||||
},
|
||||
isInDOMTree: {
|
||||
request: { node: Arg(0, "domnode") },
|
||||
response: { attached: RetVal("boolean") }
|
||||
},
|
||||
getNodeActorFromObjectActor: {
|
||||
request: {
|
||||
objectActorID: Arg(0, "string")
|
||||
},
|
||||
response: {
|
||||
nodeFront: RetVal("nullable:disconnectedNode")
|
||||
}
|
||||
},
|
||||
getStyleSheetOwnerNode: {
|
||||
request: {
|
||||
styleSheetActorID: Arg(0, "string")
|
||||
},
|
||||
response: {
|
||||
ownerNode: RetVal("nullable:disconnectedNode")
|
||||
}
|
||||
},
|
||||
getNodeFromActor: {
|
||||
request: {
|
||||
actorID: Arg(0, "string"),
|
||||
path: Arg(1, "array:string")
|
||||
},
|
||||
response: {
|
||||
node: RetVal("nullable:disconnectedNode")
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
exports.walkerSpec = walkerSpec;
|
||||
|
|
Загрузка…
Ссылка в новой задаче