Title: [220008] trunk
Revision
220008
Author
[email protected]
Date
2017-07-28 11:22:17 -0700 (Fri, 28 Jul 2017)

Log Message

Web Inspector: Record actions performed on CanvasRenderingContext2D
https://bugs.webkit.org/show_bug.cgi?id=174482

Reviewed by Joseph Pecoraro.

Source/WebCore:

Tests: inspector/canvas/recording-2d.html
       inspector/canvas/recording.html

* html/canvas/CanvasRenderingContext2D.idl:
Add CallTracingCallback to interface to record all API calls.

* html/HTMLCanvasElement.cpp:
(WebCore::HTMLCanvasElement::paint):
If a recording is active, mark the current frame as completed.

* bindings/scripts/CodeGeneratorJS.pm:
(GenerateAttributeGetterBodyDefinition):
(GenerateAttributeSetterBodyDefinition):
(GenerateImplementationFunctionCall):
(GenerateCallTracerParameter):
(GenerateCallTracer):
* bindings/scripts/test/TestCallTracer.idl:
* bindings/scripts/test/JS/JSTestCallTracer.cpp:
(WebCore::setJSTestCallTracerTestAttributeInterfaceSetter):
(WebCore::setJSTestCallTracerTestAttributeSpecifiedSetter):
(WebCore::jsTestCallTracerTestAttributeWithVariantGetter):
(WebCore::jsTestCallTracerTestAttributeWithVariant):
(WebCore::setJSTestCallTracerTestAttributeWithVariantSetter):
(WebCore::setJSTestCallTracerTestAttributeWithVariant):
(WebCore::jsTestCallTracerPrototypeFunctionTestOperationInterfaceBody):
(WebCore::jsTestCallTracerPrototypeFunctionTestOperationSpecifiedBody):
(WebCore::jsTestCallTracerPrototypeFunctionTestOperationWithArgumentsBody):
(WebCore::jsTestCallTracerPrototypeFunctionTestOperationWithNullableArgumentBody):
(WebCore::jsTestCallTracerPrototypeFunctionTestOperationWithVariantArgumentBody):
(WebCore::jsTestCallTracerPrototypeFunctionTestOperationWithVariantArgument):
* inspector/InspectorCanvas.h:
* inspector/InspectorCanvas.cpp:
(WebCore::InspectorCanvas::recordAction):
(WebCore::InspectorCanvas::buildAction):
Change CallTracer IDL generation to flatten any variants so that all types for the
parameters of an action are able to be listed in a single variant. This prevents possible
ambiguity when constructing the variant, as they require that exactly one type be
constructible and a sub-variant might not satisfy that condition. This was only an issue for
older mac SDKs.

* bindings/js/CallTracer.h:
* bindings/js/CallTracer.cpp:
(WebCore::CallTracer::recordCanvasAction):
* bindings/js/CallTracerTypes.h:
* inspector/InspectorCanvasAgent.h:
* inspector/InspectorCanvasAgent.cpp:
(WebCore::InspectorCanvasAgent::recordCanvasAction):
* inspector/InspectorInstrumentation.h:
* inspector/InspectorInstrumentation.cpp:
(WebCore::InspectorInstrumentation::recordCanvasAction):
(WebCore::InspectorInstrumentation::recordCanvasActionImpl):
Rename CanvasActionParameterVariant to RecordCanvasActionVariant to match what is expected by
the IDL generator. Also remove unnecessary includes now that they are in CallTracerTypes.h.

* CMakeLists.txt:
* bindings/js/JSBindingsAllInOne.cpp:
Add CallTracer for CMake builds.

LayoutTests:

* inspector/canvas/recording-2d-expected.txt: Added.
* inspector/canvas/recording-2d.html: Added.
* inspector/canvas/recording-expected.txt: Added.
* inspector/canvas/recording.html: Added.
Take a recording of all CanvasRenderingContext2D actions and dump the recorded JSON data.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (220007 => 220008)


--- trunk/LayoutTests/ChangeLog	2017-07-28 18:06:59 UTC (rev 220007)
+++ trunk/LayoutTests/ChangeLog	2017-07-28 18:22:17 UTC (rev 220008)
@@ -1,3 +1,16 @@
+2017-07-28  Devin Rousso  <[email protected]>
+
+        Web Inspector: Record actions performed on CanvasRenderingContext2D
+        https://bugs.webkit.org/show_bug.cgi?id=174482
+
+        Reviewed by Joseph Pecoraro.
+
+        * inspector/canvas/recording-2d-expected.txt: Added.
+        * inspector/canvas/recording-2d.html: Added.
+        * inspector/canvas/recording-expected.txt: Added.
+        * inspector/canvas/recording.html: Added.
+        Take a recording of all CanvasRenderingContext2D actions and dump the recorded JSON data.
+
 2017-07-28  Per Arne Vollan  <[email protected]>
 
         The test imported/w3c/web-platform-tests/cors/allow-headers.htm is slow on Windows.

Added: trunk/LayoutTests/inspector/canvas/recording-2d-expected.txt (0 => 220008)


