Changeset 225488 in webkit


Ignore:
Timestamp:
Dec 4, 2017 1:40:55 PM (6 years ago)
Author:
webkit@devinrousso.com
Message:

Web Inspector: provide method for recording CanvasRenderingContext2D from JavaScript
https://bugs.webkit.org/show_bug.cgi?id=175166
<rdar://problem/34040740>

Reviewed by Joseph Pecoraro.

Source/JavaScriptCore:

  • inspector/protocol/Recording.json:

Add optional name that will be used by the frontend for uniquely identifying the Recording.

  • inspector/JSGlobalObjectConsoleClient.h:
  • inspector/JSGlobalObjectConsoleClient.cpp:

(Inspector::JSGlobalObjectConsoleClient::record):
(Inspector::JSGlobalObjectConsoleClient::recordEnd):

  • runtime/ConsoleClient.h:
  • runtime/ConsoleObject.cpp:

(JSC::ConsoleObject::finishCreation):
(JSC::consoleProtoFuncRecord):
(JSC::consoleProtoFuncRecordEnd):

Source/WebCore:

No new tests, updated existing tests.

  • inspector/InspectorCanvas.h:
  • inspector/InspectorCanvas.cpp:

(WebCore::InspectorCanvas::resetRecordingData):

  • inspector/InspectorCanvasAgent.h:
  • inspector/InspectorCanvasAgent.cpp:

(WebCore::InspectorCanvasAgent::didFinishRecordingCanvasFrame):
(WebCore::InspectorCanvasAgent::consoleStartRecordingCanvas):

  • inspector/InspectorInstrumentation.h:
  • inspector/InspectorInstrumentation.cpp:

(WebCore::InspectorInstrumentation::consoleStartRecordingCanvas):
(WebCore::InspectorInstrumentation::consoleStartRecordingCanvasImpl):

  • page/PageConsoleClient.h:
  • page/PageConsoleClient.cpp:

(WebCore::PageConsoleClient::record):
(WebCore::PageConsoleClient::recordEnd):

  • workers/WorkerConsoleClient.h:
  • workers/WorkerConsoleClient.cpp:

(WebCore::WorkerConsoleClient::record):
(WebCore::WorkerConsoleClient::recordEnd):

Source/WebInspectorUI:

  • UserInterface/Controllers/CanvasManager.js:

(WI.CanvasManager.prototype.recordingFinished):
If a name is sent with the payload, use it as the suggested name.

  • UserInterface/Models/NativeFunctionParameters.js:

Add console.record and console.recordEnd.

  • UserInterface/Views/CanvasTabContentView.js:

(WI.CanvasTabContentView.prototype.showRepresentedObject):
Drive-by: remove logic that toggled the collapsed state of the navigation sidebar, as this
was not very controllable by the user and often was aggravating.

(WI.CanvasTabContentView.prototype._recordingStopped):
Only show the recording if it was not started from the console. This can determined by
CanvasManager when it recieves a recording if the recording's source is not the same as the
current canvas being recorded.

LayoutTests:

  • inspector/canvas/recording-2d-expected.txt:
  • inspector/canvas/recording-2d.html:

(performConsoleRecording):

  • inspector/canvas/recording-webgl-expected.txt:
  • inspector/canvas/recording-webgl.html:

(performConsoleRecording):

  • inspector/canvas/resources/recording-utilities.js:

(TestPage.registerInitializer):

  • js/console-expected.txt:
  • js/console.html:
