зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1265719 - Decouple the CanvasFront and FrameSnapshotFront from the CanvasActor and FrameSnapshotActor respectively; r=ejpbruel
This commit is contained in:
Родитель
644e1b42f8
Коммит
de3a8e2566
|
@ -13,7 +13,7 @@ const promise = require("promise");
|
|||
const Services = require("Services");
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const { CallWatcherFront } = require("devtools/shared/fronts/call-watcher");
|
||||
const { CanvasFront } = require("devtools/server/actors/canvas");
|
||||
const { CanvasFront } = require("devtools/shared/fronts/canvas");
|
||||
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
||||
const { LocalizationHelper } = require("devtools/client/shared/l10n");
|
||||
const { Heritage, WidgetMethods, setNamedTimeout, clearNamedTimeout,
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
const { Cc, Ci, Cu, Cr } = require("chrome");
|
||||
const promise = require("promise");
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const { CanvasFront } = require("devtools/server/actors/canvas");
|
||||
const { CanvasFront } = require("devtools/shared/fronts/canvas");
|
||||
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
||||
|
||||
function CanvasDebuggerPanel(iframeWindow, toolbox) {
|
||||
|
|
|
@ -13,7 +13,7 @@ var { gDevTools } = require("devtools/client/framework/devtools");
|
|||
var { DebuggerClient } = require("devtools/shared/client/main");
|
||||
var { DebuggerServer } = require("devtools/server/main");
|
||||
var { CallWatcherFront } = require("devtools/shared/fronts/call-watcher");
|
||||
var { CanvasFront } = require("devtools/server/actors/canvas");
|
||||
var { CanvasFront } = require("devtools/shared/fronts/canvas");
|
||||
var { setTimeout } = require("sdk/timers");
|
||||
var DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
||||
var { TargetFactory } = require("devtools/client/framework/target");
|
||||
|
|
|
@ -11,98 +11,26 @@ const {CallWatcherActor} = require("devtools/server/actors/call-watcher");
|
|||
const {CallWatcherFront} = require("devtools/shared/fronts/call-watcher");
|
||||
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
||||
const {WebGLPrimitiveCounter} = require("devtools/server/primitive");
|
||||
const {
|
||||
frameSnapshotSpec,
|
||||
canvasSpec,
|
||||
CANVAS_CONTEXTS,
|
||||
ANIMATION_GENERATORS,
|
||||
LOOP_GENERATORS,
|
||||
DRAW_CALLS,
|
||||
INTERESTING_CALLS,
|
||||
} = require("devtools/shared/specs/canvas");
|
||||
const {CanvasFront} = require("devtools/shared/fronts/canvas");
|
||||
|
||||
const {on, once, off, emit} = events;
|
||||
const {method, custom, Arg, Option, RetVal} = protocol;
|
||||
|
||||
const CANVAS_CONTEXTS = [
|
||||
"CanvasRenderingContext2D",
|
||||
"WebGLRenderingContext"
|
||||
];
|
||||
|
||||
const ANIMATION_GENERATORS = [
|
||||
"requestAnimationFrame"
|
||||
];
|
||||
|
||||
const LOOP_GENERATORS = [
|
||||
"setTimeout"
|
||||
];
|
||||
|
||||
const DRAW_CALLS = [
|
||||
// 2D canvas
|
||||
"fill",
|
||||
"stroke",
|
||||
"clearRect",
|
||||
"fillRect",
|
||||
"strokeRect",
|
||||
"fillText",
|
||||
"strokeText",
|
||||
"drawImage",
|
||||
|
||||
// WebGL
|
||||
"clear",
|
||||
"drawArrays",
|
||||
"drawElements",
|
||||
"finish",
|
||||
"flush"
|
||||
];
|
||||
|
||||
const INTERESTING_CALLS = [
|
||||
// 2D canvas
|
||||
"save",
|
||||
"restore",
|
||||
|
||||
// WebGL
|
||||
"useProgram"
|
||||
];
|
||||
|
||||
/**
|
||||
* Type representing an ArrayBufferView, serialized fast(er).
|
||||
*
|
||||
* Don't create a new array buffer view from the parsed array on the frontend.
|
||||
* Consumers may copy the data into an existing buffer, or create a new one if
|
||||
* necesasry. For example, this avoids the need for a redundant copy when
|
||||
* populating ImageData objects, at the expense of transferring char views
|
||||
* of a pixel buffer over the protocol instead of a packed int view.
|
||||
*
|
||||
* XXX: It would be nice if on local connections (only), we could just *give*
|
||||
* the buffer directly to the front, instead of going through all this
|
||||
* serialization redundancy.
|
||||
*/
|
||||
protocol.types.addType("array-buffer-view", {
|
||||
write: (v) => "[" + Array.join(v, ",") + "]",
|
||||
read: (v) => JSON.parse(v)
|
||||
});
|
||||
|
||||
/**
|
||||
* Type describing a thumbnail or screenshot in a recorded animation frame.
|
||||
*/
|
||||
protocol.types.addDictType("snapshot-image", {
|
||||
index: "number",
|
||||
width: "number",
|
||||
height: "number",
|
||||
scaling: "number",
|
||||
flipped: "boolean",
|
||||
pixels: "array-buffer-view"
|
||||
});
|
||||
|
||||
/**
|
||||
* Type describing an overview of a recorded animation frame.
|
||||
*/
|
||||
protocol.types.addDictType("snapshot-overview", {
|
||||
calls: "array:function-call",
|
||||
thumbnails: "array:snapshot-image",
|
||||
screenshot: "snapshot-image"
|
||||
});
|
||||
|
||||
/**
|
||||
* This actor represents a recorded animation frame snapshot, along with
|
||||
* all the corresponding canvas' context methods invoked in that frame,
|
||||
* thumbnails for each draw call and a screenshot of the end result.
|
||||
*/
|
||||
var FrameSnapshotActor = protocol.ActorClass({
|
||||
typeName: "frame-snapshot",
|
||||
|
||||
var FrameSnapshotActor = protocol.ActorClassWithSpec(frameSnapshotSpec, {
|
||||
/**
|
||||
* Creates the frame snapshot call actor.
|
||||
*
|
||||
|
@ -126,7 +54,7 @@ var FrameSnapshotActor = protocol.ActorClass({
|
|||
/**
|
||||
* Gets as much data about this snapshot without computing anything costly.
|
||||
*/
|
||||
getOverview: method(function () {
|
||||
getOverview: function () {
|
||||
return {
|
||||
calls: this._functionCalls,
|
||||
thumbnails: this._functionCalls.map(e => e._thumbnail).filter(e => !!e),
|
||||
|
@ -138,15 +66,13 @@ var FrameSnapshotActor = protocol.ActorClass({
|
|||
lines: this._primitive.lines
|
||||
}
|
||||
};
|
||||
}, {
|
||||
response: { overview: RetVal("snapshot-overview") }
|
||||
}),
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets a screenshot of the canvas's contents after the specified
|
||||
* function was called.
|
||||
*/
|
||||
generateScreenshotFor: method(function (functionCall) {
|
||||
generateScreenshotFor: function (functionCall) {
|
||||
let caller = functionCall.details.caller;
|
||||
let global = functionCall.details.global;
|
||||
|
||||
|
@ -186,54 +112,7 @@ var FrameSnapshotActor = protocol.ActorClass({
|
|||
screenshot.scaling = replayContextScaling;
|
||||
screenshot.index = lastDrawCallIndex;
|
||||
return screenshot;
|
||||
}, {
|
||||
request: { call: Arg(0, "function-call") },
|
||||
response: { screenshot: RetVal("snapshot-image") }
|
||||
})
|
||||
});
|
||||
|
||||
/**
|
||||
* The corresponding Front object for the FrameSnapshotActor.
|
||||
*/
|
||||
var FrameSnapshotFront = protocol.FrontClass(FrameSnapshotActor, {
|
||||
initialize: function (client, form) {
|
||||
protocol.Front.prototype.initialize.call(this, client, form);
|
||||
this._animationFrameEndScreenshot = null;
|
||||
this._cachedScreenshots = new WeakMap();
|
||||
},
|
||||
|
||||
/**
|
||||
* This implementation caches the animation frame end screenshot to optimize
|
||||
* frontend requests to `generateScreenshotFor`.
|
||||
*/
|
||||
getOverview: custom(function () {
|
||||
return this._getOverview().then(data => {
|
||||
this._animationFrameEndScreenshot = data.screenshot;
|
||||
return data;
|
||||
});
|
||||
}, {
|
||||
impl: "_getOverview"
|
||||
}),
|
||||
|
||||
/**
|
||||
* This implementation saves a roundtrip to the backend if the screenshot
|
||||
* was already generated and retrieved once.
|
||||
*/
|
||||
generateScreenshotFor: custom(function (functionCall) {
|
||||
if (CanvasFront.ANIMATION_GENERATORS.has(functionCall.name) ||
|
||||
CanvasFront.LOOP_GENERATORS.has(functionCall.name)) {
|
||||
return promise.resolve(this._animationFrameEndScreenshot);
|
||||
}
|
||||
let cachedScreenshot = this._cachedScreenshots.get(functionCall);
|
||||
if (cachedScreenshot) {
|
||||
return cachedScreenshot;
|
||||
}
|
||||
let screenshot = this._generateScreenshotFor(functionCall);
|
||||
this._cachedScreenshots.set(functionCall, screenshot);
|
||||
return screenshot;
|
||||
}, {
|
||||
impl: "_generateScreenshotFor"
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
|
@ -241,12 +120,11 @@ var FrameSnapshotFront = protocol.FrontClass(FrameSnapshotActor, {
|
|||
* of a 2D or WebGL context, to provide information regarding all the calls
|
||||
* made when drawing frame inside an animation loop.
|
||||
*/
|
||||
var CanvasActor = exports.CanvasActor = protocol.ActorClass({
|
||||
var CanvasActor = exports.CanvasActor = protocol.ActorClassWithSpec(canvasSpec, {
|
||||
// Reset for each recording, boolean indicating whether or not
|
||||
// any draw calls were called for a recording.
|
||||
_animationContainsDrawCall: false,
|
||||
|
||||
typeName: "canvas",
|
||||
initialize: function (conn, tabActor) {
|
||||
protocol.Actor.prototype.initialize.call(this, conn);
|
||||
this.tabActor = tabActor;
|
||||
|
@ -262,7 +140,7 @@ var CanvasActor = exports.CanvasActor = protocol.ActorClass({
|
|||
/**
|
||||
* Starts listening for function calls.
|
||||
*/
|
||||
setup: method(function ({ reload }) {
|
||||
setup: function ({ reload }) {
|
||||
if (this._initialized) {
|
||||
return;
|
||||
}
|
||||
|
@ -276,15 +154,12 @@ var CanvasActor = exports.CanvasActor = protocol.ActorClass({
|
|||
performReload: reload,
|
||||
storeCalls: true
|
||||
});
|
||||
}, {
|
||||
request: { reload: Option(0, "boolean") },
|
||||
oneway: true
|
||||
}),
|
||||
},
|
||||
|
||||
/**
|
||||
* Stops listening for function calls.
|
||||
*/
|
||||
finalize: method(function () {
|
||||
finalize: function () {
|
||||
if (!this._initialized) {
|
||||
return;
|
||||
}
|
||||
|
@ -292,35 +167,29 @@ var CanvasActor = exports.CanvasActor = protocol.ActorClass({
|
|||
|
||||
this._callWatcher.finalize();
|
||||
this._callWatcher = null;
|
||||
}, {
|
||||
oneway: true
|
||||
}),
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns whether this actor has been set up.
|
||||
*/
|
||||
isInitialized: method(function () {
|
||||
isInitialized: function () {
|
||||
return !!this._initialized;
|
||||
}, {
|
||||
response: { initialized: RetVal("boolean") }
|
||||
}),
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns whether or not the CanvasActor is recording an animation.
|
||||
* Used in tests.
|
||||
*/
|
||||
isRecording: method(function () {
|
||||
isRecording: function () {
|
||||
return !!this._callWatcher.isRecording();
|
||||
}, {
|
||||
response: { recording: RetVal("boolean") }
|
||||
}),
|
||||
},
|
||||
|
||||
/**
|
||||
* Records a snapshot of all the calls made during the next animation frame.
|
||||
* The animation should be implemented via the de-facto requestAnimationFrame
|
||||
* utility, or inside recursive `setTimeout`s. `setInterval` at this time are not supported.
|
||||
*/
|
||||
recordAnimationFrame: method(function () {
|
||||
recordAnimationFrame: function () {
|
||||
if (this._callWatcher.isRecording()) {
|
||||
return this._currentAnimationFrameSnapshot.promise;
|
||||
}
|
||||
|
@ -333,14 +202,12 @@ var CanvasActor = exports.CanvasActor = protocol.ActorClass({
|
|||
|
||||
let deferred = this._currentAnimationFrameSnapshot = promise.defer();
|
||||
return deferred.promise;
|
||||
}, {
|
||||
response: { snapshot: RetVal("nullable:frame-snapshot") }
|
||||
}),
|
||||
},
|
||||
|
||||
/**
|
||||
* Cease attempts to record an animation frame.
|
||||
*/
|
||||
stopRecordingAnimationFrame: method(function () {
|
||||
stopRecordingAnimationFrame: function () {
|
||||
if (!this._callWatcher.isRecording()) {
|
||||
return;
|
||||
}
|
||||
|
@ -349,9 +216,7 @@ var CanvasActor = exports.CanvasActor = protocol.ActorClass({
|
|||
this._callWatcher.eraseRecording();
|
||||
this._currentAnimationFrameSnapshot.resolve(null);
|
||||
this._currentAnimationFrameSnapshot = null;
|
||||
}, {
|
||||
oneway: true
|
||||
}),
|
||||
},
|
||||
|
||||
/**
|
||||
* Invoked whenever an instrumented function is called, be it on a
|
||||
|
@ -842,33 +707,6 @@ var ContextUtils = {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The corresponding Front object for the CanvasActor.
|
||||
*/
|
||||
var CanvasFront = exports.CanvasFront = protocol.FrontClass(CanvasActor, {
|
||||
initialize: function (client, { canvasActor }) {
|
||||
protocol.Front.prototype.initialize.call(this, client, { actor: canvasActor });
|
||||
this.manage(this);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Constants.
|
||||
*/
|
||||
CanvasFront.CANVAS_CONTEXTS = new Set(CANVAS_CONTEXTS);
|
||||
CanvasFront.ANIMATION_GENERATORS = new Set(ANIMATION_GENERATORS);
|
||||
CanvasFront.LOOP_GENERATORS = new Set(LOOP_GENERATORS);
|
||||
CanvasFront.DRAW_CALLS = new Set(DRAW_CALLS);
|
||||
CanvasFront.INTERESTING_CALLS = new Set(INTERESTING_CALLS);
|
||||
CanvasFront.THUMBNAIL_SIZE = 50; // px
|
||||
CanvasFront.WEBGL_SCREENSHOT_MAX_HEIGHT = 256; // px
|
||||
CanvasFront.INVALID_SNAPSHOT_IMAGE = {
|
||||
index: -1,
|
||||
width: 0,
|
||||
height: 0,
|
||||
pixels: []
|
||||
};
|
||||
|
||||
/**
|
||||
* Goes through all the arguments and creates a one-level shallow copy
|
||||
* of all arrays and array buffers.
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const {
|
||||
frameSnapshotSpec,
|
||||
canvasSpec,
|
||||
CANVAS_CONTEXTS,
|
||||
ANIMATION_GENERATORS,
|
||||
LOOP_GENERATORS,
|
||||
DRAW_CALLS,
|
||||
INTERESTING_CALLS,
|
||||
} = require("devtools/shared/specs/canvas");
|
||||
const protocol = require("devtools/shared/protocol");
|
||||
const promise = require("promise");
|
||||
|
||||
/**
|
||||
* The corresponding Front object for the FrameSnapshotActor.
|
||||
*/
|
||||
const FrameSnapshotFront = protocol.FrontClassWithSpec(frameSnapshotSpec, {
|
||||
initialize: function (client, form) {
|
||||
protocol.Front.prototype.initialize.call(this, client, form);
|
||||
this._animationFrameEndScreenshot = null;
|
||||
this._cachedScreenshots = new WeakMap();
|
||||
},
|
||||
|
||||
/**
|
||||
* This implementation caches the animation frame end screenshot to optimize
|
||||
* frontend requests to `generateScreenshotFor`.
|
||||
*/
|
||||
getOverview: protocol.custom(function () {
|
||||
return this._getOverview().then(data => {
|
||||
this._animationFrameEndScreenshot = data.screenshot;
|
||||
return data;
|
||||
});
|
||||
}, {
|
||||
impl: "_getOverview"
|
||||
}),
|
||||
|
||||
/**
|
||||
* This implementation saves a roundtrip to the backend if the screenshot
|
||||
* was already generated and retrieved once.
|
||||
*/
|
||||
generateScreenshotFor: protocol.custom(function (functionCall) {
|
||||
if (CanvasFront.ANIMATION_GENERATORS.has(functionCall.name) ||
|
||||
CanvasFront.LOOP_GENERATORS.has(functionCall.name)) {
|
||||
return promise.resolve(this._animationFrameEndScreenshot);
|
||||
}
|
||||
let cachedScreenshot = this._cachedScreenshots.get(functionCall);
|
||||
if (cachedScreenshot) {
|
||||
return cachedScreenshot;
|
||||
}
|
||||
let screenshot = this._generateScreenshotFor(functionCall);
|
||||
this._cachedScreenshots.set(functionCall, screenshot);
|
||||
return screenshot;
|
||||
}, {
|
||||
impl: "_generateScreenshotFor"
|
||||
})
|
||||
});
|
||||
|
||||
exports.FrameSnapshotFront = FrameSnapshotFront;
|
||||
|
||||
/**
|
||||
* The corresponding Front object for the CanvasActor.
|
||||
*/
|
||||
const CanvasFront = protocol.FrontClassWithSpec(canvasSpec, {
|
||||
initialize: function (client, { canvasActor }) {
|
||||
protocol.Front.prototype.initialize.call(this, client, { actor: canvasActor });
|
||||
this.manage(this);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Constants.
|
||||
*/
|
||||
CanvasFront.CANVAS_CONTEXTS = new Set(CANVAS_CONTEXTS);
|
||||
CanvasFront.ANIMATION_GENERATORS = new Set(ANIMATION_GENERATORS);
|
||||
CanvasFront.LOOP_GENERATORS = new Set(LOOP_GENERATORS);
|
||||
CanvasFront.DRAW_CALLS = new Set(DRAW_CALLS);
|
||||
CanvasFront.INTERESTING_CALLS = new Set(INTERESTING_CALLS);
|
||||
CanvasFront.THUMBNAIL_SIZE = 50;
|
||||
CanvasFront.WEBGL_SCREENSHOT_MAX_HEIGHT = 256;
|
||||
CanvasFront.INVALID_SNAPSHOT_IMAGE = {
|
||||
index: -1,
|
||||
width: 0,
|
||||
height: 0,
|
||||
pixels: []
|
||||
};
|
||||
|
||||
exports.CanvasFront = CanvasFront;
|
|
@ -9,6 +9,7 @@ DevToolsModules(
|
|||
'addons.js',
|
||||
'animation.js',
|
||||
'call-watcher.js',
|
||||
'canvas.js',
|
||||
'css-properties.js',
|
||||
'highlighters.js',
|
||||
'inspector.js',
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const protocol = require("devtools/shared/protocol");
|
||||
const {Arg, Option, RetVal, generateActorSpec} = protocol;
|
||||
|
||||
/**
|
||||
* Type representing an ArrayBufferView, serialized fast(er).
|
||||
*
|
||||
* Don't create a new array buffer view from the parsed array on the frontend.
|
||||
* Consumers may copy the data into an existing buffer, or create a new one if
|
||||
* necesasry. For example, this avoids the need for a redundant copy when
|
||||
* populating ImageData objects, at the expense of transferring char views
|
||||
* of a pixel buffer over the protocol instead of a packed int view.
|
||||
*
|
||||
* XXX: It would be nice if on local connections (only), we could just *give*
|
||||
* the buffer directly to the front, instead of going through all this
|
||||
* serialization redundancy.
|
||||
*/
|
||||
protocol.types.addType("array-buffer-view", {
|
||||
write: (v) => "[" + Array.join(v, ",") + "]",
|
||||
read: (v) => JSON.parse(v)
|
||||
});
|
||||
|
||||
/**
|
||||
* Type describing a thumbnail or screenshot in a recorded animation frame.
|
||||
*/
|
||||
protocol.types.addDictType("snapshot-image", {
|
||||
index: "number",
|
||||
width: "number",
|
||||
height: "number",
|
||||
scaling: "number",
|
||||
flipped: "boolean",
|
||||
pixels: "array-buffer-view"
|
||||
});
|
||||
|
||||
/**
|
||||
* Type describing an overview of a recorded animation frame.
|
||||
*/
|
||||
protocol.types.addDictType("snapshot-overview", {
|
||||
calls: "array:function-call",
|
||||
thumbnails: "array:snapshot-image",
|
||||
screenshot: "snapshot-image"
|
||||
});
|
||||
|
||||
exports.CANVAS_CONTEXTS = [
|
||||
"CanvasRenderingContext2D",
|
||||
"WebGLRenderingContext"
|
||||
];
|
||||
|
||||
exports.ANIMATION_GENERATORS = [
|
||||
"requestAnimationFrame"
|
||||
];
|
||||
|
||||
exports.LOOP_GENERATORS = [
|
||||
"setTimeout"
|
||||
];
|
||||
|
||||
exports.DRAW_CALLS = [
|
||||
// 2D canvas
|
||||
"fill",
|
||||
"stroke",
|
||||
"clearRect",
|
||||
"fillRect",
|
||||
"strokeRect",
|
||||
"fillText",
|
||||
"strokeText",
|
||||
"drawImage",
|
||||
|
||||
// WebGL
|
||||
"clear",
|
||||
"drawArrays",
|
||||
"drawElements",
|
||||
"finish",
|
||||
"flush"
|
||||
];
|
||||
|
||||
exports.INTERESTING_CALLS = [
|
||||
// 2D canvas
|
||||
"save",
|
||||
"restore",
|
||||
|
||||
// WebGL
|
||||
"useProgram"
|
||||
];
|
||||
|
||||
const frameSnapshotSpec = generateActorSpec({
|
||||
typeName: "frame-snapshot",
|
||||
|
||||
methods: {
|
||||
getOverview: {
|
||||
response: { overview: RetVal("snapshot-overview") }
|
||||
},
|
||||
generateScreenshotFor: {
|
||||
request: { call: Arg(0, "function-call") },
|
||||
response: { screenshot: RetVal("snapshot-image") }
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
exports.frameSnapshotSpec = frameSnapshotSpec;
|
||||
|
||||
const canvasSpec = generateActorSpec({
|
||||
typeName: "canvas",
|
||||
|
||||
methods: {
|
||||
setup: {
|
||||
request: { reload: Option(0, "boolean") },
|
||||
oneway: true
|
||||
},
|
||||
finalize: {
|
||||
oneway: true
|
||||
},
|
||||
isInitialized: {
|
||||
response: { initialized: RetVal("boolean") }
|
||||
},
|
||||
isRecording: {
|
||||
response: { recording: RetVal("boolean") }
|
||||
},
|
||||
recordAnimationFrame: {
|
||||
response: { snapshot: RetVal("nullable:frame-snapshot") }
|
||||
},
|
||||
stopRecordingAnimationFrame: {
|
||||
oneway: true
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
exports.canvasSpec = canvasSpec;
|
|
@ -9,6 +9,7 @@ DevToolsModules(
|
|||
'addons.js',
|
||||
'animation.js',
|
||||
'call-watcher.js',
|
||||
'canvas.js',
|
||||
'css-properties.js',
|
||||
'heap-snapshot-file.js',
|
||||
'highlighters.js',
|
||||
|
|
Загрузка…
Ссылка в новой задаче