--- trunk/LayoutTests/inspector/canvas/recording-2d-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/inspector/canvas/recording-2d-expected.txt	2017-07-28 18:22:17 UTC (rev 220008)
@@ -0,0 +1,1837 @@
+Test that CanvasManager is able to record actions made to 2D canvas contexts.
+
+
+== Running test suite: Canvas.recording2D
+-- Running test case: Canvas.recording2D.singleFrame
+{
+  "version": 1,
+  "type": "canvas-2d",
+  "initialState": {
+    "attributes": {
+      "width": 2,
+      "height": 2,
+      "setTransform": [
+        1,
+        0,
+        0,
+        1,
+        0,
+        0
+      ],
+      "globalAlpha": 1,
+      "globalCompositeOperation": "source-over",
+      "lineWidth": 1,
+      "lineCap": "butt",
+      "lineJoin": "miter",
+      "miterLimit": 10,
+      "shadowOffsetX": 0,
+      "shadowOffsetY": 0,
+      "shadowBlur": 0,
+      "shadowColor": "rgba(0, 0, 0, 0)",
+      "setLineDash": [
+        []
+      ],
+      "lineDashOffset": 0,
+      "font": "10px sans-serif",
+      "textAlign": "start",
+      "textBaseline": "alphabetic",
+      "direction": "ltr",
+      "strokeStyle": 0,
+      "fillStyle": 0,
+      "imageSmoothingEnabled": true,
+      "imageSmoothingQuality": "low"
+    },
+    "content": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAAXNSR0IArs4c6QAAAAtJREFUCB1jYEAHAAASAAGAFMrMAAAAAElFTkSuQmCC"
+  },
+  "frames": [
+    {
+      "actions": [
+        [
+          1,
+          [
+            1,
+            2,
+            3,
+            4,
+            5,
+            0
+          ]
+        ],
+        [
+          1,
+          [
+            6,
+            7,
+            8,
+            9,
+            10,
+            1
+          ]
+        ]
+      ]
+    }
+  ],
+  "data": [
+    "#000000",
+    "arc"
+  ]
+}
+
+-- Running test case: Canvas.recording2D.multipleFrames
+{
+  "version": 1,
+  "type": "canvas-2d",
+  "initialState": {
+    "attributes": {
+      "width": 2,
+      "height": 2,
+      "setTransform": [
+        1,
+        0,
+        0,
+        1,
+        0,
+        0
+      ],
+      "globalAlpha": 1,
+      "globalCompositeOperation": "source-over",
+      "lineWidth": 1,
+      "lineCap": "butt",
+      "lineJoin": "miter",
+      "miterLimit": 10,
+      "shadowOffsetX": 0,
+      "shadowOffsetY": 0,
+      "shadowBlur": 0,
+      "shadowColor": "rgba(0, 0, 0, 0)",
+      "setLineDash": [
+        []
+      ],
+      "lineDashOffset": 0,
+      "font": "10px sans-serif",
+      "textAlign": "start",
+      "textBaseline": "alphabetic",
+      "direction": "ltr",
+      "strokeStyle": 0,
+      "fillStyle": 0,
+      "imageSmoothingEnabled": true,
+      "imageSmoothingQuality": "low"
+    },
+    "content": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAAXNSR0IArs4c6QAAAAtJREFUCB1jYEAHAAASAAGAFMrMAAAAAElFTkSuQmCC"
+  },
+  "frames": [
+    {
+      "actions": [
+        [
+          1,
+          [
+            1,
+            2,
+            3,
+            4,
+            5,
+            0
+          ]
+        ],
+        [
+          1,
+          [
+            6,
+            7,
+            8,
+            9,
+            10,
+            1
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          2,
+          [
+            1,
+            2,
+            3,
+            4,
+            5
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          3,
+          []
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          4,
+          [
+            1,
+            2,
+            3,
+            4,
+            5,
+            6
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          5,
+          []
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          6,
+          [
+            1,
+            2,
+            3,
+            4
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          7,
+          []
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          8,
+          [
+            9
+          ]
+        ],
+        [
+          8,
+          [
+            10
+          ]
+        ],
+        [
+          8,
+          [
+            11,
+            9
+          ]
+        ],
+        [
+          8,
+          [
+            12,
+            10
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          13,
+          []
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          14,
+          []
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          15,
+          [
+            16
+          ]
+        ],
+        [
+          15,
+          [
+            2,
+            3
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          17,
+          [
+            1,
+            2,
+            3,
+            4
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          18,
+          [
+            19,
+            20
+          ]
+        ],
+        [
+          18,
+          [
+            21,
+            22
+          ]
+        ],
+        [
+          18,
+          [
+            23,
+            24
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          25,
+          [
+            1,
+            2,
+            3,
+            4,
+            5,
+            6
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          26,
+          []
+        ],
+        [
+          26,
+          [
+            27
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          28,
+          [
+            29
+          ]
+        ],
+        [
+          28,
+          [
+            11,
+            29
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          30,
+          [
+            19,
+            1,
+            2
+          ]
+        ],
+        [
+          30,
+          [
+            21,
+            3,
+            4
+          ]
+        ],
+        [
+          30,
+          [
+            23,
+            5,
+            6
+          ]
+        ],
+        [
+          30,
+          [
+            19,
+            7,
+            8,
+            9,
+            10
+          ]
+        ],
+        [
+          30,
+          [
+            21,
+            11,
+            12,
+            13,
+            14
+          ]
+        ],
+        [
+          30,
+          [
+            23,
+            15,
+            16,
+            17,
+            18
+          ]
+        ],
+        [
+          30,
+          [
+            19,
+            19,
+            20,
+            21,
+            22,
+            23,
+            24,
+            25,
+            26
+          ]
+        ],
+        [
+          30,
+          [
+            21,
+            27,
+            28,
+            29,
+            30,
+            31,
+            32,
+            33,
+            34
+          ]
+        ],
+        [
+          30,
+          [
+            23,
+            35,
+            36,
+            37,
+            38,
+            39,
+            40,
+            41,
+            42
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          31,
+          [
+            19,
+            1,
+            2,
+            3,
+            4,
+            5,
+            6,
+            7,
+            8,
+            32
+          ]
+        ],
+        [
+          31,
+          [
+            19,
+            9,
+            10,
+            11,
+            12,
+            13,
+            14,
+            15,
+            16,
+            27
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          33,
+          [
+            1,
+            2,
+            3,
+            4,
+            5,
+            6,
+            7,
+            0
+          ]
+        ],
+        [
+          33,
+          [
+            8,
+            9,
+            10,
+            11,
+            12,
+            13,
+            14,
+            1
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          34,
+          [
+            9
+          ]
+        ],
+        [
+          34,
+          [
+            10
+          ]
+        ],
+        [
+          34,
+          [
+            11,
+            9
+          ]
+        ],
+        [
+          34,
+          [
+            12,
+            10
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          35,
+          [
+            1,
+            2,
+            3,
+            4
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          36,
+          []
+        ],
+        [
+          36,
+          [
+            27
+          ]
+        ],
+        [
+          36,
+          [
+            38
+          ]
+        ],
+        [
+          36,
+          [
+            40
+          ]
+        ],
+        [
+          36,
+          [
+            44
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          45,
+          [
+            20,
+            1,
+            2
+          ]
+        ],
+        [
+          45,
+          [
+            22,
+            3,
+            4,
+            5
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          46,
+          []
+        ],
+        [
+          46,
+          [
+            27
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          47,
+          [
+            1,
+            2,
+            3,
+            4
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          48,
+          []
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          49,
+          []
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          50,
+          []
+        ],
+        [
+          50,
+          [
+            0
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          51,
+          []
+        ],
+        [
+          51,
+          [
+            27
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          52,
+          []
+        ],
+        [
+          52,
+          [
+            1
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          53,
+          []
+        ],
+        [
+          53,
+          [
+            54
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          55,
+          [
+            11,
+            5,
+            6,
+            9
+          ]
+        ],
+        [
+          55,
+          [
+            12,
+            7,
+            8,
+            10
+          ]
+        ],
+        [
+          55,
+          [
+            9,
+            10,
+            9
+          ]
+        ],
+        [
+          55,
+          [
+            11,
+            12,
+            10
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          56,
+          [
+            11,
+            3,
+            4
+          ]
+        ],
+        [
+          56,
+          [
+            5,
+            6
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          57,
+          []
+        ],
+        [
+          57,
+          [
+            27
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          58,
+          []
+        ],
+        [
+          58,
+          [
+            1
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          59,
+          []
+        ],
+        [
+          59,
+          [
+            27
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          60,
+          [
+            1,
+            2
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          61,
+          []
+        ],
+        [
+          61,
+          [
+            1
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          62,
+          [
+            27
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          63,
+          []
+        ],
+        [
+          63,
+          [
+            1
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          64,
+          [
+            1,
+            2
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          65,
+          [
+            16,
+            5,
+            6
+          ]
+        ],
+        [
+          65,
+          [
+            66,
+            7,
+            8,
+            9,
+            10,
+            11,
+            12
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          67,
+          [
+            1,
+            2,
+            3,
+            4
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          68,
+          [
+            1,
+            2,
+            3,
+            4
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          69,
+          []
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          70,
+          []
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          71,
+          [
+            1
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          72,
+          []
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          73,
+          [
+            1,
+            2
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          74,
+          [
+            null
+          ]
+        ],
+        [
+          74,
+          [
+            1
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          75,
+          [
+            76
+          ]
+        ],
+        [
+          75,
+          [
+            27
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          77,
+          [
+            20
+          ]
+        ],
+        [
+          77,
+          [
+            22,
+            1
+          ]
+        ],
+        [
+          77,
+          [
+            2,
+            1
+          ]
+        ],
+        [
+          77,
+          [
+            3,
+            4
+          ]
+        ],
+        [
+          77,
+          [
+            5,
+            6,
+            7,
+            8
+          ]
+        ],
+        [
+          77,
+          [
+            9,
+            10,
+            11,
+            12,
+            13
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          78,
+          [
+            76
+          ]
+        ],
+        [
+          78,
+          [
+            27
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          79,
+          [
+            [
+              1,
+              2
+            ]
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          80,
+          [
+            76
+          ]
+        ],
+        [
+          80,
+          [
+            27
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          81,
+          [
+            null
+          ]
+        ],
+        [
+          81,
+          [
+            1
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          82,
+          [
+            null
+          ]
+        ],
+        [
+          82,
+          [
+            1
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          83,
+          [
+            1,
+            2,
+            3,
+            84
+          ]
+        ],
+        [
+          83,
+          [
+            4,
+            5,
+            6,
+            27,
+            7
+          ]
+        ],
+        [
+          83,
+          [
+            8,
+            9,
+            10,
+            11,
+            1
+          ]
+        ],
+        [
+          83,
+          [
+            12,
+            13,
+            14,
+            15,
+            16
+          ]
+        ],
+        [
+          83,
+          [
+            17,
+            18,
+            19,
+            20,
+            21,
+            22,
+            23
+          ]
+        ],
+        [
+          83,
+          [
+            24,
+            25,
+            26,
+            27,
+            28,
+            29,
+            30,
+            31
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          85,
+          [
+            20
+          ]
+        ],
+        [
+          85,
+          [
+            22,
+            1
+          ]
+        ],
+        [
+          85,
+          [
+            2,
+            1
+          ]
+        ],
+        [
+          85,
+          [
+            3,
+            4
+          ]
+        ],
+        [
+          85,
+          [
+            5,
+            6,
+            7,
+            8
+          ]
+        ],
+        [
+          85,
+          [
+            9,
+            10,
+            11,
+            12,
+            13
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          86,
+          [
+            1,
+            2,
+            3,
+            4,
+            5,
+            6
+          ]
+        ],
+        [
+          86,
+          [
+            [
+              1,
+              0,
+              0,
+              1,
+              0,
+              0
+            ]
+          ]
+        ],
+        [
+          86,
+          [
+            [
+              7,
+              8,
+              9,
+              10,
+              11,
+              12
+            ]
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          87,
+          []
+        ],
+        [
+          87,
+          [
+            1
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          88,
+          []
+        ],
+        [
+          88,
+          [
+            27
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          89,
+          []
+        ],
+        [
+          89,
+          [
+            1
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          90,
+          []
+        ],
+        [
+          90,
+          [
+            1
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          91,
+          []
+        ],
+        [
+          91,
+          [
+            11
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          92,
+          [
+            1,
+            2,
+            3,
+            4
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          93,
+          []
+        ],
+        [
+          93,
+          [
+            27
+          ]
+        ],
+        [
+          93,
+          [
+            38
+          ]
+        ],
+        [
+          93,
+          [
+            40
+          ]
+        ],
+        [
+          93,
+          [
+            44
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          94,
+          [
+            20,
+            1,
+            2
+          ]
+        ],
+        [
+          94,
+          [
+            22,
+            3,
+            4,
+            5
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          95,
+          []
+        ],
+        [
+          95,
+          [
+            27
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          96,
+          []
+        ],
+        [
+          96,
+          [
+            27
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          97,
+          [
+            1,
+            2,
+            3,
+            4,
+            5,
+            6
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          98,
+          [
+            1,
+            2
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          99,
+          []
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          100,
+          [
+            1,
+            2,
+            3,
+            4
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          101,
+          []
+        ],
+        [
+          101,
+          [
+            1
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          102,
+          []
+        ],
+        [
+          102,
+          [
+            [
+              1,
+              2
+            ]
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          103,
+          []
+        ],
+        [
+          103,
+          [
+            1
+          ]
+        ]
+      ]
+    },
+    {
+      "actions": [
+        [
+          104,
+          [
+            16,
+            5,
+            6
+          ]
+        ],
+        [
+          104,
+          [
+            66,
+            7,
+            8,
+            9,
+            10,
+            11,
+            12
+          ]
+        ]
+      ]
+    }
+  ],
+  "data": [
+    "#000000",
+    "arc",
+    "arcTo",
+    "beginPath",
+    "bezierCurveTo",
+    "canvas",
+    "clearRect",
+    "clearShadow",
+    "clip",
+    "nonzero",
+    "evenodd",
+    "M1 2",
+    "M3 4",
+    "closePath",
+    "commit",
+    "createImageData",
+    [
+      [
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0
+      ],
+      1,
+      4
+    ],
+    "createLinearGradient",
+    "createPattern",
+    "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAAXNSR0IArs4c6QAAABNJREFUCB1j/M/AAEQMDEwgAgQAHxcCAmtAm/sAAAAASUVORK5CYII=",
+    "testA",
+    "data:,",
+    "testB",
+    "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAAXNSR0IArs4c6QAAAAtJREFUCB1jYEAHAAASAAGAFMrMAAAAAElFTkSuQmCC",
+    "testC",
+    "createRadialGradient",
+    "direction",
+    "test",
+    "drawFocusIfNeeded",
+    "element",
+    "drawImage",
+    "drawImageFromRect",
+    "",
+    "ellipse",
+    "fill",
+    "fillRect",
+    "fillStyle",
+    "linear-gradient",
+    [
+      37,
+      [
+        1,
+        2,
+        3,
+        4
+      ],
+      []
+    ],
+    "radial-gradient",
+    [
+      39,
+      [
+        1,
+        2,
+        3,
+        4,
+        5,
+        6
+      ],
+      []
+    ],
+    "pattern",
+    "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAAXNSR0IArs4c6QAAABNJREFUCB1j/M/AAEQMDEwgAgQAHxcCAmtAm/sAAAAASUVORK5CYII=",
+    "no-repeat",
+    [
+      41,
+      42,
+      43
+    ],
+    "fillText",
+    "font",
+    "getImageData",
+    "getLineDash",
+    "getTransform",
+    "globalAlpha",
+    "globalCompositeOperation",
+    "imageSmoothingEnabled",
+    "imageSmoothingQuality",
+    "low",
+    "isPointInPath",
+    "isPointInStroke",
+    "lineCap",
+    "lineDashOffset",
+    "lineJoin",
+    "lineTo",
+    "lineWidth",
+    "measureText",
+    "miterLimit",
+    "moveTo",
+    "putImageData",
+    [
+      [
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0
+      ],
+      2,
+      3
+    ],
+    "quadraticCurveTo",
+    "rect",
+    "resetTransform",
+    "restore",
+    "rotate",
+    "save",
+    "scale",
+    "setAlpha",
+    "setCompositeOperation",
+    "undefined",
+    "setFillColor",
+    "setLineCap",
+    "setLineDash",
+    "setLineJoin",
+    "setLineWidth",
+    "setMiterLimit",
+    "setShadow",
+    "",
+    "setStrokeColor",
+    "setTransform",
+    "shadowBlur",
+    "shadowColor",
+    "shadowOffsetX",
+    "shadowOffsetY",
+    "stroke",
+    "strokeRect",
+    "strokeStyle",
+    "strokeText",
+    "textAlign",
+    "textBaseline",
+    "transform",
+    "translate",
+    "webkitBackingStorePixelRatio",
+    "webkitGetImageDataHD",
+    "webkitImageSmoothingEnabled",
+    "webkitLineDash",
+    "webkitLineDashOffset",
+    "webkitPutImageDataHD"
+  ]
+}
+
+-- Running test case: Canvas.recording2D.memoryLimit
+{
+  "version": 1,
+  "type": "canvas-2d",
+  "initialState": {
+    "attributes": {
+      "width": 2,
+      "height": 2,
+      "setTransform": [
+        25,
+        28,
+        57,
+        64,
+        239,
+        268
+      ],
+      "globalAlpha": 1,
+      "globalCompositeOperation": "source-over",
+      "lineWidth": 1,
+      "lineCap": "butt",
+      "lineJoin": "miter",
+      "miterLimit": 1,
+      "shadowOffsetX": 1,
+      "shadowOffsetY": 1,
+      "shadowBlur": 1,
+      "shadowColor": "#ffffff",
+      "setLineDash": [
+        [
+          1,
+          2
+        ]
+      ],
+      "lineDashOffset": 1,
+      "font": "10px sans-serif",
+      "textAlign": "start",
+      "textBaseline": "alphabetic",
+      "direction": "ltr",
+      "strokeStyle": 3,
+      "fillStyle": 4,
+      "imageSmoothingEnabled": true,
+      "imageSmoothingQuality": "low"
+    },
+    "content": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAAXNSR0IArs4c6QAAAAtJREFUCB1jYEAHAAASAAGAFMrMAAAAAElFTkSuQmCC"
+  },
+  "frames": [
+    {
+      "actions": [
+        [
+          5,
+          [
+            1,
+            2,
+            3,
+            4,
+            5,
+            0
+          ]
+        ]
+      ],
+      "incomplete": true
+    }
+  ],
+  "data": [
+    "pattern",
+    "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAAXNSR0IArs4c6QAAABNJREFUCB1j/M/AAEQMDEwgAgQAHxcCAmtAm/sAAAAASUVORK5CYII=",
+    "no-repeat",
+    [
+      0,
+      1,
+      2
+    ],
+    "#ffffff",
+    "arc"
+  ]
+}
+
+-- Running test case: Canvas.recording2D.ActionParameterNaN
+PASS: The recording should have 1 frame.
+PASS: The first frame should have 1 action.
+PASS: The action should have 1 parameter.
+PASS: The parameter should be null.
+

Added: trunk/LayoutTests/inspector/canvas/recording-2d.html (0 => 220008)


--- trunk/LayoutTests/inspector/canvas/recording-2d.html	                        (rev 0)
+++ trunk/LayoutTests/inspector/canvas/recording-2d.html	2017-07-28 18:22:17 UTC (rev 220008)
@@ -0,0 +1,504 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<script>
+let ctx = null;
+
+// 2x2 red square
+let image = document.createElement("img");
+image.src = ""
+
+// Invalid video
+let video = document.createElement("video");
+
+// Blank canvas
+let canvas = document.createElement("canvas");
+canvas.width = 2;
+canvas.height = 2;
+
+let linearGradient = null;
+
+let radialGradient = null;
+
+let pattern = null;
+
+let path12 = new Path2D("M 1 2");
+let path34 = new Path2D("M 3 4");
+
+let imageData14 = new ImageData(1, 4);
+let imageData23 = new ImageData(2, 3);
+
+function load() {
+    ctx = canvas.getContext("2d");
+    linearGradient = ctx.createLinearGradient(1, 2, 3, 4);
+    radialGradient = ctx.createRadialGradient(1, 2, 3, 4, 5, 6);
+    pattern = ctx.createPattern(image, "no-repeat");
+
+    document.body.appendChild(canvas);
+
+    runTest();
+}
+
+function ignoreException(f){
+    try {
+        f();
+    } catch (e) { }
+}
+
+let timeoutID = NaN;
+
+function cancelActions() {
+    clearTimeout(timeoutID);
+}
+
+function performActions() {
+    let frames = [
+        () => {
+            ignoreException(() => ctx.arc(1, 2, 3, 4, 5));
+            ignoreException(() => ctx.arc(6, 7, 8, 9, 10, true));
+        },
+        () => {
+            ignoreException(() => ctx.arcTo(1, 2, 3, 4, 5));
+        },
+        () => {
+            ctx.beginPath();
+        },
+        () => {
+            ctx.bezierCurveTo(1, 2, 3, 4, 5, 6);
+        },
+        () => {
+            ctx.canvas;
+        },
+        () => {
+            ctx.clearRect(1, 2, 3, 4);
+        },
+        () => {
+            ctx.clearShadow();
+        },
+        () => {
+            ctx.clip();
+            ctx.clip("evenodd");
+            ctx.clip(path12);
+            ctx.clip(path34, "evenodd");
+        },
+        () => {
+            ctx.closePath();
+        },
+        () => {
+            ctx.commit();
+        },
+        () => {
+            ignoreException(() => ctx.createImageData(imageData14));
+            ignoreException(() => ctx.createImageData(2, 3));
+        },
+        () => {
+            ignoreException(() => ctx.createLinearGradient(1, 2, 3, 4));
+        },
+        () => {
+            ignoreException(() => ctx.createPattern(image, "testA"));
+            ignoreException(() => ctx.createPattern(video, "testB"));
+            ignoreException(() => ctx.createPattern(canvas, "testC"));
+        },
+        () => {
+            ignoreException(() => ctx.createRadialGradient(1, 2, 3, 4, 5, 6));
+        },
+        () => {
+            ctx.direction;
+            ctx.direction = "test";
+        },
+        () => {
+            ctx.drawFocusIfNeeded(document.body);
+            ctx.drawFocusIfNeeded(path12, document.body);
+        },
+        () => {
+            ignoreException(() => ctx.drawImage(image, 1, 2));
+            ignoreException(() => ctx.drawImage(video, 3, 4));
+            ignoreException(() => ctx.drawImage(canvas, 5, 6));
+            ignoreException(() => ctx.drawImage(image, 7, 8, 9, 10));
+            ignoreException(() => ctx.drawImage(video, 11, 12, 13, 14));
+            ignoreException(() => ctx.drawImage(canvas, 15, 16, 17, 18));
+            ignoreException(() => ctx.drawImage(image, 19, 20, 21, 22, 23, 24, 25, 26));
+            ignoreException(() => ctx.drawImage(video, 27, 28, 29, 30, 31, 32, 33, 34));
+            ignoreException(() => ctx.drawImage(canvas, 35, 36, 37, 38, 39, 40, 41 ,42));
+        },
+        () => {
+            ctx.drawImageFromRect(image, 1, 2, 3, 4, 5, 6, 7, 8)
+            ctx.drawImageFromRect(image, 9, 10, 11, 12, 13, 14, 15, 16, "test");
+        },
+        () => {
+            ignoreException(() => ctx.ellipse(1, 2, 3, 4, 5, 6, 7));
+            ignoreException(() => ctx.ellipse(8, 9, 10, 11, 12, 13, 14, true));
+        },
+        () => {
+            ctx.fill();
+            ctx.fill("evenodd");
+            ctx.fill(path12);
+            ctx.fill(path34, "evenodd");
+        },
+        () => {
+            ctx.fillRect(1, 2, 3, 4);
+        },
+        () => {
+            ctx.fillStyle;
+            ctx.fillStyle = "test";
+            ctx.fillStyle = linearGradient;
+            ctx.fillStyle = radialGradient;
+            ctx.fillStyle = pattern;
+        },
+        () => {
+            ctx.fillText("testA", 1, 2);
+            ctx.fillText("testB", 3, 4, 5);
+        },
+        () => {
+            ctx.font;
+            ctx.font = "test";
+        },
+        () => {
+            ignoreException(() => ctx.getImageData(1, 2, 3, 4));
+        },
+        () => {
+            ctx.getLineDash();
+        },
+        () => {
+            ctx.getTransform();
+        },
+        () => {
+            ctx.globalAlpha;
+            ctx.globalAlpha = 0;
+        },
+        () => {
+            ctx.globalCompositeOperation;
+            ctx.globalCompositeOperation = "test";
+        },
+        () => {
+            ctx.imageSmoothingEnabled;
+            ctx.imageSmoothingEnabled = true;
+        },
+        () => {
+            ctx.imageSmoothingQuality;
+            ctx.imageSmoothingQuality = "low";
+        },
+        () => {
+            ctx.isPointInPath(path12, 5, 6);
+            ctx.isPointInPath(path34, 7, 8, "evenodd");
+            ctx.isPointInPath(9, 10);
+            ctx.isPointInPath(11, 12, "evenodd");
+        },
+        () => {
+            ctx.isPointInStroke(path12, 3, 4);
+            ctx.isPointInStroke(5, 6);
+        },
+        () => {
+            ctx.lineCap;
+            ctx.lineCap = "test";
+        },
+        () => {
+            ctx.lineDashOffset;
+            ctx.lineDashOffset = 1;
+        },
+        () => {
+            ctx.lineJoin;
+            ctx.lineJoin = "test";
+        },
+        () => {
+            ctx.lineTo(1, 2);
+        },
+        () => {
+            ctx.lineWidth;
+            ctx.lineWidth = 1;
+        },
+        () => {
+            ctx.measureText("test");
+        },
+        () => {
+            ctx.miterLimit;
+            ctx.miterLimit = 1;
+        },
+        () => {
+            ctx.moveTo(1, 2);
+        },
+        () => {
+            ctx.putImageData(imageData14, 5, 6);
+            ctx.putImageData(imageData23, 7, 8, 9, 10, 11, 12);
+        },
+        () => {
+            ctx.quadraticCurveTo(1, 2, 3, 4);
+        },
+        () => {
+            ctx.rect(1, 2, 3, 4);
+        },
+        () => {
+            ctx.resetTransform();
+        },
+        () => {
+            ctx.restore();
+        },
+        () => {
+            ctx.rotate(1);
+        },
+        () => {
+            ctx.save();
+        },
+        () => {
+            ctx.scale(1, 2);
+        },
+        () => {
+            ctx.setAlpha();
+            ctx.setAlpha(1);
+        },
+        () => {
+            ctx.setCompositeOperation();
+            ctx.setCompositeOperation("test");
+        },
+        () => {
+            ctx.setFillColor("testA");
+            ctx.setFillColor("testB", 1);
+            ctx.setFillColor(2);
+            ctx.setFillColor(3, 4);
+            ctx.setFillColor(5, 6, 7, 8);
+            ctx.setFillColor(9, 10, 11, 12, 13);
+        },
+        () => {
+            ctx.setLineCap();
+            ctx.setLineCap("test");
+        },
+        () => {
+            ctx.setLineDash([1, 2]);
+        },
+        () => {
+            ctx.setLineJoin();
+            ctx.setLineJoin("test");
+        },
+        () => {
+            ctx.setLineWidth();
+            ctx.setLineWidth(1);
+        },
+        () => {
+            ctx.setMiterLimit();
+            ctx.setMiterLimit(1);
+        },
+        () => {
+            ctx.setShadow(1, 2, 3);
+            ctx.setShadow(4, 5, 6, "test", 7);
+            ctx.setShadow(8, 9, 10, 11);
+            ctx.setShadow(12, 13, 14, 15, 16);
+            ctx.setShadow(17, 18, 19, 20, 21, 22, 23);
+            ctx.setShadow(24, 25, 26, 27, 28, 29, 30, 31);
+        },
+        () => {
+            ctx.setStrokeColor("testA");
+            ctx.setStrokeColor("testB", 1);
+            ctx.setStrokeColor(2);
+            ctx.setStrokeColor(3, 4);
+            ctx.setStrokeColor(5, 6, 7, 8);
+            ctx.setStrokeColor(9, 10, 11, 12, 13);
+        },
+        () => {
+            ctx.setTransform(1, 2, 3, 4, 5, 6);
+            ignoreException(() => ctx.setTransform());
+            ignoreException(() => ctx.setTransform(new DOMMatrix([7, 8, 9, 10, 11, 12])));
+        },
+        () => {
+            ctx.shadowBlur;
+            ctx.shadowBlur = 1;
+        },
+        () => {
+            ctx.shadowColor;
+            ctx.shadowColor = "test";
+        },
+        () => {
+            ctx.shadowOffsetX;
+            ctx.shadowOffsetX = 1;
+        },
+        () => {
+            ctx.shadowOffsetY;
+            ctx.shadowOffsetY = 1;
+        },
+        () => {
+            ctx.stroke();
+            ctx.stroke(path12);
+        },
+        () => {
+            ctx.strokeRect(1, 2, 3, 4);
+        },
+        () => {
+            ctx.strokeStyle;
+            ctx.strokeStyle = "test";
+            ctx.strokeStyle = linearGradient;
+            ctx.strokeStyle = radialGradient;
+            ctx.strokeStyle = pattern;
+        },
+        () => {
+            ctx.strokeText("testA", 1, 2);
+            ctx.strokeText("testB", 3, 4, 5);
+        },
+        () => {
+            ctx.textAlign;
+            ctx.textAlign = "test";
+        },
+        () => {
+            ctx.textBaseline;
+            ctx.textBaseline = "test";
+        },
+        () => {
+            ctx.transform(1, 2, 3, 4, 5, 6);
+        },
+        () => {
+            ctx.translate(1, 2);
+        },
+        () => {
+            ctx.webkitBackingStorePixelRatio;
+        },
+        () => {
+            ignoreException(() => ctx.webkitGetImageDataHD(1, 2, 3, 4));
+        },
+        () => {
+            ctx.webkitImageSmoothingEnabled;
+            ctx.webkitImageSmoothingEnabled = true;
+        },
+        () => {
+            ctx.webkitLineDash;
+            ctx.webkitLineDash = [1, 2];
+        },
+        () => {
+            ctx.webkitLineDashOffset;
+            ctx.webkitLineDashOffset = 1;
+        },
+        () => {
+            ctx.webkitPutImageDataHD(imageData14, 5, 6);
+            ctx.webkitPutImageDataHD(imageData23, 7, 8, 9, 10, 11, 12);
+        },
+        () => {
+            TestPage.dispatchEventToFrontend("LastFrame");
+        },
+    ];
+    let index = 0;
+    function f() {
+        frames[index++]();
+        if (index < frames.length)
+            timeoutID = setTimeout(f, 0);
+    };
+    f();
+}
+
+function performNaNActions() {
+    ctx.globalAlpha = NaN;
+}
+
+function test() {
+    let suite = InspectorTest.createAsyncSuite("Canvas.recording2D");
+
+    function getCanvas() {
+        let canvases = WebInspector.canvasManager.canvases.filter((canvas) => canvas.contextType === WebInspector.Canvas.ContextType.Canvas2D);
+        InspectorTest.assert(canvases.length === 1, "There should only be one canvas-2d.");
+        if (canvases.length !== 1)
+            return null;
+        return canvases[0];
+    }
+
+    function requestRecording(resolve, reject, {singleFrame, memoryLimit} = {}) {
+        let canvas = getCanvas();
+        if (!canvas) {
+            reject("Missing 2D canvas.");
+            return;
+        }
+
+        WebInspector.canvasManager.awaitEvent(WebInspector.CanvasManager.Event.RecordingFinished)
+        .then((event) => {
+            InspectorTest.evaluateInPage(`cancelActions()`);
+
+            let json = event.data.recording.toJSON();
+            InspectorTest.log(JSON.stringify(json, null, 2));
+        })
+        .then(resolve, reject);
+
+        CanvasAgent.requestRecording(canvas.identifier, singleFrame, memoryLimit, (error) => {
+            if (error) {
+                reject(error);
+                return;
+            }
+
+            InspectorTest.evaluateInPage(`performActions()`);
+        });
+
+        return canvas;
+    }
+
+    suite.addTestCase({
+        name: "Canvas.recording2D.singleFrame",
+        description: "Check that the recording is stopped after a single frame.",
+        test(resolve, reject) {
+            requestRecording(resolve, reject, {singleFrame: true});
+        },
+    });
+
+    suite.addTestCase({
+        name: "Canvas.recording2D.multipleFrames",
+        description: "Check that recording data is serialized correctly for multiple frames.",
+        test(resolve, reject) {
+            let canvas = requestRecording(resolve, reject, {singleFrame: false});
+
+            InspectorTest.singleFireEventListener("LastFrame", () => {
+                CanvasAgent.cancelRecording(canvas.identifier, (error) => {
+                    if (error) {
+                        reject(error);
+                        return;
+                    }
+                });
+            });
+        },
+    });
+
+    suite.addTestCase({
+        name: "Canvas.recording2D.memoryLimit",
+        description: "Check that the recording is stopped when it reaches the memory limit.",
+        test(resolve, reject) {
+            requestRecording(resolve, reject, {memoryLimit: 10});
+        },
+    });
+
+    suite.addTestCase({
+        name: "Canvas.recording2D.ActionParameterNaN",
+        description: "Check that NaN is converted into the proper value for serialization.",
+        test(resolve, reject) {
+            let canvas = getCanvas();
+            if (!canvas) {
+                reject("Missing 2D canvas.");
+                return;
+            }
+
+            WebInspector.canvasManager.awaitEvent(WebInspector.CanvasManager.Event.RecordingFinished)
+            .then((event) => {
+                let recording = event.data.recording.toJSON();
+
+                let frames = recording.frames;
+                InspectorTest.expectEqual(frames.length, 1, "The recording should have 1 frame.");
+
+                let actions = frames[0].actions;
+                InspectorTest.expectEqual(actions.length, 1, "The first frame should have 1 action.");
+                InspectorTest.expectEqual(actions[0][1].length, 1, "The action should have 1 parameter.");
+                InspectorTest.expectEqual(actions[0][1][0], null, "The parameter should be null.");
+            })
+            .then(resolve, reject);
+
+            const singleFrame = true;
+            CanvasAgent.requestRecording(canvas.identifier, singleFrame, (error) => {
+                if (error) {
+                    reject(error);
+                    return;
+                }
+
+                InspectorTest.evaluateInPage(`performNaNActions()`);
+            });
+        },
+    });
+
+    suite.runTestCasesAndFinish();
+}
+</script>
+</head>
+<body _onload_="load()">
+    <p>Test that CanvasManager is able to record actions made to 2D canvas contexts.</p>
+</body>
+</html>

Added: trunk/LayoutTests/inspector/canvas/recording-expected.txt (0 => 220008)


--- trunk/LayoutTests/inspector/canvas/recording-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/inspector/canvas/recording-expected.txt	2017-07-28 18:22:17 UTC (rev 220008)
@@ -0,0 +1,12 @@
+Test general cases of CanvasAgent recording calls.
+
+
+== Running test suite: Canvas.recording
+-- Running test case: Canvas.requestRecording.InvalidCanvasId
+PASS: Should produce an error.
+Error: No canvas for given identifier.
+
+-- Running test case: Canvas.cancelRecording.InvalidCanvasId
+PASS: Should produce an error.
+Error: No canvas for given identifier.
+

Added: trunk/LayoutTests/inspector/canvas/recording.html (0 => 220008)


--- trunk/LayoutTests/inspector/canvas/recording.html	                        (rev 0)
+++ trunk/LayoutTests/inspector/canvas/recording.html	2017-07-28 18:22:17 UTC (rev 220008)
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<script>
+function test() {
+    let suite = InspectorTest.createAsyncSuite("Canvas.recording");
+
+    suite.addTestCase({
+        name: "Canvas.requestRecording.InvalidCanvasId",
+        description: "Invalid canvas identifiers should cause an error.",
+        test(resolve, reject) {
+            const canvasId = "DOES_NOT_EXIST";
+            CanvasAgent.requestRecording(canvasId, (error) => {
+                InspectorTest.expectThat(error, "Should produce an error.");
+                InspectorTest.log("Error: " + error);
+                resolve();
+            });
+        },
+    });
+
+    suite.addTestCase({
+        name: "Canvas.cancelRecording.InvalidCanvasId",
+        description: "Invalid canvas identifiers should cause an error.",
+        test(resolve, reject) {
+            const canvasId = "DOES_NOT_EXIST";
+            CanvasAgent.cancelRecording(canvasId, (error) => {
+                InspectorTest.expectThat(error, "Should produce an error.");
+                InspectorTest.log("Error: " + error);
+                resolve();
+            });
+        },
+    });
+
+    suite.runTestCasesAndFinish();
+}
+</script>
+</head>
+<body _onload_="runTest()">
+    <p>Test general cases of CanvasAgent recording calls.</p>
+</body>
+</html>

Modified: trunk/Source/WebCore/CMakeLists.txt (220007 => 220008)


--- trunk/Source/WebCore/CMakeLists.txt	2017-07-28 18:06:59 UTC (rev 220007)
+++ trunk/Source/WebCore/CMakeLists.txt	2017-07-28 18:22:17 UTC (rev 220008)
@@ -1136,6 +1136,7 @@
 
     bindings/js/CachedModuleScriptLoader.cpp
     bindings/js/CachedScriptFetcher.cpp
+    bindings/js/CallTracer.cpp
     bindings/js/CommonVM.cpp
     bindings/js/DOMWrapperWorld.cpp
     bindings/js/GCController.cpp

Modified: trunk/Source/WebCore/ChangeLog (220007 => 220008)


--- trunk/Source/WebCore/ChangeLog	2017-07-28 18:06:59 UTC (rev 220007)
+++ trunk/Source/WebCore/ChangeLog	2017-07-28 18:22:17 UTC (rev 220008)
@@ -1,3 +1,68 @@
+2017-07-28  Devin Rousso  <[email protected]>
+
+        Web Inspector: Record actions performed on CanvasRenderingContext2D
+        https://bugs.webkit.org/show_bug.cgi?id=174482
+
+        Reviewed by Joseph Pecoraro.
+
+        Tests: inspector/canvas/recording-2d.html
+               inspector/canvas/recording.html
+
+        * html/canvas/CanvasRenderingContext2D.idl:
+        Add CallTracingCallback to interface to record all API calls.
+
+        * html/HTMLCanvasElement.cpp:
+        (WebCore::HTMLCanvasElement::paint):
+        If a recording is active, mark the current frame as completed.
+
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (GenerateAttributeGetterBodyDefinition):
+        (GenerateAttributeSetterBodyDefinition):
+        (GenerateImplementationFunctionCall):
+        (GenerateCallTracerParameter):
+        (GenerateCallTracer):
+        * bindings/scripts/test/TestCallTracer.idl:
+        * bindings/scripts/test/JS/JSTestCallTracer.cpp:
+        (WebCore::setJSTestCallTracerTestAttributeInterfaceSetter):
+        (WebCore::setJSTestCallTracerTestAttributeSpecifiedSetter):
+        (WebCore::jsTestCallTracerTestAttributeWithVariantGetter):
+        (WebCore::jsTestCallTracerTestAttributeWithVariant):
+        (WebCore::setJSTestCallTracerTestAttributeWithVariantSetter):
+        (WebCore::setJSTestCallTracerTestAttributeWithVariant):
+        (WebCore::jsTestCallTracerPrototypeFunctionTestOperationInterfaceBody):
+        (WebCore::jsTestCallTracerPrototypeFunctionTestOperationSpecifiedBody):
+        (WebCore::jsTestCallTracerPrototypeFunctionTestOperationWithArgumentsBody):
+        (WebCore::jsTestCallTracerPrototypeFunctionTestOperationWithNullableArgumentBody):
+        (WebCore::jsTestCallTracerPrototypeFunctionTestOperationWithVariantArgumentBody):
+        (WebCore::jsTestCallTracerPrototypeFunctionTestOperationWithVariantArgument):
+        * inspector/InspectorCanvas.h:
+        * inspector/InspectorCanvas.cpp:
+        (WebCore::InspectorCanvas::recordAction):
+        (WebCore::InspectorCanvas::buildAction):
+        Change CallTracer IDL generation to flatten any variants so that all types for the
+        parameters of an action are able to be listed in a single variant. This prevents possible
+        ambiguity when constructing the variant, as they require that exactly one type be
+        constructible and a sub-variant might not satisfy that condition. This was only an issue for
+        older mac SDKs.
+
+        * bindings/js/CallTracer.h:
+        * bindings/js/CallTracer.cpp:
+        (WebCore::CallTracer::recordCanvasAction):
+        * bindings/js/CallTracerTypes.h:
+        * inspector/InspectorCanvasAgent.h:
+        * inspector/InspectorCanvasAgent.cpp:
+        (WebCore::InspectorCanvasAgent::recordCanvasAction):
+        * inspector/InspectorInstrumentation.h:
+        * inspector/InspectorInstrumentation.cpp:
+        (WebCore::InspectorInstrumentation::recordCanvasAction):
+        (WebCore::InspectorInstrumentation::recordCanvasActionImpl):
+        Rename CanvasActionParameterVariant to RecordCanvasActionVariant to match what is expected by
+        the IDL generator. Also remove unnecessary includes now that they are in CallTracerTypes.h.
+
+        * CMakeLists.txt:
+        * bindings/js/JSBindingsAllInOne.cpp:
+        Add CallTracer for CMake builds.
+
 2017-07-28  Sam Weinig  <[email protected]>
 
         [WebIDL] Split-up and cleanup Fetch IDL files in preparation for removing unnecessary js builtins

Modified: trunk/Source/WebCore/bindings/js/CallTracer.cpp (220007 => 220008)


--- trunk/Source/WebCore/bindings/js/CallTracer.cpp	2017-07-28 18:06:59 UTC (rev 220007)
+++ trunk/Source/WebCore/bindings/js/CallTracer.cpp	2017-07-28 18:22:17 UTC (rev 220008)
@@ -26,20 +26,12 @@
 #include "config.h"
 #include "CallTracer.h"
 
-#include "CanvasGradient.h"
-#include "CanvasPattern.h"
 #include "CanvasRenderingContext.h"
-#include "DOMPath.h"
-#include "Element.h"
-#include "HTMLCanvasElement.h"
-#include "HTMLImageElement.h"
-#include "HTMLVideoElement.h"
-#include "ImageData.h"
 #include "InspectorInstrumentation.h"
 
 namespace WebCore {
 
-void CallTracer::recordCanvasAction(CanvasRenderingContext& canvasRenderingContext, const String& name, Vector<CanvasActionParameterVariant>&& parameters)
+void CallTracer::recordCanvasAction(CanvasRenderingContext& canvasRenderingContext, const String& name, Vector<RecordCanvasActionVariant>&& parameters)
 {
     InspectorInstrumentation::recordCanvasAction(canvasRenderingContext, name, WTFMove(parameters));
 }

Modified: trunk/Source/WebCore/bindings/js/CallTracer.h (220007 => 220008)


--- trunk/Source/WebCore/bindings/js/CallTracer.h	2017-07-28 18:06:59 UTC (rev 220007)
+++ trunk/Source/WebCore/bindings/js/CallTracer.h	2017-07-28 18:22:17 UTC (rev 220008)
@@ -35,7 +35,7 @@
 
 class CallTracer {
 public:
-    static void recordCanvasAction(CanvasRenderingContext&, const String&, Vector<CanvasActionParameterVariant>&& = { });
+    static void recordCanvasAction(CanvasRenderingContext&, const String&, Vector<RecordCanvasActionVariant>&& = { });
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/bindings/js/CallTracerTypes.h (220007 => 220008)


--- trunk/Source/WebCore/bindings/js/CallTracerTypes.h	2017-07-28 18:06:59 UTC (rev 220007)
+++ trunk/Source/WebCore/bindings/js/CallTracerTypes.h	2017-07-28 18:22:17 UTC (rev 220008)
@@ -25,8 +25,17 @@
 
 #pragma once
 
+#include "CanvasGradient.h"
+#include "CanvasPattern.h"
 #include "CanvasRenderingContext2D.h"
 #include "DOMMatrixInit.h"
+#include "DOMPath.h"
+#include "Element.h"
+#include "HTMLCanvasElement.h"
+#include "HTMLImageElement.h"
+#include "HTMLVideoElement.h"
+#include "ImageData.h"
+#include <wtf/RefPtr.h>
 #include <wtf/Variant.h>
 #include <wtf/Vector.h>
 #include <wtf/text/WTFString.h>
@@ -33,17 +42,21 @@
 
 namespace WebCore {
 
-class DOMPath;
-class Element;
-class HTMLImageElement;
-class ImageData;
-
 typedef Variant<
+    CanvasRenderingContext2D::ImageSmoothingQuality,
+    CanvasRenderingContext2D::WindingRule,
+    DOMMatrixInit,
+    DOMPath*,
     Element*,
     HTMLImageElement*,
     ImageData*,
-    DOMMatrixInit,
-    DOMPath*,
+    RefPtr<CanvasGradient>,
+    RefPtr<CanvasPattern>,
+    RefPtr<HTMLCanvasElement>,
+    RefPtr<HTMLImageElement>,
+#if ENABLE(VIDEO)
+    RefPtr<HTMLVideoElement>,
+#endif
     Vector<float>,
     String,
     double,
@@ -50,11 +63,7 @@
     float,
     int,
     bool,
-    std::optional<float>,
-    CanvasImageSource,
-    CanvasRenderingContext2D::Style,
-    CanvasRenderingContext2D::WindingRule,
-    CanvasRenderingContext2D::ImageSmoothingQuality
-> CanvasActionParameterVariant;
+    std::optional<float>
+> RecordCanvasActionVariant;
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/bindings/js/JSBindingsAllInOne.cpp (220007 => 220008)


--- trunk/Source/WebCore/bindings/js/JSBindingsAllInOne.cpp	2017-07-28 18:06:59 UTC (rev 220007)
+++ trunk/Source/WebCore/bindings/js/JSBindingsAllInOne.cpp	2017-07-28 18:22:17 UTC (rev 220008)
@@ -26,6 +26,7 @@
 // This all-in-one cpp file cuts down on template bloat to allow us to build our Windows release build.
 
 #include "CachedModuleScriptLoader.cpp"
+#include "CallTracer.cpp"
 #include "DOMWrapperWorld.cpp"
 #include "GCController.cpp"
 #include "JSAnimationTimelineCustom.cpp"

Modified: trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm (220007 => 220008)


--- trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm	2017-07-28 18:06:59 UTC (rev 220007)
+++ trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm	2017-07-28 18:22:17 UTC (rev 220008)
@@ -4724,10 +4724,8 @@
 
         my $callTracingCallback = $attribute->extendedAttributes->{CallTracingCallback} || $interface->extendedAttributes->{CallTracingCallback};
         if ($callTracingCallback) {
-            AddToImplIncludes("CallTracer.h");
-
-            push(@$outputArray, "    if (UNLIKELY(impl.callTracingActive()))\n");
-            push(@$outputArray, "        CallTracer::$callTracingCallback(impl, ASCIILiteral(\"" . $attribute->name . "\"));\n");
+            my @callTracerArguments = ();
+            GenerateCallTracer($outputArray, $callTracingCallback, $attribute->name, \@callTracerArguments, "    ");
         }
 
         push(@$outputArray, "    JSValue result = ${toJSExpression};\n");
@@ -4914,10 +4912,10 @@
 
         my $callTracingCallback = $attribute->extendedAttributes->{CallTracingCallback} || $interface->extendedAttributes->{CallTracingCallback};
         if ($callTracingCallback) {
-            AddToImplIncludes("CallTracer.h");
-
-            push(@$outputArray, "    if (UNLIKELY(impl.callTracingActive()))\n");
-            push(@$outputArray, "        CallTracer::$callTracingCallback(impl, ASCIILiteral(\"" . $attribute->name . "\"), { nativeValue });\n");
+            my $indent = "    ";
+            my @callTracerArguments = ();
+            push(@callTracerArguments, GenerateCallTracerParameter("nativeValue", $attribute->type, $indent));
+            GenerateCallTracer($outputArray, $callTracingCallback, $attribute->name, \@callTracerArguments, $indent);
         }
 
         push(@$outputArray, "    ${functionString};\n");
@@ -6057,15 +6055,11 @@
 
     my $callTracingCallback = $operation->extendedAttributes->{CallTracingCallback} || $interface->extendedAttributes->{CallTracingCallback};
     if ($callTracingCallback) {
-        AddToImplIncludes("CallTracer.h");
-
-        my @inspectorRecordingArguments = ();
+        my @callTracerArguments = ();
         foreach my $argument (@{$operation->arguments}) {
-            push(@inspectorRecordingArguments, $argument->name);
+            push(@callTracerArguments, GenerateCallTracerParameter($argument->name, $argument->type, $indent));
         }
-
-        push(@$outputArray, $indent . "if (UNLIKELY(impl.callTracingActive()))\n");
-        push(@$outputArray, $indent . "    CallTracer::$callTracingCallback(impl, ASCIILiteral(\"" . $operation->name . "\"), { " . join(", ", @inspectorRecordingArguments) . " });\n");
+        GenerateCallTracer($outputArray, $callTracingCallback, $operation->name, \@callTracerArguments, $indent);
     }
 
     if (OperationHasForcedReturnValue($operation)) {
@@ -7264,4 +7258,40 @@
     }
 }
 
+sub GenerateCallTracerParameter()
+{
+    my ($name, $type, $indent) = @_;
+
+    if ($type->isUnion) {
+        return $indent . "    WTF::visit([&] (auto& value) { callTracerParameters.append(value); }, " . $name . ");";
+    }
+
+    return $indent . "    callTracerParameters.append(" . $name . ");";
+}
+
+sub GenerateCallTracer()
+{
+    my ($outputArray, $callTracingCallback, $name, $arguments, $indent) = @_;
+
+    AddToImplIncludes("CallTracer.h");
+
+    my $count = scalar(@$arguments);
+
+    push(@$outputArray, $indent . "if (UNLIKELY(impl.callTracingActive()))");
+    if ($count) {
+        push(@$outputArray, " {\n");
+        push(@$outputArray, $indent . "    Vector<" . $codeGenerator->WK_ucfirst($callTracingCallback) . "Variant> callTracerParameters;\n");
+        push(@$outputArray, join("\n", @$arguments));
+    }
+    push(@$outputArray, "\n");
+    push(@$outputArray, $indent . "    CallTracer::" . $callTracingCallback . "(impl, ASCIILiteral(\"" . $name . "\")");
+    if ($count) {
+        push(@$outputArray, ", WTFMove(callTracerParameters)");
+    }
+    push(@$outputArray, ");\n");
+    if ($count) {
+        push(@$outputArray, $indent . "}\n")
+    }
+}
+
 1;

Modified: trunk/Source/WebCore/bindings/scripts/test/JS/JSTestCallTracer.cpp (220007 => 220008)


--- trunk/Source/WebCore/bindings/scripts/test/JS/JSTestCallTracer.cpp	2017-07-28 18:06:59 UTC (rev 220007)
+++ trunk/Source/WebCore/bindings/scripts/test/JS/JSTestCallTracer.cpp	2017-07-28 18:22:17 UTC (rev 220008)
@@ -30,7 +30,9 @@
 #include "JSDOMConvertNullable.h"
 #include "JSDOMConvertNumbers.h"
 #include "JSDOMConvertStrings.h"
+#include "JSDOMConvertUnion.h"
 #include "JSDOMExceptionHandling.h"
+#include "JSDOMGlobalObject.h"
 #include "JSDOMOperation.h"
 #include "JSDOMWrapperCache.h"
 #include "JSNode.h"
@@ -37,6 +39,7 @@
 #include <runtime/FunctionPrototype.h>
 #include <runtime/JSCInlines.h>
 #include <wtf/GetPtr.h>
+#include <wtf/Variant.h>
 
 using namespace JSC;
 
@@ -48,6 +51,7 @@
 JSC::EncodedJSValue JSC_HOST_CALL jsTestCallTracerPrototypeFunctionTestOperationSpecified(JSC::ExecState*);
 JSC::EncodedJSValue JSC_HOST_CALL jsTestCallTracerPrototypeFunctionTestOperationWithArguments(JSC::ExecState*);
 JSC::EncodedJSValue JSC_HOST_CALL jsTestCallTracerPrototypeFunctionTestOperationWithNullableArgument(JSC::ExecState*);
+JSC::EncodedJSValue JSC_HOST_CALL jsTestCallTracerPrototypeFunctionTestOperationWithVariantArgument(JSC::ExecState*);
 
 // Attributes
 
@@ -57,6 +61,8 @@
 bool setJSTestCallTracerTestAttributeInterface(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
 JSC::EncodedJSValue jsTestCallTracerTestAttributeSpecified(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
 bool setJSTestCallTracerTestAttributeSpecified(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
+JSC::EncodedJSValue jsTestCallTracerTestAttributeWithVariant(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
+bool setJSTestCallTracerTestAttributeWithVariant(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
 
 class JSTestCallTracerPrototype : public JSC::JSNonFinalObject {
 public:
@@ -107,10 +113,12 @@
     { "constructor", DontEnum, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestCallTracerConstructor), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSTestCallTracerConstructor) } },
     { "testAttributeInterface", CustomAccessor | DOMAttribute, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestCallTracerTestAttributeInterface), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSTestCallTracerTestAttributeInterface) } },
     { "testAttributeSpecified", CustomAccessor | DOMAttribute, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestCallTracerTestAttributeSpecified), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSTestCallTracerTestAttributeSpecified) } },
+    { "testAttributeWithVariant", CustomAccessor | DOMAttribute, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestCallTracerTestAttributeWithVariant), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSTestCallTracerTestAttributeWithVariant) } },
     { "testOperationInterface", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestCallTracerPrototypeFunctionTestOperationInterface), (intptr_t) (0) } },
     { "testOperationSpecified", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestCallTracerPrototypeFunctionTestOperationSpecified), (intptr_t) (0) } },
     { "testOperationWithArguments", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestCallTracerPrototypeFunctionTestOperationWithArguments), (intptr_t) (3) } },
     { "testOperationWithNullableArgument", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestCallTracerPrototypeFunctionTestOperationWithNullableArgument), (intptr_t) (1) } },
+    { "testOperationWithVariantArgument", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestCallTracerPrototypeFunctionTestOperationWithVariantArgument), (intptr_t) (1) } },
 };
 
 const ClassInfo JSTestCallTracerPrototype::s_info = { "TestCallTracerPrototype", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSTestCallTracerPrototype) };
@@ -212,8 +220,11 @@
     auto& impl = thisObject.wrapped();
     auto nativeValue = convert<IDLBoolean>(state, value);
     RETURN_IF_EXCEPTION(throwScope, false);
-    if (UNLIKELY(impl.callTracingActive()))
-        CallTracer::testCallTracerInterface(impl, ASCIILiteral("testAttributeInterface"), { nativeValue });
+    if (UNLIKELY(impl.callTracingActive())) {
+        Vector<TestCallTracerInterfaceVariant> callTracerParameters;
+        callTracerParameters.append(nativeValue);
+        CallTracer::testCallTracerInterface(impl, ASCIILiteral("testAttributeInterface"), WTFMove(callTracerParameters));
+    }
     impl.setTestAttributeInterface(WTFMove(nativeValue));
     return true;
 }
@@ -246,8 +257,11 @@
     auto& impl = thisObject.wrapped();
     auto nativeValue = convert<IDLBoolean>(state, value);
     RETURN_IF_EXCEPTION(throwScope, false);
-    if (UNLIKELY(impl.callTracingActive()))
-        CallTracer::testCallTracerAttribute(impl, ASCIILiteral("testAttributeSpecified"), { nativeValue });
+    if (UNLIKELY(impl.callTracingActive())) {
+        Vector<TestCallTracerAttributeVariant> callTracerParameters;
+        callTracerParameters.append(nativeValue);
+        CallTracer::testCallTracerAttribute(impl, ASCIILiteral("testAttributeSpecified"), WTFMove(callTracerParameters));
+    }
     impl.setTestAttributeSpecified(WTFMove(nativeValue));
     return true;
 }
@@ -257,6 +271,43 @@
     return IDLAttribute<JSTestCallTracer>::set<setJSTestCallTracerTestAttributeSpecifiedSetter>(*state, thisValue, encodedValue, "testAttributeSpecified");
 }
 
+static inline JSValue jsTestCallTracerTestAttributeWithVariantGetter(ExecState& state, JSTestCallTracer& thisObject, ThrowScope& throwScope)
+{
+    UNUSED_PARAM(throwScope);
+    UNUSED_PARAM(state);
+    auto& impl = thisObject.wrapped();
+    if (UNLIKELY(impl.callTracingActive()))
+        CallTracer::testCallTracerInterface(impl, ASCIILiteral("testAttributeWithVariant"));
+    JSValue result = toJS<IDLUnion<IDLBoolean, IDLFloat, IDLDOMString>>(state, *thisObject.globalObject(), impl.testAttributeWithVariant());
+    return result;
+}
+
+EncodedJSValue jsTestCallTracerTestAttributeWithVariant(ExecState* state, EncodedJSValue thisValue, PropertyName)
+{
+    return IDLAttribute<JSTestCallTracer>::get<jsTestCallTracerTestAttributeWithVariantGetter, CastedThisErrorBehavior::Assert>(*state, thisValue, "testAttributeWithVariant");
+}
+
+static inline bool setJSTestCallTracerTestAttributeWithVariantSetter(ExecState& state, JSTestCallTracer& thisObject, JSValue value, ThrowScope& throwScope)
+{
+    UNUSED_PARAM(state);
+    UNUSED_PARAM(throwScope);
+    auto& impl = thisObject.wrapped();
+    auto nativeValue = convert<IDLUnion<IDLBoolean, IDLFloat, IDLDOMString>>(state, value);
+    RETURN_IF_EXCEPTION(throwScope, false);
+    if (UNLIKELY(impl.callTracingActive())) {
+        Vector<TestCallTracerInterfaceVariant> callTracerParameters;
+        WTF::visit([&] (auto& value) { callTracerParameters.append(value); }, nativeValue);
+        CallTracer::testCallTracerInterface(impl, ASCIILiteral("testAttributeWithVariant"), WTFMove(callTracerParameters));
+    }
+    impl.setTestAttributeWithVariant(WTFMove(nativeValue));
+    return true;
+}
+
+bool setJSTestCallTracerTestAttributeWithVariant(ExecState* state, EncodedJSValue thisValue, EncodedJSValue encodedValue)
+{
+    return IDLAttribute<JSTestCallTracer>::set<setJSTestCallTracerTestAttributeWithVariantSetter>(*state, thisValue, encodedValue, "testAttributeWithVariant");
+}
+
 static inline JSC::EncodedJSValue jsTestCallTracerPrototypeFunctionTestOperationInterfaceBody(JSC::ExecState* state, typename IDLOperation<JSTestCallTracer>::ClassParameter castedThis, JSC::ThrowScope& throwScope)
 {
     UNUSED_PARAM(state);
@@ -263,7 +314,7 @@
     UNUSED_PARAM(throwScope);
     auto& impl = castedThis->wrapped();
     if (UNLIKELY(impl.callTracingActive()))
-        CallTracer::testCallTracerInterface(impl, ASCIILiteral("testOperationInterface"), {  });
+        CallTracer::testCallTracerInterface(impl, ASCIILiteral("testOperationInterface"));
     impl.testOperationInterface();
     return JSValue::encode(jsUndefined());
 }
@@ -279,7 +330,7 @@
     UNUSED_PARAM(throwScope);
     auto& impl = castedThis->wrapped();
     if (UNLIKELY(impl.callTracingActive()))
-        CallTracer::testCallTracerOperation(impl, ASCIILiteral("testOperationSpecified"), {  });
+        CallTracer::testCallTracerOperation(impl, ASCIILiteral("testOperationSpecified"));
     impl.testOperationSpecified();
     return JSValue::encode(jsUndefined());
 }
@@ -302,8 +353,13 @@
     RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
     auto c = convert<IDLDOMString>(*state, state->uncheckedArgument(2));
     RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
-    if (UNLIKELY(impl.callTracingActive()))
-        CallTracer::testCallTracerInterface(impl, ASCIILiteral("testOperationWithArguments"), { a, b, c });
+    if (UNLIKELY(impl.callTracingActive())) {
+        Vector<TestCallTracerInterfaceVariant> callTracerParameters;
+        callTracerParameters.append(a);
+        callTracerParameters.append(b);
+        callTracerParameters.append(c);
+        CallTracer::testCallTracerInterface(impl, ASCIILiteral("testOperationWithArguments"), WTFMove(callTracerParameters));
+    }
     impl.testOperationWithArguments(WTFMove(a), WTFMove(b), WTFMove(c));
     return JSValue::encode(jsUndefined());
 }
@@ -322,8 +378,11 @@
         return throwVMError(state, throwScope, createNotEnoughArgumentsError(state));
     auto nodeNullableArg = convert<IDLNullable<IDLInterface<Node>>>(*state, state->uncheckedArgument(0), [](JSC::ExecState& state, JSC::ThrowScope& scope) { throwArgumentTypeError(state, scope, 0, "nodeNullableArg", "TestCallTracer", "testOperationWithNullableArgument", "Node"); });
     RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
-    if (UNLIKELY(impl.callTracingActive()))
-        CallTracer::testCallTracerInterface(impl, ASCIILiteral("testOperationWithNullableArgument"), { nodeNullableArg });
+    if (UNLIKELY(impl.callTracingActive())) {
+        Vector<TestCallTracerInterfaceVariant> callTracerParameters;
+        callTracerParameters.append(nodeNullableArg);
+        CallTracer::testCallTracerInterface(impl, ASCIILiteral("testOperationWithNullableArgument"), WTFMove(callTracerParameters));
+    }
     impl.testOperationWithNullableArgument(WTFMove(nodeNullableArg));
     return JSValue::encode(jsUndefined());
 }
@@ -333,6 +392,29 @@
     return IDLOperation<JSTestCallTracer>::call<jsTestCallTracerPrototypeFunctionTestOperationWithNullableArgumentBody>(*state, "testOperationWithNullableArgument");
 }
 
+static inline JSC::EncodedJSValue jsTestCallTracerPrototypeFunctionTestOperationWithVariantArgumentBody(JSC::ExecState* state, typename IDLOperation<JSTestCallTracer>::ClassParameter castedThis, JSC::ThrowScope& throwScope)
+{
+    UNUSED_PARAM(state);
+    UNUSED_PARAM(throwScope);
+    auto& impl = castedThis->wrapped();
+    if (UNLIKELY(state->argumentCount() < 1))
+        return throwVMError(state, throwScope, createNotEnoughArgumentsError(state));
+    auto variantArg = convert<IDLUnion<IDLBoolean, IDLFloat, IDLDOMString>>(*state, state->uncheckedArgument(0));
+    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
+    if (UNLIKELY(impl.callTracingActive())) {
+        Vector<TestCallTracerInterfaceVariant> callTracerParameters;
+        WTF::visit([&] (auto& value) { callTracerParameters.append(value); }, variantArg);
+        CallTracer::testCallTracerInterface(impl, ASCIILiteral("testOperationWithVariantArgument"), WTFMove(callTracerParameters));
+    }
+    impl.testOperationWithVariantArgument(WTFMove(variantArg));
+    return JSValue::encode(jsUndefined());
+}
+
+EncodedJSValue JSC_HOST_CALL jsTestCallTracerPrototypeFunctionTestOperationWithVariantArgument(ExecState* state)
+{
+    return IDLOperation<JSTestCallTracer>::call<jsTestCallTracerPrototypeFunctionTestOperationWithVariantArgumentBody>(*state, "testOperationWithVariantArgument");
+}
+
 bool JSTestCallTracerOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)
 {
     UNUSED_PARAM(handle);

Modified: trunk/Source/WebCore/bindings/scripts/test/TestCallTracer.idl (220007 => 220008)


--- trunk/Source/WebCore/bindings/scripts/test/TestCallTracer.idl	2017-07-28 18:06:59 UTC (rev 220007)
+++ trunk/Source/WebCore/bindings/scripts/test/TestCallTracer.idl	2017-07-28 18:22:17 UTC (rev 220008)
@@ -23,6 +23,8 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+typedef (boolean or float or DOMString) VariantType;
+
 [
     CallTracingCallback=testCallTracerInterface,
 ] interface TestCallTracer {
@@ -29,10 +31,13 @@
     attribute boolean testAttributeInterface;
     [CallTracingCallback=testCallTracerAttribute] attribute boolean testAttributeSpecified;
 
+    attribute VariantType testAttributeWithVariant;
+
     void testOperationInterface();
     [CallTracingCallback=testCallTracerOperation] void testOperationSpecified();
 
     void testOperationWithArguments(boolean a, float b, DOMString c);
     void testOperationWithNullableArgument(Node? nodeNullableArg);
+    void testOperationWithVariantArgument(VariantType variantArg);
 };
 

Modified: trunk/Source/WebCore/html/HTMLCanvasElement.cpp (220007 => 220008)


--- trunk/Source/WebCore/html/HTMLCanvasElement.cpp	2017-07-28 18:06:59 UTC (rev 220007)
+++ trunk/Source/WebCore/html/HTMLCanvasElement.cpp	2017-07-28 18:22:17 UTC (rev 220008)
@@ -505,6 +505,9 @@
 
 void HTMLCanvasElement::paint(GraphicsContext& context, const LayoutRect& r)
 {
+    if (UNLIKELY(m_context && m_context->callTracingActive()))
+        InspectorInstrumentation::didFinishRecordingCanvasFrame(*this);
+
     // Clear the dirty rect
     m_dirtyRect = FloatRect();
 

Modified: trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.idl (220007 => 220008)


--- trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.idl	2017-07-28 18:06:59 UTC (rev 220007)
+++ trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.idl	2017-07-28 18:22:17 UTC (rev 220008)
@@ -37,6 +37,7 @@
     CustomIsReachable,
     JSGenerateToJSObject,
     JSCustomMarkFunction,
+    CallTracingCallback=recordCanvasAction,
 ] interface CanvasRenderingContext2D {
 
     // back-reference to the canvas

Modified: trunk/Source/WebCore/inspector/InspectorCanvas.cpp (220007 => 220008)


--- trunk/Source/WebCore/inspector/InspectorCanvas.cpp	2017-07-28 18:06:59 UTC (rev 220007)
+++ trunk/Source/WebCore/inspector/InspectorCanvas.cpp	2017-07-28 18:22:17 UTC (rev 220008)
@@ -99,7 +99,7 @@
     return m_initialState && m_frames;
 }
 
-void InspectorCanvas::recordAction(const String& name, Vector<CanvasActionParameterVariant>&& parameters)
+void InspectorCanvas::recordAction(const String& name, Vector<RecordCanvasActionVariant>&& parameters)
 {
     if (!hasRecordingData()) {
         m_initialState = buildInitialState();
@@ -385,23 +385,21 @@
     return initialState;
 }
 
-RefPtr<Inspector::Protocol::Array<Inspector::InspectorValue>> InspectorCanvas::buildAction(const String& name, Vector<CanvasActionParameterVariant>&& parameters)
+RefPtr<Inspector::Protocol::Array<Inspector::InspectorValue>> InspectorCanvas::buildAction(const String& name, Vector<RecordCanvasActionVariant>&& parameters)
 {
     RefPtr<Inspector::Protocol::Array<InspectorValue>> action = ""
-    action->addItem(static_cast<double>(indexForData(name)));
+    action->addItem(indexForData(name));
 
     RefPtr<Inspector::Protocol::Array<InspectorValue>> parametersData = Inspector::Protocol::Array<Inspector::InspectorValue>::create();
-    for (CanvasActionParameterVariant& item : parameters) {
+    for (RecordCanvasActionVariant& item : parameters) {
         WTF::switchOn(item,
-            [&] (const Element*) {
-                // Elements are not serializable, so add a string as a placeholder since the actual
-                // element cannot be reconstructed in the frontend.
-                parametersData->addItem(indexForData(String("element")));
+            [&] (const CanvasRenderingContext2D::WindingRule& value) {
+                String windingRule = CanvasRenderingContext2D::stringForWindingRule(value);
+                parametersData->addItem(indexForData(windingRule));
             },
-            [&] (const HTMLImageElement* value) { parametersData->addItem(indexForData(value)); },
-            [&] (const ImageData* value) {
-                if (value)
-                    parametersData->addItem(indexForData(value));
+            [&] (const CanvasRenderingContext2D::ImageSmoothingQuality& value) {
+                String imageSmoothingQuality = CanvasRenderingContext2D::stringForImageSmoothingQuality(value);
+                parametersData->addItem(indexForData(imageSmoothingQuality));
             },
             [&] (const DOMMatrixInit& value) {
                 RefPtr<Inspector::Protocol::Array<double>> array = Inspector::Protocol::Array<double>::create();
@@ -414,6 +412,23 @@
                 parametersData->addItem(WTFMove(array));
             },
             [&] (const DOMPath* value) { parametersData->addItem(indexForData(buildStringFromPath(value->path()))); },
+            [&] (const Element*) {
+                // Elements are not serializable, so add a string as a placeholder since the actual
+                // element cannot be reconstructed in the frontend.
+                parametersData->addItem(indexForData(String("element")));
+            },
+            [&] (HTMLImageElement* value) { parametersData->addItem(indexForData(value)); },
+            [&] (ImageData* value) {
+                if (value)
+                    parametersData->addItem(indexForData(value));
+            },
+            [&] (const RefPtr<CanvasGradient>& value) { parametersData->addItem(indexForData(value.get())); },
+            [&] (const RefPtr<CanvasPattern>& value) { parametersData->addItem(indexForData(value.get())); },
+            [&] (RefPtr<HTMLCanvasElement>& value) { parametersData->addItem(indexForData(value.get())); },
+            [&] (const RefPtr<HTMLImageElement>& value) { parametersData->addItem(indexForData(value.get())); },
+#if ENABLE(VIDEO)
+            [&] (RefPtr<HTMLVideoElement>& value) { parametersData->addItem(indexForData(value.get())); },
+#endif
             [&] (const Vector<float>& value) { parametersData->addItem(buildArrayForVector(value)); },
             [&] (const String& value) { parametersData->addItem(indexForData(value)); },
             [&] (double value) { parametersData->addItem(value); },
@@ -423,30 +438,6 @@
             [&] (const std::optional<float>& value) {
                 if (value)
                     parametersData->addItem(value.value());
-            },
-            [&] (CanvasImageSource& canvasImageSource) {
-                WTF::switchOn(canvasImageSource,
-                    [&] (const RefPtr<HTMLImageElement>& value) { parametersData->addItem(indexForData(value.get())); },
-#if ENABLE(VIDEO)
-                    [&] (RefPtr<HTMLVideoElement>& value) { parametersData->addItem(indexForData(value.get())); },
-#endif
-                    [&] (RefPtr<HTMLCanvasElement>& value) { parametersData->addItem(indexForData(value.get())); }
-                );
-            },
-            [&] (const CanvasRenderingContext2D::Style& style) {
-                WTF::switchOn(style,
-                    [&] (const String& value) { parametersData->addItem(indexForData(value)); },
-                    [&] (const RefPtr<CanvasGradient>& value) { parametersData->addItem(indexForData(value.get())); },
-                    [&] (const RefPtr<CanvasPattern>& value) { parametersData->addItem(indexForData(value.get())); }
-                );
-            },
-            [&] (CanvasRenderingContext2D::WindingRule value) {
-                String windingRule = CanvasRenderingContext2D::stringForWindingRule(value);
-                parametersData->addItem(indexForData(windingRule));
-            },
-            [&] (CanvasRenderingContext2D::ImageSmoothingQuality value) {
-                String imageSmoothingQuality = CanvasRenderingContext2D::stringForImageSmoothingQuality(value);
-                parametersData->addItem(indexForData(imageSmoothingQuality));
             }
         );
     }

Modified: trunk/Source/WebCore/inspector/InspectorCanvas.h (220007 => 220008)


--- trunk/Source/WebCore/inspector/InspectorCanvas.h	2017-07-28 18:06:59 UTC (rev 220007)
+++ trunk/Source/WebCore/inspector/InspectorCanvas.h	2017-07-28 18:22:17 UTC (rev 220008)
@@ -47,18 +47,6 @@
 
 typedef String ErrorString;
 
-typedef Variant<
-    const HTMLImageElement*,
-#if ENABLE(VIDEO)
-    HTMLVideoElement*,
-#endif
-    HTMLCanvasElement*,
-    const CanvasGradient*,
-    const CanvasPattern*,
-    const ImageData*,
-    String
-> DuplicateDataVariant;
-
 class InspectorCanvas final : public RefCounted<InspectorCanvas> {
 public:
     static Ref<InspectorCanvas> create(HTMLCanvasElement&, const String& cssCanvasName);
@@ -69,7 +57,7 @@
 
     void resetRecordingData();
     bool hasRecordingData() const;
-    void recordAction(const String&, Vector<CanvasActionParameterVariant>&& = { });
+    void recordAction(const String&, Vector<RecordCanvasActionVariant>&& = { });
 
     RefPtr<Inspector::Protocol::Recording::InitialState>&& releaseInitialState() { return WTFMove(m_initialState); }
     RefPtr<Inspector::Protocol::Array<Inspector::Protocol::Recording::Frame>>&& releaseFrames() { return WTFMove(m_frames); }
@@ -91,9 +79,21 @@
 private:
     InspectorCanvas(HTMLCanvasElement&, const String& cssCanvasName);
 
+    typedef Variant<
+        CanvasGradient*,
+        CanvasPattern*,
+        HTMLCanvasElement*,
+        HTMLImageElement*,
+#if ENABLE(VIDEO)
+        HTMLVideoElement*,
+#endif
+        ImageData*,
+        String
+    > DuplicateDataVariant;
+
     int indexForData(DuplicateDataVariant);
     RefPtr<Inspector::Protocol::Recording::InitialState> buildInitialState();
-    RefPtr<Inspector::Protocol::Array<Inspector::InspectorValue>> buildAction(const String&, Vector<CanvasActionParameterVariant>&& = { });
+    RefPtr<Inspector::Protocol::Array<Inspector::InspectorValue>> buildAction(const String&, Vector<RecordCanvasActionVariant>&& = { });
     RefPtr<Inspector::Protocol::Array<Inspector::InspectorValue>> buildArrayForCanvasGradient(const CanvasGradient&);
     RefPtr<Inspector::Protocol::Array<Inspector::InspectorValue>> buildArrayForCanvasPattern(const CanvasPattern&);
     RefPtr<Inspector::Protocol::Array<Inspector::InspectorValue>> buildArrayForImageData(const ImageData&);

Modified: trunk/Source/WebCore/inspector/InspectorCanvasAgent.cpp (220007 => 220008)


--- trunk/Source/WebCore/inspector/InspectorCanvasAgent.cpp	2017-07-28 18:06:59 UTC (rev 220007)
+++ trunk/Source/WebCore/inspector/InspectorCanvasAgent.cpp	2017-07-28 18:22:17 UTC (rev 220008)
@@ -26,19 +26,11 @@
 #include "config.h"
 #include "InspectorCanvasAgent.h"
 
-#include "CanvasGradient.h"
-#include "CanvasPattern.h"
 #include "CanvasRenderingContext.h"
 #include "CanvasRenderingContext2D.h"
-#include "DOMMatrixInit.h"
-#include "DOMPath.h"
 #include "Document.h"
 #include "Element.h"
 #include "Frame.h"
-#include "HTMLCanvasElement.h"
-#include "HTMLImageElement.h"
-#include "HTMLVideoElement.h"
-#include "ImageData.h"
 #include "InspectorDOMAgent.h"
 #include "InstrumentingAgents.h"
 #include "JSCanvasRenderingContext2D.h"
@@ -337,7 +329,7 @@
     m_frontendDispatcher->canvasMemoryChanged(inspectorCanvas->identifier(), canvasElement.memoryCost());
 }
 
-void InspectorCanvasAgent::recordCanvasAction(CanvasRenderingContext& canvasRenderingContext, const String& name, Vector<CanvasActionParameterVariant>&& parameters)
+void InspectorCanvasAgent::recordCanvasAction(CanvasRenderingContext& canvasRenderingContext, const String& name, Vector<RecordCanvasActionVariant>&& parameters)
 {
     HTMLCanvasElement& canvasElement = canvasRenderingContext.canvas();
 

Modified: trunk/Source/WebCore/inspector/InspectorCanvasAgent.h (220007 => 220008)


--- trunk/Source/WebCore/inspector/InspectorCanvasAgent.h	2017-07-28 18:06:59 UTC (rev 220007)
+++ trunk/Source/WebCore/inspector/InspectorCanvasAgent.h	2017-07-28 18:22:17 UTC (rev 220008)
@@ -75,7 +75,7 @@
     void didChangeCSSCanvasClientNodes(HTMLCanvasElement&);
     void didCreateCanvasRenderingContext(HTMLCanvasElement&);
     void didChangeCanvasMemory(HTMLCanvasElement&);
-    void recordCanvasAction(CanvasRenderingContext&, const String&, Vector<CanvasActionParameterVariant>&& = { });
+    void recordCanvasAction(CanvasRenderingContext&, const String&, Vector<RecordCanvasActionVariant>&& = { });
     void didFinishRecordingCanvasFrame(HTMLCanvasElement&, bool forceDispatch = false);
 
     // CanvasObserver

Modified: trunk/Source/WebCore/inspector/InspectorInstrumentation.cpp (220007 => 220008)


--- trunk/Source/WebCore/inspector/InspectorInstrumentation.cpp	2017-07-28 18:06:59 UTC (rev 220007)
+++ trunk/Source/WebCore/inspector/InspectorInstrumentation.cpp	2017-07-28 18:22:17 UTC (rev 220008)
@@ -980,7 +980,7 @@
         canvasAgent->didChangeCanvasMemory(canvasElement);
 }
 
-void InspectorInstrumentation::recordCanvasActionImpl(InstrumentingAgents* instrumentingAgents, CanvasRenderingContext& canvasRenderingContext, const String& name, Vector<CanvasActionParameterVariant>&& parameters)
+void InspectorInstrumentation::recordCanvasActionImpl(InstrumentingAgents* instrumentingAgents, CanvasRenderingContext& canvasRenderingContext, const String& name, Vector<RecordCanvasActionVariant>&& parameters)
 {
     if (InspectorCanvasAgent* canvasAgent = instrumentingAgents->inspectorCanvasAgent())
         canvasAgent->recordCanvasAction(canvasRenderingContext, name, WTFMove(parameters));

Modified: trunk/Source/WebCore/inspector/InspectorInstrumentation.h (220007 => 220008)


--- trunk/Source/WebCore/inspector/InspectorInstrumentation.h	2017-07-28 18:06:59 UTC (rev 220007)
+++ trunk/Source/WebCore/inspector/InspectorInstrumentation.h	2017-07-28 18:22:17 UTC (rev 220008)
@@ -33,19 +33,13 @@
 
 #include "CSSSelector.h"
 #include "CallTracerTypes.h"
-#include "CanvasGradient.h"
-#include "CanvasPattern.h"
 #include "CanvasRenderingContext.h"
-#include "DOMPath.h"
 #include "DocumentThreadableLoader.h"
 #include "Element.h"
 #include "FormData.h"
 #include "Frame.h"
 #include "HTMLCanvasElement.h"
-#include "HTMLImageElement.h"
-#include "HTMLVideoElement.h"
 #include "HitTestResult.h"
-#include "ImageData.h"
 #include "InspectorController.h"
 #include "InspectorInstrumentationCookie.h"
 #include "Page.h"
@@ -232,7 +226,7 @@
     static void didChangeCSSCanvasClientNodes(HTMLCanvasElement&);
     static void didCreateCanvasRenderingContext(HTMLCanvasElement&);
     static void didChangeCanvasMemory(HTMLCanvasElement&);
-    static void recordCanvasAction(CanvasRenderingContext&, const String&, Vector<CanvasActionParameterVariant>&& = { });
+    static void recordCanvasAction(CanvasRenderingContext&, const String&, Vector<RecordCanvasActionVariant>&& = { });
     static void didFinishRecordingCanvasFrame(HTMLCanvasElement&, bool forceDispatch = false);
 
     static void networkStateChanged(Page&);
@@ -391,7 +385,7 @@
     static void didChangeCSSCanvasClientNodesImpl(InstrumentingAgents*, HTMLCanvasElement&);
     static void didCreateCanvasRenderingContextImpl(InstrumentingAgents*, HTMLCanvasElement&);
     static void didChangeCanvasMemoryImpl(InstrumentingAgents*, HTMLCanvasElement&);
-    static void recordCanvasActionImpl(InstrumentingAgents*, CanvasRenderingContext&, const String&, Vector<CanvasActionParameterVariant>&& = { });
+    static void recordCanvasActionImpl(InstrumentingAgents*, CanvasRenderingContext&, const String&, Vector<RecordCanvasActionVariant>&& = { });
     static void didFinishRecordingCanvasFrameImpl(InstrumentingAgents*, HTMLCanvasElement&, bool forceDispatch = false);
 
     static void layerTreeDidChangeImpl(InstrumentingAgents&);
@@ -1098,7 +1092,7 @@
         didChangeCanvasMemoryImpl(instrumentingAgents, canvasElement);
 }
 
-inline void InspectorInstrumentation::recordCanvasAction(CanvasRenderingContext& canvasRenderingContext, const String& name, Vector<CanvasActionParameterVariant>&& parameters)
+inline void InspectorInstrumentation::recordCanvasAction(CanvasRenderingContext& canvasRenderingContext, const String& name, Vector<RecordCanvasActionVariant>&& parameters)
 {
     FAST_RETURN_IF_NO_FRONTENDS(void());
     if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(&canvasRenderingContext.canvas().document()))
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to