Location:
trunk
Files:
30 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r225479 r225488  
     12017-12-04  Devin Rousso  <webkit@devinrousso.com>
     2
     3        Web Inspector: provide method for recording CanvasRenderingContext2D from JavaScript
     4        https://bugs.webkit.org/show_bug.cgi?id=175166
     5        <rdar://problem/34040740>
     6
     7        Reviewed by Joseph Pecoraro.
     8
     9        * inspector/canvas/recording-2d-expected.txt:
     10        * inspector/canvas/recording-2d.html:
     11        (performConsoleRecording):
     12        * inspector/canvas/recording-webgl-expected.txt:
     13        * inspector/canvas/recording-webgl.html:
     14        (performConsoleRecording):
     15        * inspector/canvas/resources/recording-utilities.js:
     16        (TestPage.registerInitializer):
     17        * js/console-expected.txt:
     18        * js/console.html:
     19
    1202017-12-04  Ms2ger  <Ms2ger@igalia.com>
    221
  • trunk/LayoutTests/inspector/canvas/recording-2d-expected.txt

    r224389 r225488  
    15231523  30: [29,10,122,108]
    15241524
     1525-- Running test case: Canvas.recording2D.Console
     1526PASS: The recording should have the name "TEST".
     1527PASS: The recording should have one frame.
     1528PASS: The first frame should have one action.
     1529
    15251530-- Running test case: Canvas.recording2D.ActionParameterNaN
    15261531PASS: The recording should have 1 frame.
  • trunk/LayoutTests/inspector/canvas/recording-2d.html

    r223998 r225488  
    396396}
    397397
     398function performConsoleActions() {
     399    console.record(ctx, {name: "TEST"});
     400
     401    ctx.fill();
     402
     403    console.recordEnd(ctx);
     404
     405    ctx.stroke();
     406}
     407
    398408function performNaNActions() {
    399409    ctx.globalAlpha = NaN;
     
    433443        test(resolve, reject) {
    434444            startRecording(WI.Canvas.ContextType.Canvas2D, resolve, reject, {memoryLimit: 10});
     445        },
     446    });
     447
     448    suite.addTestCase({
     449        name: "Canvas.recording2D.Console",
     450        description: "Check that a recording can be triggered by console.record().",
     451        test(resolve, reject) {
     452            consoleRecord(resolve, reject);
    435453        },
    436454    });
     
    477495        test(resolve, reject) {
    478496            let canvas = getCanvas(WI.Canvas.ContextType.Canvas2D);
    479             if (!canvas)
    480                 throw "Missing 2D canvas.";
     497            if (!canvas) {
     498                reject("Missing 2D canvas.");
     499                return;
     500            }
    481501
    482502            let eventCount = 0;
    483503            function handleRecordingStopped(event) {
    484504                InspectorTest.assert(event.data.canvas === canvas, "We should have stopped recording the selected canvas.");
     505                InspectorTest.assert(!event.data.recording, "The recording payload should be null.");
     506
    485507                ++eventCount;
    486 
    487508                if (eventCount == 1)
    488509                    InspectorTest.pass("A recording should have been started and stopped once.");
    489 
    490                 if (eventCount >= 2) {
     510                else if (eventCount >= 2) {
    491511                    InspectorTest.pass("A recording should have been started and stopped twice.");
    492512
  • trunk/LayoutTests/inspector/canvas/recording-webgl-expected.txt

    r224389 r225488  
    15011501  17: [16,3,122,108]
    15021502
     1503-- Running test case: Canvas.recordingWebGL.Console
     1504PASS: The recording should have the name "TEST".
     1505PASS: The recording should have one frame.
     1506PASS: The first frame should have one action.
     1507
  • trunk/LayoutTests/inspector/canvas/recording-webgl.html

    r222888 r225488  
    497497}
    498498
     499function performConsoleActions() {
     500    console.record(context, {name: "TEST"});
     501
     502    context.createTexture();
     503
     504    console.recordEnd(context);
     505
     506    context.createBuffer();
     507}
     508
    499509function test() {
    500510    let suite = InspectorTest.createAsyncSuite("Canvas.recordingWebGL");
     
    533543    });
    534544
     545    suite.addTestCase({
     546        name: "Canvas.recordingWebGL.Console",
     547        description: "Check that a recording can be triggered by console.record().",
     548        test(resolve, reject) {
     549            consoleRecord(resolve, reject);
     550        },
     551    });
     552
    535553    suite.runTestCasesAndFinish();
    536554}
  • trunk/LayoutTests/inspector/canvas/resources/recording-utilities.js

    r224726 r225488  
    145145        return canvas;
    146146    };
     147
     148    window.consoleRecord = function(resolve, reject) {
     149        WI.canvasManager.awaitEvent(WI.CanvasManager.Event.RecordingStopped).then((event) => {
     150            let recording = event.data.recording;
     151            InspectorTest.expectEqual(recording.displayName, "TEST", "The recording should have the name \"TEST\".");
     152            InspectorTest.expectEqual(recording.frames.length, 1, "The recording should have one frame.");
     153            InspectorTest.expectEqual(recording.frames[0].actions.length, 1, "The first frame should have one action.");
     154        }).then(resolve, reject);
     155
     156        InspectorTest.evaluateInPage(`performConsoleActions()`);
     157    };
    147158});
  • trunk/LayoutTests/js/console-expected.txt

    r201022 r225488  
    164164PASS descriptor.enumerable is true
    165165
     166console.record
     167PASS typeof console.record is "function"
     168PASS console.record.length is 0
     169PASS descriptor.configurable is true
     170PASS descriptor.writable is true
     171PASS descriptor.enumerable is true
     172
     173console.recordEnd
     174PASS typeof console.recordEnd is "function"
     175PASS console.recordEnd.length is 0
     176PASS descriptor.configurable is true
     177PASS descriptor.writable is true
     178PASS descriptor.enumerable is true
     179
    166180PASS Object.getOwnPropertyNames(console).length is enumerablePropertyCount
     181
     182fuzzing of target for console.record
     183PASS console.record() did not throw exception.
     184PASS console.record(undefined) did not throw exception.
     185PASS console.record(null) did not throw exception.
     186PASS console.record(1) did not throw exception.
     187PASS console.record("test") did not throw exception.
     188PASS console.record([]) did not throw exception.
     189PASS console.record({}) did not throw exception.
     190PASS console.record(window) did not throw exception.
     191PASS console.record(console) did not throw exception.
     192
     193fuzzing of options for console.record
     194PASS console.record({}, undefined) did not throw exception.
     195PASS console.record({}, null) did not throw exception.
     196PASS console.record({}, 1) did not throw exception.
     197PASS console.record({}, "test") did not throw exception.
     198PASS console.record({}, []) did not throw exception.
     199PASS console.record({}, {}) did not throw exception.
     200PASS console.record({}, window) did not throw exception.
     201PASS console.record({}, console) did not throw exception.
     202
     203fuzzing of target for console.recordEnd
     204PASS console.recordEnd() did not throw exception.
     205PASS console.recordEnd(undefined) did not throw exception.
     206PASS console.recordEnd(null) did not throw exception.
     207PASS console.recordEnd(1) did not throw exception.
     208PASS console.recordEnd("test") did not throw exception.
     209PASS console.recordEnd([]) did not throw exception.
     210PASS console.recordEnd({}) did not throw exception.
     211PASS console.recordEnd(window) did not throw exception.
     212PASS console.recordEnd(console) did not throw exception.
     213
     214ensure multiple calls don't throw
     215PASS console.recordEnd(window.canvas) did not throw exception.
     216PASS console.recordEnd(window.canvas) did not throw exception.
     217PASS console.recordEnd(window.canvas) did not throw exception.
     218PASS console.record(window.canvas) did not throw exception.
     219PASS console.record(window.canvas) did not throw exception.
     220PASS console.record(window.canvas) did not throw exception.
    167221PASS successfullyParsed is true
    168222
  • trunk/LayoutTests/js/console.html

    r201022 r225488  
    4747debug("");
    4848shouldBe("Object.getOwnPropertyNames(console).length", "enumerablePropertyCount");
     49
     50const consoleRecordArguments = [
     51        `undefined`,
     52        `null`,
     53        `1`,
     54        `"test"`,
     55        `[]`,
     56        `{}`,
     57        `window`,
     58        `console`,
     59];
     60
     61debug("");
     62debug("fuzzing of target for console.record");
     63shouldNotThrow(`console.record()`);
     64for (let argument of consoleRecordArguments)
     65        shouldNotThrow(`console.record(${argument})`);
     66
     67debug("");
     68debug("fuzzing of options for console.record");
     69for (let argument of consoleRecordArguments)
     70        shouldNotThrow(`console.record({}, ${argument})`);
     71
     72debug("");
     73debug("fuzzing of target for console.recordEnd");
     74shouldNotThrow(`console.recordEnd()`);
     75for (let argument of consoleRecordArguments)
     76        shouldNotThrow(`console.recordEnd(${argument})`);
     77
     78debug("");
     79debug("ensure multiple calls don't throw");
     80shouldNotThrow(`console.recordEnd(window.canvas)`);
     81shouldNotThrow(`console.recordEnd(window.canvas)`);
     82shouldNotThrow(`console.recordEnd(window.canvas)`);
     83shouldNotThrow(`console.record(window.canvas)`);
     84shouldNotThrow(`console.record(window.canvas)`);
     85shouldNotThrow(`console.record(window.canvas)`);
     86
    4987</script>
    5088<script src="../resources/js-test-post.js"></script>
     89<canvas id="canvas"></canvas>
    5190</body>
    5291</html>
  • trunk/Source/JavaScriptCore/ChangeLog

    r225470 r225488  
     12017-12-04  Devin Rousso  <webkit@devinrousso.com>
     2
     3        Web Inspector: provide method for recording CanvasRenderingContext2D from JavaScript
     4        https://bugs.webkit.org/show_bug.cgi?id=175166
     5        <rdar://problem/34040740>
     6
     7        Reviewed by Joseph Pecoraro.
     8
     9        * inspector/protocol/Recording.json:
     10        Add optional `name` that will be used by the frontend for uniquely identifying the Recording.
     11
     12        * inspector/JSGlobalObjectConsoleClient.h:
     13        * inspector/JSGlobalObjectConsoleClient.cpp:
     14        (Inspector::JSGlobalObjectConsoleClient::record):
     15        (Inspector::JSGlobalObjectConsoleClient::recordEnd):
     16
     17        * runtime/ConsoleClient.h:
     18        * runtime/ConsoleObject.cpp:
     19        (JSC::ConsoleObject::finishCreation):
     20        (JSC::consoleProtoFuncRecord):
     21        (JSC::consoleProtoFuncRecordEnd):
     22
    1232017-12-03  Yusuke Suzuki  <utatane.tea@gmail.com>
    224
  • trunk/Source/JavaScriptCore/inspector/JSGlobalObjectConsoleClient.cpp

    r212448 r225488  
    166166}
    167167
     168void JSGlobalObjectConsoleClient::record(ExecState*, Ref<ScriptArguments>&&) { }
     169void JSGlobalObjectConsoleClient::recordEnd(ExecState*, Ref<ScriptArguments>&&) { }
     170
    168171void JSGlobalObjectConsoleClient::warnUnimplemented(const String& method)
    169172{
  • trunk/Source/JavaScriptCore/inspector/JSGlobalObjectConsoleClient.h

    r212448 r225488  
    5454    void timeEnd(JSC::ExecState*, const String& title) override;
    5555    void timeStamp(JSC::ExecState*, Ref<ScriptArguments>&&) override;
     56    void record(JSC::ExecState*, Ref<ScriptArguments>&&) override;
     57    void recordEnd(JSC::ExecState*, Ref<ScriptArguments>&&) override;
    5658
    5759private:
  • trunk/Source/JavaScriptCore/inspector/protocol/Recording.json

    r224726 r225488  
    3636                { "name": "type", "$ref": "Type" },
    3737                { "name": "initialState", "$ref": "InitialState", "description": "JSON data of inital state of object before recording." },
    38                 { "name": "data", "type": "array", "items": { "type": "any" }, "description": "Array of objects that can be referenced by index. Used to avoid duplicating objects." }
     38                { "name": "data", "type": "array", "items": { "type": "any" }, "description": "Array of objects that can be referenced by index. Used to avoid duplicating objects." },
     39                { "name": "name", "type": "string", "optional": true }
    3940            ]
    4041        }
  • trunk/Source/JavaScriptCore/runtime/ConsoleClient.h

    r212448 r225488  
    6363    virtual void timeEnd(ExecState*, const String& title) = 0;
    6464    virtual void timeStamp(ExecState*, Ref<Inspector::ScriptArguments>&&) = 0;
     65    virtual void record(ExecState*, Ref<Inspector::ScriptArguments>&&) = 0;
     66    virtual void recordEnd(ExecState*, Ref<Inspector::ScriptArguments>&&) = 0;
    6567
    6668private:
  • trunk/Source/JavaScriptCore/runtime/ConsoleObject.cpp

    r222473 r225488  
    5858static EncodedJSValue JSC_HOST_CALL consoleProtoFuncGroupCollapsed(ExecState*);
    5959static EncodedJSValue JSC_HOST_CALL consoleProtoFuncGroupEnd(ExecState*);
     60static EncodedJSValue JSC_HOST_CALL consoleProtoFuncRecord(ExecState*);
     61static EncodedJSValue JSC_HOST_CALL consoleProtoFuncRecordEnd(ExecState*);
    6062
    6163const ClassInfo ConsoleObject::s_info = { "Console", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(ConsoleObject) };
     
    9698    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("groupCollapsed", consoleProtoFuncGroupCollapsed, static_cast<unsigned>(PropertyAttribute::None), 0);
    9799    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("groupEnd", consoleProtoFuncGroupEnd, static_cast<unsigned>(PropertyAttribute::None), 0);
     100    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("record", consoleProtoFuncRecord, static_cast<unsigned>(PropertyAttribute::None), 0);
     101    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("recordEnd", consoleProtoFuncRecordEnd, static_cast<unsigned>(PropertyAttribute::None), 0);
    98102}
    99103
     
    368372}
    369373
     374static EncodedJSValue JSC_HOST_CALL consoleProtoFuncRecord(ExecState* exec)
     375{
     376    ConsoleClient* client = exec->lexicalGlobalObject()->consoleClient();
     377    if (!client)
     378        return JSValue::encode(jsUndefined());
     379
     380    client->record(exec, Inspector::createScriptArguments(exec, 0));
     381    return JSValue::encode(jsUndefined());
     382}
     383
     384static EncodedJSValue JSC_HOST_CALL consoleProtoFuncRecordEnd(ExecState* exec)
     385{
     386    ConsoleClient* client = exec->lexicalGlobalObject()->consoleClient();
     387    if (!client)
     388        return JSValue::encode(jsUndefined());
     389
     390    client->recordEnd(exec, Inspector::createScriptArguments(exec, 0));
     391    return JSValue::encode(jsUndefined());
     392}
     393
    370394} // namespace JSC
  • trunk/Source/WebCore/ChangeLog

    r225486 r225488  
     12017-12-04  Devin Rousso  <webkit@devinrousso.com>
     2
     3        Web Inspector: provide method for recording CanvasRenderingContext2D from JavaScript
     4        https://bugs.webkit.org/show_bug.cgi?id=175166
     5        <rdar://problem/34040740>
     6
     7        Reviewed by Joseph Pecoraro.
     8
     9        No new tests, updated existing tests.
     10
     11        * inspector/InspectorCanvas.h:
     12        * inspector/InspectorCanvas.cpp:
     13        (WebCore::InspectorCanvas::resetRecordingData):
     14
     15        * inspector/InspectorCanvasAgent.h:
     16        * inspector/InspectorCanvasAgent.cpp:
     17        (WebCore::InspectorCanvasAgent::didFinishRecordingCanvasFrame):
     18        (WebCore::InspectorCanvasAgent::consoleStartRecordingCanvas):
     19
     20        * inspector/InspectorInstrumentation.h:
     21        * inspector/InspectorInstrumentation.cpp:
     22        (WebCore::InspectorInstrumentation::consoleStartRecordingCanvas):
     23        (WebCore::InspectorInstrumentation::consoleStartRecordingCanvasImpl):
     24
     25        * page/PageConsoleClient.h:
     26        * page/PageConsoleClient.cpp:
     27        (WebCore::PageConsoleClient::record):
     28        (WebCore::PageConsoleClient::recordEnd):
     29
     30        * workers/WorkerConsoleClient.h:
     31        * workers/WorkerConsoleClient.cpp:
     32        (WebCore::WorkerConsoleClient::record):
     33        (WebCore::WorkerConsoleClient::recordEnd):
     34
    1352017-12-04  Youenn Fablet  <youenn@apple.com>
    236
  • trunk/Source/WebCore/inspector/InspectorCanvas.cpp

    r225425 r225488  
    103103    m_serializedDuplicateData = nullptr;
    104104    m_indexedDuplicateData.clear();
     105    m_recordingName = { };
    105106    m_bufferLimit = 100 * 1024 * 1024;
    106107    m_bufferUsed = 0;
  • trunk/Source/WebCore/inspector/InspectorCanvas.h

    r225425 r225488  
    6969    void markCurrentFrameIncomplete();
    7070
     71    const String& recordingName() const { return m_recordingName; }
     72    void setRecordingName(const String& name) { m_recordingName = name; }
     73
    7174    void setBufferLimit(long);
    7275    bool hasBufferSpace() const;
     
    117120    RefPtr<JSON::ArrayOf<JSON::Value>> m_serializedDuplicateData;
    118121    Vector<DuplicateDataVariant> m_indexedDuplicateData;
     122
     123    String m_recordingName;
    119124    double m_currentFrameStartTime { NAN };
    120125    size_t m_bufferLimit { 100 * 1024 * 1024 };
  • trunk/Source/WebCore/inspector/InspectorInstrumentation.cpp

    r225263 r225488  
    883883}
    884884
     885void InspectorInstrumentation::consoleStartRecordingCanvasImpl(InstrumentingAgents& instrumentingAgents, HTMLCanvasElement& canvasElement, JSC::ExecState& exec, JSC::JSObject* options)
     886{
     887    if (InspectorCanvasAgent* canvasAgent = instrumentingAgents.inspectorCanvasAgent())
     888        canvasAgent->consoleStartRecordingCanvas(canvasElement, exec, options);
     889}
     890
    885891void InspectorInstrumentation::didOpenDatabaseImpl(InstrumentingAgents& instrumentingAgents, RefPtr<Database>&& database, const String& domain, const String& name, const String& version)
    886892{
  • trunk/Source/WebCore/inspector/InspectorInstrumentation.h

    r225193 r225488  
    4949#include "WorkerGlobalScope.h"
    5050#include "WorkerInspectorController.h"
     51#include <runtime/JSCInlines.h>
    5152#include <wtf/MemoryPressureHandler.h>
    5253#include <wtf/RefPtr.h>
     
    226227    static void startProfiling(Page&, JSC::ExecState*, const String& title);
    227228    static void stopProfiling(Page&, JSC::ExecState*, const String& title);
     229    static void consoleStartRecordingCanvas(HTMLCanvasElement&, JSC::ExecState&, JSC::JSObject* options);
    228230
    229231    static void didRequestAnimationFrame(Document&, int callbackId);
     
    392394    static void stopConsoleTimingImpl(InstrumentingAgents&, const String& title, Ref<Inspector::ScriptCallStack>&&);
    393395    static void consoleTimeStampImpl(InstrumentingAgents&, Frame&, Ref<Inspector::ScriptArguments>&&);
     396    static void startProfilingImpl(InstrumentingAgents&, JSC::ExecState*, const String& title);
     397    static void stopProfilingImpl(InstrumentingAgents&, JSC::ExecState*, const String& title);
     398    static void consoleStartRecordingCanvasImpl(InstrumentingAgents&, HTMLCanvasElement&, JSC::ExecState&, JSC::JSObject* options);
    394399
    395400    static void didRequestAnimationFrameImpl(InstrumentingAgents&, int callbackId, Document&);
     
    397402    static InspectorInstrumentationCookie willFireAnimationFrameImpl(InstrumentingAgents&, int callbackId, Document&);
    398403    static void didFireAnimationFrameImpl(const InspectorInstrumentationCookie&);
    399 
    400     static void startProfilingImpl(InstrumentingAgents&, JSC::ExecState*, const String& title);
    401     static void stopProfilingImpl(InstrumentingAgents&, JSC::ExecState*, const String& title);
    402404
    403405    static void didOpenDatabaseImpl(InstrumentingAgents&, RefPtr<Database>&&, const String& domain, const String& name, const String& version);
     
    13901392}
    13911393
     1394inline void InspectorInstrumentation::consoleStartRecordingCanvas(HTMLCanvasElement& canvasElement, JSC::ExecState& exec, JSC::JSObject* options)
     1395{
     1396    FAST_RETURN_IF_NO_FRONTENDS(void());
     1397    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(&canvasElement.document()))
     1398        consoleStartRecordingCanvasImpl(*instrumentingAgents, canvasElement, exec, options);
     1399}
     1400
    13921401inline void InspectorInstrumentation::didRequestAnimationFrame(Document& document, int callbackId)
    13931402{
  • trunk/Source/WebCore/inspector/agents/InspectorCanvasAgent.cpp

    r225425 r225488  
    523523        .release();
    524524
     525    const String& name = inspectorCanvas->recordingName();
     526    if (!name.isEmpty())
     527        recording->setName(name);
     528
    525529    m_frontendDispatcher->recordingFinished(inspectorCanvas->identifier(), WTFMove(recording));
    526530
    527531    inspectorCanvas->resetRecordingData();
     532}
     533
     534void InspectorCanvasAgent::consoleStartRecordingCanvas(HTMLCanvasElement& canvasElement, JSC::ExecState& exec, JSC::JSObject* options)
     535{
     536    auto* inspectorCanvas = findInspectorCanvas(canvasElement);
     537    if (!inspectorCanvas)
     538        return;
     539
     540    if (inspectorCanvas->canvas().renderingContext()->callTracingActive())
     541        return;
     542
     543    inspectorCanvas->resetRecordingData();
     544
     545    if (options) {
     546        if (JSC::JSValue optionName = options->get(&exec, JSC::Identifier::fromString(&exec, "name")))
     547            inspectorCanvas->setRecordingName(optionName.toWTFString(&exec));
     548        if (JSC::JSValue optionSingleFrame = options->get(&exec, JSC::Identifier::fromString(&exec, "singleFrame")))
     549            inspectorCanvas->setSingleFrame(optionSingleFrame.toBoolean(&exec));
     550        if (JSC::JSValue optionMemoryLimit = options->get(&exec, JSC::Identifier::fromString(&exec, "memoryLimit")))
     551            inspectorCanvas->setBufferLimit(optionMemoryLimit.toNumber(&exec));
     552    }
     553
     554    inspectorCanvas->canvas().renderingContext()->setCallTracingActive(true);
    528555}
    529556
  • trunk/Source/WebCore/inspector/agents/InspectorCanvasAgent.h

    r225425 r225488  
    8888    void recordCanvasAction(CanvasRenderingContext&, const String&, Vector<RecordCanvasActionVariant>&& = { });
    8989    void didFinishRecordingCanvasFrame(HTMLCanvasElement&, bool forceDispatch = false);
     90    void consoleStartRecordingCanvas(HTMLCanvasElement&, JSC::ExecState&, JSC::JSObject* options);
    9091#if ENABLE(WEBGL)
    9192    void didEnableExtension(WebGLRenderingContextBase&, const String&);
  • trunk/Source/WebCore/page/PageConsoleClient.cpp

    r223728 r225488  
    3030#include "PageConsoleClient.h"
    3131
     32#include "CanvasRenderingContext2D.h"
    3233#include "Chrome.h"
    3334#include "ChromeClient.h"
    3435#include "Document.h"
    3536#include "Frame.h"
     37#include "HTMLCanvasElement.h"
    3638#include "InspectorController.h"
    3739#include "InspectorInstrumentation.h"
     40#include "JSCanvasRenderingContext2D.h"
     41#include "JSHTMLCanvasElement.h"
    3842#include "JSMainThreadExecState.h"
    3943#include "MainFrame.h"
     
    4145#include "ScriptableDocumentParser.h"
    4246#include "Settings.h"
     47#include <bindings/ScriptValue.h>
    4348#include <inspector/ConsoleMessage.h>
    4449#include <inspector/ScriptArguments.h>
    4550#include <inspector/ScriptCallStack.h>
    4651#include <inspector/ScriptCallStackFactory.h>
     52#include <runtime/JSCInlines.h>
     53#include <wtf/text/WTFString.h>
     54
     55#if ENABLE(WEBGL)
     56#include "JSWebGLRenderingContext.h"
     57#include "WebGLRenderingContext.h"
     58#endif
    4759
    4860
     
    207219}
    208220
     221void PageConsoleClient::record(JSC::ExecState* exec, Ref<ScriptArguments>&& arguments)
     222{
     223    if (arguments->argumentCount() < 1)
     224        return;
     225
     226    JSC::JSObject* target = arguments->argumentAt(0).jsValue().getObject();
     227    if (!target)
     228        return;
     229
     230    JSC::JSObject* options = nullptr;
     231    if (arguments->argumentCount() >= 2)
     232        options = arguments->argumentAt(1).jsValue().getObject();
     233
     234    if (HTMLCanvasElement* canvasElement = JSHTMLCanvasElement::toWrapped(*target->vm(), target))
     235        InspectorInstrumentation::consoleStartRecordingCanvas(*canvasElement, *exec, options);
     236    else if (CanvasRenderingContext2D* context2d = JSCanvasRenderingContext2D::toWrapped(*target->vm(), target))
     237        InspectorInstrumentation::consoleStartRecordingCanvas(context2d->canvas(), *exec, options);
     238#if ENABLE(WEBGL)
     239    else if (WebGLRenderingContext* contextWebGL = JSWebGLRenderingContext::toWrapped(*target->vm(), target)) {
     240        auto canvas = contextWebGL->canvas();
     241        if (WTF::holds_alternative<RefPtr<HTMLCanvasElement>>(canvas))
     242            InspectorInstrumentation::consoleStartRecordingCanvas(*WTF::get<RefPtr<HTMLCanvasElement>>(canvas), *exec, options);
     243    }
     244#endif
     245}
     246
     247void PageConsoleClient::recordEnd(JSC::ExecState*, Ref<ScriptArguments>&& arguments)
     248{
     249    if (arguments->argumentCount() < 1)
     250        return;
     251
     252    JSC::JSObject* target = arguments->argumentAt(0).jsValue().getObject();
     253    if (!target)
     254        return;
     255
     256    if (HTMLCanvasElement* canvasElement = JSHTMLCanvasElement::toWrapped(*target->vm(), target))
     257        InspectorInstrumentation::didFinishRecordingCanvasFrame(*canvasElement, true);
     258    else if (CanvasRenderingContext2D* context2d = JSCanvasRenderingContext2D::toWrapped(*target->vm(), target))
     259        InspectorInstrumentation::didFinishRecordingCanvasFrame(context2d->canvas(), true);
     260#if ENABLE(WEBGL)
     261    else if (WebGLRenderingContext* contextWebGL = JSWebGLRenderingContext::toWrapped(*target->vm(), target)) {
     262        auto canvas = contextWebGL->canvas();
     263        if (WTF::holds_alternative<RefPtr<HTMLCanvasElement>>(canvas))
     264            InspectorInstrumentation::didFinishRecordingCanvasFrame(*WTF::get<RefPtr<HTMLCanvasElement>>(canvas), true);
     265    }
     266#endif
     267}
     268
    209269} // namespace WebCore
  • trunk/Source/WebCore/page/PageConsoleClient.h

    r218603 r225488  
    7575    void timeEnd(JSC::ExecState*, const String& title) override;
    7676    void timeStamp(JSC::ExecState*, Ref<Inspector::ScriptArguments>&&) override;
     77    void record(JSC::ExecState*, Ref<Inspector::ScriptArguments>&&) override;
     78    void recordEnd(JSC::ExecState*, Ref<Inspector::ScriptArguments>&&) override;
    7779
    7880private:
  • trunk/Source/WebCore/workers/WorkerConsoleClient.cpp

    r223728 r225488  
    7575void WorkerConsoleClient::timeStamp(JSC::ExecState*, Ref<ScriptArguments>&&) { }
    7676
     77void WorkerConsoleClient::record(JSC::ExecState*, Ref<ScriptArguments>&&) { }
     78void WorkerConsoleClient::recordEnd(JSC::ExecState*, Ref<ScriptArguments>&&) { }
     79
    7780} // namespace WebCore
  • trunk/Source/WebCore/workers/WorkerConsoleClient.h

    r212448 r225488  
    5151    void timeEnd(JSC::ExecState*, const String& title) override;
    5252    void timeStamp(JSC::ExecState*, Ref<Inspector::ScriptArguments>&&) override;
     53    void record(JSC::ExecState*, Ref<Inspector::ScriptArguments>&&) override;
     54    void recordEnd(JSC::ExecState*, Ref<Inspector::ScriptArguments>&&) override;
    5355
    5456private:
  • trunk/Source/WebInspectorUI/ChangeLog

    r225487 r225488  
     12017-12-04  Devin Rousso  <webkit@devinrousso.com>
     2
     3        Web Inspector: provide method for recording CanvasRenderingContext2D from JavaScript
     4        https://bugs.webkit.org/show_bug.cgi?id=175166
     5        <rdar://problem/34040740>
     6
     7        Reviewed by Joseph Pecoraro.
     8
     9        * UserInterface/Controllers/CanvasManager.js:
     10        (WI.CanvasManager.prototype.recordingFinished):
     11        If a `name` is sent with the payload, use it as the suggested name.
     12
     13        * UserInterface/Models/NativeFunctionParameters.js:
     14        Add `console.record` and `console.recordEnd`.
     15
     16        * UserInterface/Views/CanvasTabContentView.js:
     17        (WI.CanvasTabContentView.prototype.showRepresentedObject):
     18        Drive-by: remove logic that toggled the collapsed state of the navigation sidebar, as this
     19        was not very controllable by the user and often was aggravating.
     20
     21        (WI.CanvasTabContentView.prototype._recordingStopped):
     22        Only show the recording if it was not started from the console. This can determined by
     23        CanvasManager when it recieves a recording if the recording's source is not the same as the
     24        current canvas being recorded.
     25
    1262017-12-04  Matt Baker  <mattbaker@apple.com>
    227
  • trunk/Source/WebInspectorUI/UserInterface/Controllers/CanvasManager.js

    r224726 r225488  
    169169        // Called from WI.CanvasObserver.
    170170
    171         this._recordingCanvas = null;
    172 
    173         let canvas = this._canvasIdentifierMap.get(canvasIdentifier);
    174         console.assert(canvas);
     171        let canvas = this._canvasIdentifierMap.get(canvasIdentifier);
     172        console.assert(canvas);
     173
     174        let fromConsole = canvas !== this._recordingCanvas;
     175        if (!fromConsole)
     176            this._recordingCanvas = null;
     177
    175178        if (!canvas)
    176179            return;
     
    180183        if (recording) {
    181184            recording.source = canvas;
    182             recording.createDisplayName();
     185            recording.createDisplayName(recordingPayload.name);
    183186
    184187            canvas.recordingCollection.add(recording);
    185188        }
    186189
    187         this.dispatchEventToListeners(WI.CanvasManager.Event.RecordingStopped, {canvas, recording});
     190        this.dispatchEventToListeners(WI.CanvasManager.Event.RecordingStopped, {canvas, recording, fromConsole});
    188191    }
    189192
  • trunk/Source/WebInspectorUI/UserInterface/Models/NativeFunctionParameters.js

    r220119 r225488  
    174174        profile: "name",
    175175        profileEnd: "name",
     176        record: "object, [options]",
     177        recordEnd: "object",
    176178        table: "data, [columns]",
    177179        takeHeapSnapshot: "[label]",
  • trunk/Source/WebInspectorUI/UserInterface/Views/CanvasTabContentView.js

    r224475 r225488  
    104104        if (representedObject instanceof WI.CanvasCollection || representedObject instanceof WI.ShaderProgram) {
    105105            this._overviewNavigationItem.hidden = true;
    106             WI.navigationSidebar.collapsed = true;
    107106            return;
    108107        }
     
    110109        if (representedObject instanceof WI.Recording) {
    111110            this._overviewNavigationItem.hidden = false;
    112             representedObject.actions.then((actions) => {
    113                 this.navigationSidebarPanel.recording = representedObject;
    114                 WI.navigationSidebar.collapsed = false;
    115             });
     111            this.navigationSidebarPanel.recording = representedObject;
    116112            return;
    117113        }
     
    246242        }
    247243
    248         this._recordingAdded(recording);
     244        this._recordingAdded(recording, {
     245            suppressShowRecording: event.data.fromConsole,
     246        });
    249247    }
    250248
  • trunk/Source/WebInspectorUI/UserInterface/Views/RecordingNavigationSidebarPanel.js

    r224389 r225488  
    5959
    6060        this._recording.actions.then((actions) => {
     61            if (recording !== this._recording)
     62                return;
     63
    6164            this.contentTreeOutline.element.dataset.indent = Number.countDigits(actions.length);
    6265
Note: See TracChangeset for help on using the changeset viewer.