Source/JavaScriptCore/inspector/JSGlobalObjectConsoleClient.cpp

@@void JSGlobalObjectConsoleClient::warnUnimplemented(const String& method)
171171 m_consoleAgent->addMessageToConsole(std::make_unique<ConsoleMessage>(MessageSource::ConsoleAPI, MessageType::Log, MessageLevel::Warning, message));
172172}
173173
 174void JSGlobalObjectConsoleClient::record(ExecState*, Ref<ScriptArguments>&&) { }
 175void JSGlobalObjectConsoleClient::recordEnd(ExecState*, Ref<ScriptArguments>&&) { }
 176
174177} // namespace Inspector

Source/JavaScriptCore/inspector/JSGlobalObjectConsoleClient.h

@@protected:
5353 void time(JSC::ExecState*, const String& title) override;
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:
5860 void warnUnimplemented(const String& method);

Source/JavaScriptCore/inspector/protocol/Canvas.json

4141 { "name": "contextAttributes", "$ref": "ContextAttributes", "optional": true, "description": "Context attributes for WebGL rendering contexts." },
4242 { "name": "memoryCost", "type": "number", "optional": true, "description": "Memory usage of the canvas." }
4343 ]
 44 },
 45 {
 46 "id": "InitialState",
 47 "type": "object",
 48 "description": "Information about the initial state of the recorded canvas.",
 49 "properties": [
 50 { "name": "attributes", "type": "object", "optional": true, "description": "Key-value map for each attribute." },
 51 { "name": "functions", "type": "object", "optional": true, "description": "Key-value map for each state that is only accessible via a function call. Values must be arrays." },
 52 { "name": "content", "type": "string", "optional": true, "description": "Current content at the start of the recording." }
 53 ]
 54 },
 55 {
 56 "id": "RecordingAction",
 57 "type": "object",
 58 "description": "Information about an action made to the recorded canvas.",
 59 "properties": [
 60 { "name": "name", "type": "string", "description": "Name of the function/attribute that was called/changed." },
 61 { "name": "parameters", "type": "array", "items": { "type": "any" }, "optional": true, "description": "Array of parameter values." }
 62 ]
4463 }
4564 ],
4665 "commands": [

89108 "returns": [
90109 { "name": "object", "$ref": "Runtime.RemoteObject", "description": "JavaScript object wrapper for given canvas context." }
91110 ]
 111 },
 112 {
 113 "name": "toggleRecording",
 114 "description": "Sets whether the next draw frame should be recorded for the given canvas.",
 115 "parameters": [
 116 { "name": "canvasId", "$ref": "CanvasId", "description": "Canvas identifier." },
 117 { "name": "flag", "type": "boolean", "description": "Flag of whether to request a recording or cancel an existing request." }
 118 ]
92119 }
93120 ],
94121 "events": [

110137 { "name": "canvasId", "$ref": "CanvasId", "description": "Identifier of canvas who's memory cost changed." },
111138 { "name": "memoryCost", "type": "number", "description": "New memory cost value for the canvas." }
112139 ]
 140 },
 141 {
 142 "name": "recordingFinished",
 143 "parameters": [
 144 { "name": "canvasId", "$ref": "CanvasId", "description": "Identifier of canvas who's memory cost changed." },
 145 { "name": "initialState", "$ref": "InitialState", "description": "JSON data of inital state of canvas before recording." },
 146 { "name": "actions", "type": "array", "items": { "$ref": "RecordingAction" }, "description": "JSON data of all canvas API calls." }
 147 ]
113148 }
114149 ]
115150}

Source/JavaScriptCore/runtime/ConsoleClient.h

@@public:
6262 virtual void time(ExecState*, const String& title) = 0;
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:
6769 enum ArgumentRequirement { ArgumentRequired, ArgumentNotRequired };

Source/JavaScriptCore/runtime/ConsoleObject.cpp

@@static EncodedJSValue JSC_HOST_CALL consoleProtoFuncTimeStamp(ExecState*);
5757static EncodedJSValue JSC_HOST_CALL consoleProtoFuncGroup(ExecState*);
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) };
6264

@@void ConsoleObject::finishCreation(VM& vm, JSGlobalObject* globalObject)
9597 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("group", consoleProtoFuncGroup, None, 0);
9698 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("groupCollapsed", consoleProtoFuncGroupCollapsed, None, 0);
9799 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("groupEnd", consoleProtoFuncGroupEnd, None, 0);
 100 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("record", consoleProtoFuncRecord, None, 0);
 101 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("recordEnd", consoleProtoFuncRecordEnd, None, 0);
98102}
99103
100104static String valueToStringWithUndefinedOrNullCheck(ExecState* exec, JSValue value)

@@static EncodedJSValue JSC_HOST_CALL consoleProtoFuncGroupEnd(ExecState* exec)
367371 return JSValue::encode(jsUndefined());
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

Source/WebCore/WebCore.xcodeproj/project.pbxproj

39693969 94E839521DFB2A12007BC6A7 /* CSSNamespaceRule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94E8394E1DFB2700007BC6A7 /* CSSNamespaceRule.cpp */; };
39703970 94E839551DFB2BC4007BC6A7 /* JSCSSNamespaceRule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94E839531DFB2BA6007BC6A7 /* JSCSSNamespaceRule.cpp */; };
39713971 94E839561DFB2BC4007BC6A7 /* JSCSSNamespaceRule.h in Headers */ = {isa = PBXBuildFile; fileRef = 94E839541DFB2BA6007BC6A7 /* JSCSSNamespaceRule.h */; };
 3972 9540D31F1EFCA78D00DA2EBB /* InspectorCanvasActionTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 9540D31E1EFCA76E00DA2EBB /* InspectorCanvasActionTypes.h */; };
39723973 96ABA42314BCB80E00D56204 /* GraphicsContext3DOpenGLCommon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 96ABA42214BCB80E00D56204 /* GraphicsContext3DOpenGLCommon.cpp */; };
39733974 9703E1BF15DC4E37001F24C8 /* JSVoidCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 97E9EC8B15DC492F004F2E71 /* JSVoidCallback.cpp */; };
39743975 97059977107D975200A50A7C /* PolicyCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 97059973107D975200A50A7C /* PolicyCallback.cpp */; };

1216912170 94E839531DFB2BA6007BC6A7 /* JSCSSNamespaceRule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCSSNamespaceRule.cpp; sourceTree = "<group>"; };
1217012171 94E839541DFB2BA6007BC6A7 /* JSCSSNamespaceRule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCSSNamespaceRule.h; sourceTree = "<group>"; };
1217112172 950C4C02BED8936F818E2F99 /* JSSVGGraphicsElement.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = JSSVGGraphicsElement.h; sourceTree = "<group>"; };
 12173 9540D31E1EFCA76E00DA2EBB /* InspectorCanvasActionTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InspectorCanvasActionTypes.h; sourceTree = "<group>"; };
1217212174 96ABA42214BCB80E00D56204 /* GraphicsContext3DOpenGLCommon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GraphicsContext3DOpenGLCommon.cpp; sourceTree = "<group>"; };
1217312175 97059973107D975200A50A7C /* PolicyCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PolicyCallback.cpp; sourceTree = "<group>"; };
1217412176 97059974107D975200A50A7C /* PolicyCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolicyCallback.h; sourceTree = "<group>"; };

1724917251 7A54881514E432A1006AE05A /* DOMPatchSupport.h */,
1725017252 B885E8D211E06DD2009FFBF4 /* InspectorApplicationCacheAgent.cpp */,
1725117253 B885E8D311E06DD2009FFBF4 /* InspectorApplicationCacheAgent.h */,
 17254 9540D31E1EFCA76E00DA2EBB /* InspectorCanvasActionTypes.h */,
1725217255 6A4B6D6619D225D8006F11D3 /* InspectorCanvasAgent.cpp */,
1725317256 6A4B6D6419D22519006F11D3 /* InspectorCanvasAgent.h */,
1725417257 7A1F2B51126C61B20006A7E6 /* InspectorClient.cpp */,

2726327266 FD1762E4176686EA00D836A8 /* DownSampler.h in Headers */,
2726427267 A718760E0B2A120100A16ECE /* DragActions.h in Headers */,
2726527268 A7CA59630B27C1F200FA021D /* DragClient.h in Headers */,
 27269 9540D31F1EFCA78D00DA2EBB /* InspectorCanvasActionTypes.h in Headers */,
2726627270 A7CA595D0B27BD9E00FA021D /* DragController.h in Headers */,
2726727271 A7B6E69F0B291A9600D0529F /* DragData.h in Headers */,
2726827272 A7CFB3D20B7ED10A0070C32D /* DragImage.h in Headers */,

Source/WebCore/html/HTMLCanvasElement.cpp

@@void HTMLCanvasElement::removeObserver(CanvasObserver& observer)
179179
180180void HTMLCanvasElement::setHeight(unsigned value)
181181{
 182 if (UNLIKELY(m_recordingState != RecordingState::Inactive))
 183 InspectorInstrumentation::recordCanvasAction(*this, ASCIILiteral("width"), { value });
 184
182185 setAttributeWithoutSynchronization(heightAttr, AtomicString::number(limitToOnlyHTMLNonNegative(value, defaultHeight)));
183186}
184187
185188void HTMLCanvasElement::setWidth(unsigned value)
186189{
 190 if (UNLIKELY(m_recordingState != RecordingState::Inactive))
 191 InspectorInstrumentation::recordCanvasAction(*this, ASCIILiteral("height"), { value });
 192
187193 setAttributeWithoutSynchronization(widthAttr, AtomicString::number(limitToOnlyHTMLNonNegative(value, defaultWidth)));
188194}
189195

@@bool HTMLCanvasElement::paintsIntoCanvasBuffer() const
445451
446452void HTMLCanvasElement::paint(GraphicsContext& context, const LayoutRect& r)
447453{
 454 if (UNLIKELY(m_recordingState != RecordingState::Inactive))
 455 InspectorInstrumentation::didFinishRecordingCanvas(*this);
 456
448457 // Clear the dirty rect
449458 m_dirtyRect = FloatRect();
450459

Source/WebCore/html/HTMLCanvasElement.h

@@public:
154154 size_t memoryCost() const;
155155 size_t externalMemoryCost() const;
156156
 157 enum RecordingState { Inactive, Requested, Active };
 158 RecordingState recordingState() const { return m_recordingState; }
 159 void setRecordingState(RecordingState state) { m_recordingState = state; }
 160
157161private:
158162 HTMLCanvasElement(const QualifiedName&, Document&);
159163

@@private:
188192 bool m_usesDisplayListDrawing { false };
189193 bool m_tracksDisplayListReplay { false };
190194
 195 RecordingState m_recordingState { Inactive };
 196
191197 // m_createdImageBuffer means we tried to malloc the buffer. We didn't necessarily get it.
192198 mutable bool m_hasCreatedImageBuffer { false };
193199 mutable bool m_didClearImageBuffer { false };

Source/WebCore/html/canvas/CanvasPath.cpp

3636#include "CanvasPath.h"
3737
3838#include "AffineTransform.h"
 39#include "CanvasRenderingContext2D.h"
3940#include "ExceptionCode.h"
4041#include "FloatRect.h"
 42#include "HTMLCanvasElement.h"
 43#include "InspectorInstrumentation.h"
4144#include <wtf/MathExtras.h>
4245
4346namespace WebCore {
4447
4548void CanvasPath::closePath()
4649{
 50 if (HTMLCanvasElement* canvas = recordingCanvas())
 51 InspectorInstrumentation::recordCanvasAction(*canvas, ASCIILiteral("closePath"));
 52
4753 if (m_path.isEmpty())
4854 return;
4955

@@void CanvasPath::closePath()
5460
5561void CanvasPath::moveTo(float x, float y)
5662{
 63 if (HTMLCanvasElement* canvas = recordingCanvas())
 64 InspectorInstrumentation::recordCanvasAction(*canvas, ASCIILiteral("moveTo"), { x, y });
 65
5766 if (!std::isfinite(x) || !std::isfinite(y))
5867 return;
5968 if (!hasInvertibleTransform())

@@void CanvasPath::lineTo(FloatPoint point)
6877
6978void CanvasPath::lineTo(float x, float y)
7079{
 80 if (HTMLCanvasElement* canvas = recordingCanvas())
 81 InspectorInstrumentation::recordCanvasAction(*canvas, ASCIILiteral("lineTo"), { x, y });
 82
7183 if (!std::isfinite(x) || !std::isfinite(y))
7284 return;
7385 if (!hasInvertibleTransform())

@@void CanvasPath::lineTo(float x, float y)
8294
8395void CanvasPath::quadraticCurveTo(float cpx, float cpy, float x, float y)
8496{
 97 if (HTMLCanvasElement* canvas = recordingCanvas())
 98 InspectorInstrumentation::recordCanvasAction(*canvas, ASCIILiteral("quadraticCurveTo"), { cpx, cpy, x, y });
 99
85100 if (!std::isfinite(cpx) || !std::isfinite(cpy) || !std::isfinite(x) || !std::isfinite(y))
86101 return;
87102 if (!hasInvertibleTransform())

@@void CanvasPath::quadraticCurveTo(float cpx, float cpy, float x, float y)
97112
98113void CanvasPath::bezierCurveTo(float cp1x, float cp1y, float cp2x, float cp2y, float x, float y)
99114{
 115 if (HTMLCanvasElement* canvas = recordingCanvas())
 116 InspectorInstrumentation::recordCanvasAction(*canvas, ASCIILiteral("bezierCurveTo"), { cp1x, cp1y, cp2x, cp2y, x, y });
 117
100118 if (!std::isfinite(cp1x) || !std::isfinite(cp1y) || !std::isfinite(cp2x) || !std::isfinite(cp2y) || !std::isfinite(x) || !std::isfinite(y))
101119 return;
102120 if (!hasInvertibleTransform())

@@void CanvasPath::bezierCurveTo(float cp1x, float cp1y, float cp2x, float cp2y, f
113131
114132ExceptionOr<void> CanvasPath::arcTo(float x1, float y1, float x2, float y2, float r)
115133{
 134 if (HTMLCanvasElement* canvas = recordingCanvas())
 135 InspectorInstrumentation::recordCanvasAction(*canvas, ASCIILiteral("arcTo"), { x1, y1, x2, y2, r });
 136
116137 if (!std::isfinite(x1) || !std::isfinite(y1) || !std::isfinite(x2) || !std::isfinite(y2) || !std::isfinite(r))
117138 return { };
118139

@@static void normalizeAngles(float& startAngle, float& endAngle, bool anticlockwi
156177
157178ExceptionOr<void> CanvasPath::arc(float x, float y, float radius, float startAngle, float endAngle, bool anticlockwise)
158179{
 180 if (HTMLCanvasElement* canvas = recordingCanvas())
 181 InspectorInstrumentation::recordCanvasAction(*canvas, ASCIILiteral("arc"), { x, y, radius, startAngle, endAngle, anticlockwise });
 182
159183 if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(radius) || !std::isfinite(startAngle) || !std::isfinite(endAngle))
160184 return { };
161185

@@ExceptionOr<void> CanvasPath::arc(float x, float y, float radius, float startAng
179203
180204ExceptionOr<void> CanvasPath::ellipse(float x, float y, float radiusX, float radiusY, float rotation, float startAngle, float endAngle, bool anticlockwise)
181205{
 206 if (HTMLCanvasElement* canvas = recordingCanvas())
 207 InspectorInstrumentation::recordCanvasAction(*canvas, ASCIILiteral("ellipse"), { x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise });
 208
182209 if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(radiusX) || !std::isfinite(radiusY) || !std::isfinite(rotation) || !std::isfinite(startAngle) || !std::isfinite(endAngle))
183210 return { };
184211

@@ExceptionOr<void> CanvasPath::ellipse(float x, float y, float radiusX, float rad
222249
223250void CanvasPath::rect(float x, float y, float width, float height)
224251{
 252 if (HTMLCanvasElement* canvas = recordingCanvas())
 253 InspectorInstrumentation::recordCanvasAction(*canvas, ASCIILiteral("rect"), { x, y, width, height });
 254
225255 if (!hasInvertibleTransform())
226256 return;
227257

@@void CanvasPath::rect(float x, float y, float width, float height)
235265
236266 m_path.addRect(FloatRect(x, y, width, height));
237267}
 268
 269HTMLCanvasElement* CanvasPath::recordingCanvas() const
 270{
 271 if (!is<CanvasRenderingContext2D>(this))
 272 return nullptr;
 273
 274 HTMLCanvasElement& canvas = downcast<CanvasRenderingContext2D>(this)->canvas();
 275 if (LIKELY(canvas.recordingState() == HTMLCanvasElement::RecordingState::Inactive))
 276 return nullptr;
 277
 278 return &canvas;
238279}
 280
 281} // namespace WebCore

Source/WebCore/html/canvas/CanvasPath.h

2929#pragma once
3030
3131#include "ExceptionOr.h"
 32#include "HTMLCanvasElement.h"
3233#include "Path.h"
 34#include <wtf/text/WTFString.h>
3335
3436namespace WebCore {
3537

@@class CanvasPath {
3739public:
3840 virtual ~CanvasPath() { }
3941
 42 virtual bool isCanvasRenderingContext2D() const { return false; }
 43 virtual bool isDOMPath() const { return false; }
 44
4045 void closePath();
4146 void moveTo(float x, float y);
4247 void lineTo(float x, float y);

@@protected:
5762
5863 void lineTo(FloatPoint);
5964
 65 HTMLCanvasElement* recordingCanvas() const;
 66
6067 Path m_path;
6168};
6269

Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp

4848#include "HTMLVideoElement.h"
4949#include "ImageBuffer.h"
5050#include "ImageData.h"
 51#include "InspectorInstrumentation.h"
 52#include "Pattern.h"
5153#include "RenderElement.h"
5254#include "RenderImage.h"
5355#include "RenderLayer.h"

5961#include "TextMetrics.h"
6062#include "TextRun.h"
6163#include "TextStream.h"
 64#include <runtime/TypedArrayInlines.h>
6265#include <wtf/CheckedArithmetic.h>
6366#include <wtf/MathExtras.h>
6467#include <wtf/NeverDestroyed.h>

@@void CanvasRenderingContext2D::realizeSavesLoop()
371374 } while (--m_unrealizedSaveCount);
372375}
373376
 377void CanvasRenderingContext2D::save()
 378{
 379 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 380 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("save"));
 381
 382 ++m_unrealizedSaveCount;
 383}
 384
374385void CanvasRenderingContext2D::restore()
375386{
 387 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 388 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("restore"));
 389
376390 if (m_unrealizedSaveCount) {
377391 --m_unrealizedSaveCount;
378392 return;

@@float CanvasRenderingContext2D::lineWidth() const
451465
452466void CanvasRenderingContext2D::setLineWidth(float width)
453467{
 468 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 469 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("lineWidth"), { width });
 470
454471 if (!(std::isfinite(width) && width > 0))
455472 return;
456473 if (state().lineWidth == width)

@@String CanvasRenderingContext2D::lineCap() const
470487
471488void CanvasRenderingContext2D::setLineCap(const String& s)
472489{
 490 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 491 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("lineCap"), { s });
 492
473493 LineCap cap;
474494 if (!parseLineCap(s, cap))
475495 return;

@@String CanvasRenderingContext2D::lineJoin() const
490510
491511void CanvasRenderingContext2D::setLineJoin(const String& s)
492512{
 513 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 514 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("lineJoin"), { s });
 515
493516 LineJoin join;
494517 if (!parseLineJoin(s, join))
495518 return;

@@float CanvasRenderingContext2D::miterLimit() const
510533
511534void CanvasRenderingContext2D::setMiterLimit(float limit)
512535{
 536 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 537 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("miterLimit"), { limit });
 538
513539 if (!(std::isfinite(limit) && limit > 0))
514540 return;
515541 if (state().miterLimit == limit)

@@float CanvasRenderingContext2D::shadowOffsetX() const
529555
530556void CanvasRenderingContext2D::setShadowOffsetX(float x)
531557{
 558 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 559 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("shadowOffsetX"), { x });
 560
532561 if (!std::isfinite(x))
533562 return;
534563 if (state().shadowOffset.width() == x)

@@float CanvasRenderingContext2D::shadowOffsetY() const
545574
546575void CanvasRenderingContext2D::setShadowOffsetY(float y)
547576{
 577 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 578 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("shadowOffsetY"), { y });
 579
548580 if (!std::isfinite(y))
549581 return;
550582 if (state().shadowOffset.height() == y)

@@float CanvasRenderingContext2D::shadowBlur() const
561593
562594void CanvasRenderingContext2D::setShadowBlur(float blur)
563595{
 596 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 597 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("shadowBlur"), { blur });
 598
564599 if (!(std::isfinite(blur) && blur >= 0))
565600 return;
566601 if (state().shadowBlur == blur)

@@String CanvasRenderingContext2D::shadowColor() const
577612
578613void CanvasRenderingContext2D::setShadowColor(const String& colorString)
579614{
 615 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 616 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("shadowColor"), { colorString });
 617
580618 Color color = parseColorOrCurrentColor(colorString, &canvas());
581619 if (!color.isValid())
582620 return;

@@static bool lineDashSequenceIsValid(const Vector<float>& dash)
603641
604642void CanvasRenderingContext2D::setLineDash(const Vector<float>& dash)
605643{
 644 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 645 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("setLineDash"), { dash });
 646
606647 if (!lineDashSequenceIsValid(dash))
607648 return;
608649

@@void CanvasRenderingContext2D::setLineDash(const Vector<float>& dash)
618659
619660void CanvasRenderingContext2D::setWebkitLineDash(const Vector<float>& dash)
620661{
 662 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 663 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("webkitLineDash"), { dash });
 664
621665 if (!lineDashSequenceIsValid(dash))
622666 return;
623667

@@float CanvasRenderingContext2D::lineDashOffset() const
634678
635679void CanvasRenderingContext2D::setLineDashOffset(float offset)
636680{
 681 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 682 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("lineDashOffset"), { offset });
 683
637684 if (!std::isfinite(offset) || state().lineDashOffset == offset)
638685 return;
639686

@@float CanvasRenderingContext2D::globalAlpha() const
660707
661708void CanvasRenderingContext2D::setGlobalAlpha(float alpha)
662709{
 710 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 711 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("globalAlpha"), { alpha });
 712
663713 if (!(alpha >= 0 && alpha <= 1))
664714 return;
665715 if (state().globalAlpha == alpha)

@@String CanvasRenderingContext2D::globalCompositeOperation() const
679729
680730void CanvasRenderingContext2D::setGlobalCompositeOperation(const String& operation)
681731{
 732 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 733 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("globalCompositeOperation"), { operation });
 734
682735 CompositeOperator op = CompositeSourceOver;
683736 BlendMode blendMode = BlendModeNormal;
684737 if (!parseCompositeAndBlendOperator(operation, op, blendMode))

@@void CanvasRenderingContext2D::setGlobalCompositeOperation(const String& operati
696749
697750void CanvasRenderingContext2D::scale(float sx, float sy)
698751{
 752 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 753 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("scale"), { sx, sy });
 754
699755 GraphicsContext* c = drawingContext();
700756 if (!c)
701757 return;

@@void CanvasRenderingContext2D::scale(float sx, float sy)
724780
725781void CanvasRenderingContext2D::rotate(float angleInRadians)
726782{
 783 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 784 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("rotate"), { angleInRadians });
 785
727786 GraphicsContext* c = drawingContext();
728787 if (!c)
729788 return;

@@void CanvasRenderingContext2D::rotate(float angleInRadians)
747806
748807void CanvasRenderingContext2D::translate(float tx, float ty)
749808{
 809 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 810 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("translate"), { tx, ty });
 811
750812 GraphicsContext* c = drawingContext();
751813 if (!c)
752814 return;

@@void CanvasRenderingContext2D::translate(float tx, float ty)
770832
771833void CanvasRenderingContext2D::transform(float m11, float m12, float m21, float m22, float dx, float dy)
772834{
 835 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 836 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("transform"), { m11, m12, m21, m22, dx, dy });
 837
773838 GraphicsContext* c = drawingContext();
774839 if (!c)
775840 return;

@@void CanvasRenderingContext2D::transform(float m11, float m12, float m21, float
797862
798863void CanvasRenderingContext2D::setTransform(float m11, float m12, float m21, float m22, float dx, float dy)
799864{
 865 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 866 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("setTransform"), { m11, m12, m21, m22, dx, dy });
 867
800868 GraphicsContext* c = drawingContext();
801869 if (!c)
802870 return;

@@void CanvasRenderingContext2D::setTransform(float m11, float m12, float m21, flo
810878
811879void CanvasRenderingContext2D::resetTransform()
812880{
 881 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 882 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("resetTransform"));
 883
813884 GraphicsContext* c = drawingContext();
814885 if (!c)
815886 return;

@@void CanvasRenderingContext2D::resetTransform()
830901
831902void CanvasRenderingContext2D::setStrokeColor(const String& color, std::optional<float> alpha)
832903{
 904 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive)) {
 905 Vector<Canvas2DParameterVariant> parameters { color };
 906 if (alpha)
 907 parameters.append(alpha.value());
 908
 909 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("setStrokeColor"), WTFMove(parameters));
 910 }
 911
833912 if (alpha) {
834913 setStrokeStyle(CanvasStyle::createFromStringWithOverrideAlpha(color, alpha.value()));
835914 return;

@@void CanvasRenderingContext2D::setStrokeColor(const String& color, std::optional
845924
846925void CanvasRenderingContext2D::setStrokeColor(float grayLevel, float alpha)
847926{
 927 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 928 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("setStrokeColor"), { grayLevel, alpha });
 929
848930 if (state().strokeStyle.isValid() && state().strokeStyle.isEquivalentRGBA(grayLevel, grayLevel, grayLevel, alpha))
849931 return;
850932 setStrokeStyle(CanvasStyle(grayLevel, alpha));

@@void CanvasRenderingContext2D::setStrokeColor(float grayLevel, float alpha)
852934
853935void CanvasRenderingContext2D::setStrokeColor(float r, float g, float b, float a)
854936{
 937 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 938 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("setStrokeColor"), { r, g, b, a });
 939
855940 if (state().strokeStyle.isValid() && state().strokeStyle.isEquivalentRGBA(r, g, b, a))
856941 return;
857942 setStrokeStyle(CanvasStyle(r, g, b, a));

@@void CanvasRenderingContext2D::setStrokeColor(float r, float g, float b, float a
859944
860945void CanvasRenderingContext2D::setStrokeColor(float c, float m, float y, float k, float a)
861946{
 947 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 948 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("setStrokeColor"), { c, m, y, k, a });
 949
862950 if (state().strokeStyle.isValid() && state().strokeStyle.isEquivalentCMYKA(c, m, y, k, a))
863951 return;
864952 setStrokeStyle(CanvasStyle(c, m, y, k, a));

@@void CanvasRenderingContext2D::setStrokeColor(float c, float m, float y, float k
866954
867955void CanvasRenderingContext2D::setFillColor(const String& color, std::optional<float> alpha)
868956{
 957 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive)) {
 958 Vector<Canvas2DParameterVariant> parameters { color };
 959 if (alpha)
 960 parameters.append(alpha.value());
 961
 962 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("setFillColor"), WTFMove(parameters));
 963 }
 964
869965 if (alpha) {
870966 setFillStyle(CanvasStyle::createFromStringWithOverrideAlpha(color, alpha.value()));
871967 return;

@@void CanvasRenderingContext2D::setFillColor(const String& color, std::optional<f
881977
882978void CanvasRenderingContext2D::setFillColor(float grayLevel, float alpha)
883979{
 980 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 981 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("setFillColor"), { grayLevel, alpha });
 982
884983 if (state().fillStyle.isValid() && state().fillStyle.isEquivalentRGBA(grayLevel, grayLevel, grayLevel, alpha))
885984 return;
886985 setFillStyle(CanvasStyle(grayLevel, alpha));

@@void CanvasRenderingContext2D::setFillColor(float grayLevel, float alpha)
888987
889988void CanvasRenderingContext2D::setFillColor(float r, float g, float b, float a)
890989{
 990 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 991 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("setFillColor"), { r, g, b, a });
 992
891993 if (state().fillStyle.isValid() && state().fillStyle.isEquivalentRGBA(r, g, b, a))
892994 return;
893995 setFillStyle(CanvasStyle(r, g, b, a));

@@void CanvasRenderingContext2D::setFillColor(float r, float g, float b, float a)
895997
896998void CanvasRenderingContext2D::setFillColor(float c, float m, float y, float k, float a)
897999{
 1000 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 1001 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("setFillColor"), { c, m, y, k, a });
 1002
8981003 if (state().fillStyle.isValid() && state().fillStyle.isEquivalentCMYKA(c, m, y, k, a))
8991004 return;
9001005 setFillStyle(CanvasStyle(c, m, y, k, a));

@@void CanvasRenderingContext2D::setFillColor(float c, float m, float y, float k,
9021007
9031008void CanvasRenderingContext2D::beginPath()
9041009{
 1010 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 1011 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("beginPath"));
 1012
9051013 m_path.clear();
9061014}
9071015

@@static WindRule toWindRule(CanvasRenderingContext2D::WindingRule rule)
9471055 return rule == CanvasRenderingContext2D::WindingRule::Nonzero ? RULE_NONZERO : RULE_EVENODD;
9481056}
9491057
 1058static inline String stringForWindingRule(CanvasRenderingContext2D::WindingRule windingRule)
 1059{
 1060 switch (windingRule) {
 1061 case CanvasRenderingContext2D::WindingRule::Nonzero:
 1062 return ASCIILiteral("nonzero");
 1063 case CanvasRenderingContext2D::WindingRule::Evenodd:
 1064 return ASCIILiteral("evenodd");
 1065 }
 1066
 1067 ASSERT_NOT_REACHED();
 1068 return "";
 1069}
 1070
9501071void CanvasRenderingContext2D::fill(WindingRule windingRule)
9511072{
 1073 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 1074 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("fill"), { stringForWindingRule(windingRule) });
 1075
9521076 fillInternal(m_path, windingRule);
9531077 clearPathForDashboardBackwardCompatibilityMode();
9541078}
9551079
9561080void CanvasRenderingContext2D::stroke()
9571081{
 1082 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 1083 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("stroke"));
 1084
9581085 strokeInternal(m_path);
9591086 clearPathForDashboardBackwardCompatibilityMode();
9601087}
9611088
9621089void CanvasRenderingContext2D::clip(WindingRule windingRule)
9631090{
 1091 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 1092 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("clip"), { stringForWindingRule(windingRule) });
 1093
9641094 clipInternal(m_path, windingRule);
9651095 clearPathForDashboardBackwardCompatibilityMode();
9661096}
9671097
9681098void CanvasRenderingContext2D::fill(DOMPath& path, WindingRule windingRule)
9691099{
 1100 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 1101 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("fill"), { path.toString(), stringForWindingRule(windingRule) });
 1102
9701103 fillInternal(path.path(), windingRule);
9711104}
9721105
9731106void CanvasRenderingContext2D::stroke(DOMPath& path)
9741107{
 1108 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 1109 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("stroke"), { path.toString() });
 1110
9751111 strokeInternal(path.path());
9761112}
9771113
9781114void CanvasRenderingContext2D::clip(DOMPath& path, WindingRule windingRule)
9791115{
 1116 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 1117 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("clip"), { path.toString(), stringForWindingRule(windingRule) });
 1118
9801119 clipInternal(path.path(), windingRule);
9811120}
9821121

@@inline void CanvasRenderingContext2D::endCompositeLayer()
10751214
10761215bool CanvasRenderingContext2D::isPointInPath(float x, float y, WindingRule windingRule)
10771216{
 1217 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 1218 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("isPointInPath"), { x, y, stringForWindingRule(windingRule) });
 1219
10781220 return isPointInPathInternal(m_path, x, y, windingRule);
10791221}
10801222
10811223bool CanvasRenderingContext2D::isPointInStroke(float x, float y)
10821224{
 1225 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 1226 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("isPointInStroke"), { x, y });
 1227
10831228 return isPointInStrokeInternal(m_path, x, y);
10841229}
10851230
10861231bool CanvasRenderingContext2D::isPointInPath(DOMPath& path, float x, float y, WindingRule windingRule)
10871232{
 1233 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 1234 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("isPointInPath"), { path.toString(), x, y, stringForWindingRule(windingRule) });
 1235
10881236 return isPointInPathInternal(path.path(), x, y, windingRule);
10891237}
10901238
10911239bool CanvasRenderingContext2D::isPointInStroke(DOMPath& path, float x, float y)
10921240{
 1241 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 1242 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("isPointInStroke"), { path.toString(), x, y });
 1243
10931244 return isPointInStrokeInternal(path.path(), x, y);
10941245}
10951246

@@bool CanvasRenderingContext2D::isPointInStrokeInternal(const Path& path, float x
11271278
11281279void CanvasRenderingContext2D::clearRect(float x, float y, float width, float height)
11291280{
 1281 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 1282 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("clearRect"), { x, y, width, height });
 1283
11301284 if (!validateRectForCanvas(x, y, width, height))
11311285 return;
11321286 auto* context = drawingContext();

@@void CanvasRenderingContext2D::clearRect(float x, float y, float width, float he
11641318
11651319void CanvasRenderingContext2D::fillRect(float x, float y, float width, float height)
11661320{
 1321 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 1322 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("fillRect"), { x, y, width, height });
 1323
11671324 if (!validateRectForCanvas(x, y, width, height))
11681325 return;
11691326

@@void CanvasRenderingContext2D::fillRect(float x, float y, float width, float hei
12021359
12031360void CanvasRenderingContext2D::strokeRect(float x, float y, float width, float height)
12041361{
 1362 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 1363 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("strokeRect"), { x, y, width, height });
 1364
12051365 if (!validateRectForCanvas(x, y, width, height))
12061366 return;
12071367

@@void CanvasRenderingContext2D::strokeRect(float x, float y, float width, float h
12381398
12391399void CanvasRenderingContext2D::setShadow(float width, float height, float blur, const String& colorString, std::optional<float> alpha)
12401400{
 1401 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive)) {
 1402 Vector<Canvas2DParameterVariant> parameters { width, height, blur, colorString };
 1403 if (alpha)
 1404 parameters.append(alpha.value());
 1405
 1406 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("setShadow"), WTFMove(parameters));
 1407 }
 1408
12411409 Color color = Color::transparent;
12421410 if (!colorString.isNull()) {
12431411 color = parseColorOrCurrentColor(colorString, &canvas());

@@void CanvasRenderingContext2D::setShadow(float width, float height, float blur,
12501418
12511419void CanvasRenderingContext2D::setShadow(float width, float height, float blur, float grayLevel, float alpha)
12521420{
 1421 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 1422 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("setShadow"), { width, height, blur, grayLevel, alpha });
 1423
12531424 setShadow(FloatSize(width, height), blur, Color(grayLevel, grayLevel, grayLevel, alpha));
12541425}
12551426
12561427void CanvasRenderingContext2D::setShadow(float width, float height, float blur, float r, float g, float b, float a)
12571428{
 1429 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 1430 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("setShadow"), { width, height, blur, r, g, b, a });
 1431
12581432 setShadow(FloatSize(width, height), blur, Color(r, g, b, a));
12591433}
12601434
12611435void CanvasRenderingContext2D::setShadow(float width, float height, float blur, float c, float m, float y, float k, float a)
12621436{
 1437 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 1438 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("setShadow"), { width, height, blur, c, m, y, k, a });
 1439
12631440 setShadow(FloatSize(width, height), blur, Color(c, m, y, k, a));
12641441}
12651442
12661443void CanvasRenderingContext2D::clearShadow()
12671444{
 1445 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 1446 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("clearShadow"));
 1447
12681448 setShadow(FloatSize(), 0, Color::transparent);
12691449}
12701450

@@static inline FloatRect normalizeRect(const FloatRect& rect)
13401520
13411521ExceptionOr<void> CanvasRenderingContext2D::drawImage(CanvasImageSource&& image, float dx, float dy)
13421522{
 1523 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive)) {
 1524 String source;
 1525 WTF::switchOn(image,
 1526 [&] (RefPtr<HTMLImageElement>& imageElement) {
 1527 source = imageElement->currentSrc().string();
 1528 },
 1529 [&] (RefPtr<HTMLVideoElement>& videoElement) {
 1530 // get dataURL of current frame
 1531 source = videoElement->currentSrc().string();
 1532 },
 1533 [&] (RefPtr<HTMLCanvasElement>& canvasElement) {
 1534 source = canvasElement->toDataURL(ASCIILiteral("image/png")).releaseReturnValue();
 1535 }
 1536 );
 1537 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("drawImage"), { source, dx, dy });
 1538 }
 1539
13431540 return WTF::switchOn(image,
13441541 [&] (RefPtr<HTMLImageElement>& imageElement) -> ExceptionOr<void> {
13451542 LayoutSize destRectSize = size(*imageElement, ImageSizeType::AfterDevicePixelRatio);

@@ExceptionOr<void> CanvasRenderingContext2D::drawImage(CanvasImageSource&& image,
13551552
13561553ExceptionOr<void> CanvasRenderingContext2D::drawImage(CanvasImageSource&& image, float dx, float dy, float dw, float dh)
13571554{
 1555 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive)) {
 1556 String source;
 1557 WTF::switchOn(image,
 1558 [&] (RefPtr<HTMLImageElement>& imageElement) {
 1559 source = imageElement->currentSrc().string();
 1560 },
 1561 [&] (RefPtr<HTMLVideoElement>& videoElement) {
 1562 // get dataURL of current frame
 1563 source = videoElement->currentSrc().string();
 1564 },
 1565 [&] (RefPtr<HTMLCanvasElement>& canvasElement) {
 1566 source = canvasElement->toDataURL(ASCIILiteral("image/png")).releaseReturnValue();
 1567 }
 1568 );
 1569 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("drawImage"), { source, dx, dy, dw, dh });
 1570 }
 1571
13581572 return WTF::switchOn(image,
13591573 [&] (auto& element) -> ExceptionOr<void> {
13601574 FloatSize elementSize = size(*element);

@@ExceptionOr<void> CanvasRenderingContext2D::drawImage(CanvasImageSource&& image,
13651579
13661580ExceptionOr<void> CanvasRenderingContext2D::drawImage(CanvasImageSource&& image, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh)
13671581{
 1582 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive)) {
 1583 String source;
 1584 WTF::switchOn(image,
 1585 [&] (RefPtr<HTMLImageElement>& imageElement) {
 1586 source = imageElement->currentSrc().string();
 1587 },
 1588 [&] (RefPtr<HTMLVideoElement>& videoElement) {
 1589 // get dataURL of current frame
 1590 source = videoElement->currentSrc().string();
 1591 },
 1592 [&] (RefPtr<HTMLCanvasElement>& canvasElement) {
 1593 source = canvasElement->toDataURL(ASCIILiteral("image/png")).releaseReturnValue();
 1594 }
 1595 );
 1596 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("drawImage"), { source, sx, sy, sw, sh, dx, dy, dw, dh });
 1597 }
 1598
13681599 return WTF::switchOn(image,
13691600 [&] (auto& element) -> ExceptionOr<void> {
13701601 return this->drawImage(*element, FloatRect { sx, sy, sw, sh }, FloatRect { dx, dy, dw, dh });

@@ExceptionOr<void> CanvasRenderingContext2D::drawImage(HTMLVideoElement& video, c
15621793
15631794void CanvasRenderingContext2D::drawImageFromRect(HTMLImageElement& imageElement, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh, const String& compositeOperation)
15641795{
 1796 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 1797 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("drawImageFromRect"), { imageElement.currentSrc().string(), sx, sy, sw, sh, dx, dy, dw, dh, compositeOperation });
 1798
15651799 CompositeOperator op;
15661800 auto blendOp = BlendModeNormal;
15671801 if (!parseCompositeAndBlendOperator(compositeOperation, op, blendOp) || blendOp != BlendModeNormal)

@@void CanvasRenderingContext2D::drawImageFromRect(HTMLImageElement& imageElement,
15711805
15721806void CanvasRenderingContext2D::setAlpha(float alpha)
15731807{
 1808 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 1809 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("setAlpha"), { alpha });
 1810
15741811 setGlobalAlpha(alpha);
15751812}
15761813
15771814void CanvasRenderingContext2D::setCompositeOperation(const String& operation)
15781815{
 1816 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 1817 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("setCompositeOperation"), { operation });
 1818
15791819 setGlobalCompositeOperation(operation);
15801820}
15811821

@@CanvasRenderingContext2D::Style CanvasRenderingContext2D::strokeStyle() const
17201960void CanvasRenderingContext2D::setStrokeStyle(CanvasRenderingContext2D::Style&& style)
17211961{
17221962 WTF::switchOn(style,
1723  [this] (const String& string) { this->setStrokeColor(string); },
1724  [this] (const RefPtr<CanvasGradient>& gradient) { this->setStrokeStyle(CanvasStyle(*gradient)); },
1725  [this] (const RefPtr<CanvasPattern>& pattern) { this->setStrokeStyle(CanvasStyle(*pattern)); }
 1963 [this] (const String& string) {
 1964 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 1965 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("strokeStyle"), { string });
 1966
 1967 if (string == state().unparsedStrokeColor)
 1968 return;
 1969
 1970 realizeSaves();
 1971 setStrokeStyle(CanvasStyle::createFromString(string));
 1972 modifiableState().unparsedStrokeColor = string;
 1973 },
 1974 [this] (const RefPtr<CanvasGradient>& gradient) {
 1975 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 1976 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("strokeStyle"), { gradient });
 1977
 1978 setStrokeStyle(CanvasStyle(*gradient));
 1979 },
 1980 [this] (const RefPtr<CanvasPattern>& pattern) {
 1981 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 1982 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("strokeStyle"), { pattern });
 1983
 1984 setStrokeStyle(CanvasStyle(*pattern));
 1985 }
17261986 );
17271987}
17281988

@@CanvasRenderingContext2D::Style CanvasRenderingContext2D::fillStyle() const
17341994void CanvasRenderingContext2D::setFillStyle(CanvasRenderingContext2D::Style&& style)
17351995{
17361996 WTF::switchOn(style,
1737  [this] (const String& string) { this->setFillColor(string); },
1738  [this] (const RefPtr<CanvasGradient>& gradient) { this->setFillStyle(CanvasStyle(*gradient)); },
1739  [this] (const RefPtr<CanvasPattern>& pattern) { this->setFillStyle(CanvasStyle(*pattern)); }
 1997 [this] (const String& string) {
 1998 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 1999 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("fillStyle"), { string });
 2000
 2001 if (string == state().unparsedFillColor)
 2002 return;
 2003
 2004 realizeSaves();
 2005 setFillStyle(CanvasStyle::createFromString(string));
 2006 modifiableState().unparsedFillColor = string;
 2007 },
 2008 [this] (const RefPtr<CanvasGradient>& gradient) {
 2009 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 2010 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("fillStyle"), { gradient });
 2011
 2012 setFillStyle(CanvasStyle(*gradient));
 2013 },
 2014 [this] (const RefPtr<CanvasPattern>& pattern) {
 2015 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 2016 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("fillStyle"), { pattern });
 2017
 2018 setFillStyle(CanvasStyle(*pattern));
 2019 }
17402020 );
17412021}
17422022
17432023ExceptionOr<Ref<CanvasGradient>> CanvasRenderingContext2D::createLinearGradient(float x0, float y0, float x1, float y1)
17442024{
 2025 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 2026 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("createLinearGradient"), { x0, y0, x1, y1 });
 2027
17452028 if (!std::isfinite(x0) || !std::isfinite(y0) || !std::isfinite(x1) || !std::isfinite(y1))
17462029 return Exception { NOT_SUPPORTED_ERR };
17472030

@@ExceptionOr<Ref<CanvasGradient>> CanvasRenderingContext2D::createLinearGradient(
17522035
17532036ExceptionOr<Ref<CanvasGradient>> CanvasRenderingContext2D::createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1)
17542037{
 2038 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 2039 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("createRadialGradient"), { x0, y0, r0, x1, y1, r1 });
 2040
17552041 if (!std::isfinite(x0) || !std::isfinite(y0) || !std::isfinite(r0) || !std::isfinite(x1) || !std::isfinite(y1) || !std::isfinite(r1))
17562042 return Exception { NOT_SUPPORTED_ERR };
17572043

@@ExceptionOr<Ref<CanvasGradient>> CanvasRenderingContext2D::createRadialGradient(
17652051
17662052ExceptionOr<RefPtr<CanvasPattern>> CanvasRenderingContext2D::createPattern(CanvasImageSource&& image, const String& repetition)
17672053{
 2054 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive)) {
 2055 String source;
 2056 WTF::switchOn(image,
 2057 [&] (RefPtr<HTMLImageElement>& imageElement) {
 2058 source = imageElement->currentSrc().string();
 2059 },
 2060 [&] (RefPtr<HTMLVideoElement>& videoElement) {
 2061 // get dataURL of current frame
 2062 source = videoElement->currentSrc().string();
 2063 },
 2064 [&] (RefPtr<HTMLCanvasElement>& canvasElement) {
 2065 source = canvasElement->toDataURL(ASCIILiteral("image/png")).releaseReturnValue();
 2066 }
 2067 );
 2068 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("createPattern"), { source, repetition });
 2069 }
 2070
17682071 bool repeatX, repeatY;
17692072 if (!CanvasPattern::parseRepetitionType(repetition, repeatX, repeatY))
17702073 return Exception { SYNTAX_ERR };

@@GraphicsContext* CanvasRenderingContext2D::drawingContext() const
19342237 return canvas().drawingContext();
19352238}
19362239
 2240static RefPtr<ImageData> duplicateImageData(ImageData& imageData)
 2241{
 2242 return ImageData::create(imageData.size(), Uint8ClampedArray::create(imageData.data()->data(), imageData.data()->length()).releaseNonNull());
 2243}
 2244
19372245static RefPtr<ImageData> createEmptyImageData(const IntSize& size)
19382246{
19392247 auto data = ImageData::create(size);

@@static RefPtr<ImageData> createEmptyImageData(const IntSize& size)
19442252
19452253ExceptionOr<RefPtr<ImageData>> CanvasRenderingContext2D::createImageData(ImageData* imageData) const
19462254{
 2255 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 2256 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("createImageData"), { imageData ? duplicateImageData(*imageData) : createEmptyImageData(canvas().size()) });
 2257
19472258 if (!imageData)
19482259 return Exception { NOT_SUPPORTED_ERR };
19492260

@@ExceptionOr<RefPtr<ImageData>> CanvasRenderingContext2D::createImageData(ImageDa
19522263
19532264ExceptionOr<RefPtr<ImageData>> CanvasRenderingContext2D::createImageData(float sw, float sh) const
19542265{
 2266 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 2267 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("createImageData"), { sw, sh });
 2268
19552269 if (!sw || !sh)
19562270 return Exception { INDEX_SIZE_ERR };
19572271

@@ExceptionOr<RefPtr<ImageData>> CanvasRenderingContext2D::createImageData(float s
19702284
19712285ExceptionOr<RefPtr<ImageData>> CanvasRenderingContext2D::getImageData(float sx, float sy, float sw, float sh) const
19722286{
 2287 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 2288 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("getImageData"), { sx, sy, sw, sh });
 2289
19732290 return getImageData(ImageBuffer::LogicalCoordinateSystem, sx, sy, sw, sh);
19742291}
19752292
19762293ExceptionOr<RefPtr<ImageData>> CanvasRenderingContext2D::webkitGetImageDataHD(float sx, float sy, float sw, float sh) const
19772294{
 2295 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 2296 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("webkitGetImageDataHD"), { sx, sy, sw, sh });
 2297
19782298 return getImageData(ImageBuffer::BackingStoreCoordinateSystem, sx, sy, sw, sh);
19792299}
19802300

@@ExceptionOr<RefPtr<ImageData>> CanvasRenderingContext2D::getImageData(ImageBuffe
20282348
20292349void CanvasRenderingContext2D::putImageData(ImageData& data, float dx, float dy)
20302350{
2031  putImageData(data, dx, dy, 0, 0, data.width(), data.height());
 2351 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 2352 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("putImageData"), { duplicateImageData(data), dx, dy });
 2353
 2354 putImageData(data, ImageBuffer::LogicalCoordinateSystem, dx, dy, 0, 0, data.width(), data.height());
20322355}
20332356
20342357void CanvasRenderingContext2D::webkitPutImageDataHD(ImageData& data, float dx, float dy)
20352358{
2036  webkitPutImageDataHD(data, dx, dy, 0, 0, data.width(), data.height());
 2359 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 2360 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("webkitPutImageDataHD"), { duplicateImageData(data), dx, dy });
 2361
 2362 putImageData(data, ImageBuffer::BackingStoreCoordinateSystem, dx, dy, 0, 0, data.width(), data.height());
20372363}
20382364
20392365void CanvasRenderingContext2D::putImageData(ImageData& data, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight)
20402366{
 2367 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 2368 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("putImageData"), { duplicateImageData(data), dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight });
 2369
20412370 putImageData(data, ImageBuffer::LogicalCoordinateSystem, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight);
20422371}
20432372
20442373void CanvasRenderingContext2D::webkitPutImageDataHD(ImageData& data, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight)
20452374{
 2375 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 2376 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("webkitPutImageDataHD"), { duplicateImageData(data), dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight });
 2377
20462378 putImageData(data, ImageBuffer::BackingStoreCoordinateSystem, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight);
20472379}
20482380
20492381void CanvasRenderingContext2D::drawFocusIfNeeded(Element& element)
20502382{
 2383 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 2384 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("drawFocusIfNeeded"), { String("element") });
 2385
20512386 drawFocusIfNeededInternal(m_path, element);
20522387}
20532388
20542389void CanvasRenderingContext2D::drawFocusIfNeeded(DOMPath& path, Element& element)
20552390{
 2391 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 2392 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("drawFocusIfNeeded"), { path.toString(), String("element") });
 2393
20562394 drawFocusIfNeededInternal(path.path(), element);
20572395}
20582396

@@String CanvasRenderingContext2D::font() const
21332471
21342472void CanvasRenderingContext2D::setFont(const String& newFont)
21352473{
 2474 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 2475 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("font"), { newFont });
 2476
21362477 if (newFont == state().unparsedFont && state().font.realized())
21372478 return;
21382479

@@String CanvasRenderingContext2D::textAlign() const
21982539
21992540void CanvasRenderingContext2D::setTextAlign(const String& s)
22002541{
 2542 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 2543 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("textAlign"), { s });
 2544
22012545 TextAlign align;
22022546 if (!parseTextAlign(s, align))
22032547 return;

@@String CanvasRenderingContext2D::textBaseline() const
22142558
22152559void CanvasRenderingContext2D::setTextBaseline(const String& s)
22162560{
 2561 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 2562 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("textBaseline"), { s });
 2563
22172564 TextBaseline baseline;
22182565 if (!parseTextBaseline(s, baseline))
22192566 return;

@@String CanvasRenderingContext2D::direction() const
22492596
22502597void CanvasRenderingContext2D::setDirection(const String& directionString)
22512598{
 2599 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 2600 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("direction"), { directionString });
 2601
22522602 Direction direction;
22532603 if (directionString == "inherit")
22542604 direction = Direction::Inherit;

@@void CanvasRenderingContext2D::setDirection(const String& directionString)
22682618
22692619void CanvasRenderingContext2D::fillText(const String& text, float x, float y, std::optional<float> maxWidth)
22702620{
 2621 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive)) {
 2622 Vector<Canvas2DParameterVariant> parameters { text, x, y };
 2623 if (maxWidth)
 2624 parameters.append(maxWidth.value());
 2625
 2626 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("fillText"), WTFMove(parameters));
 2627 }
 2628
22712629 drawTextInternal(text, x, y, true, maxWidth);
22722630}
22732631
22742632void CanvasRenderingContext2D::strokeText(const String& text, float x, float y, std::optional<float> maxWidth)
22752633{
 2634 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive)) {
 2635 Vector<Canvas2DParameterVariant> parameters { text, x, y };
 2636 if (maxWidth)
 2637 parameters.append(maxWidth.value());
 2638
 2639 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("strokeText"), WTFMove(parameters));
 2640 }
 2641
22762642 drawTextInternal(text, x, y, false, maxWidth);
22772643}
22782644

@@static void normalizeSpaces(String& text)
23082674
23092675Ref<TextMetrics> CanvasRenderingContext2D::measureText(const String& text)
23102676{
 2677 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 2678 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("measureText"), { text });
 2679
23112680 Ref<TextMetrics> metrics = TextMetrics::create();
23122681
23132682 String normalizedText = text;

@@auto CanvasRenderingContext2D::imageSmoothingQuality() const -> ImageSmoothingQu
25472916
25482917void CanvasRenderingContext2D::setImageSmoothingQuality(ImageSmoothingQuality quality)
25492918{
 2919 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 2920 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("imageSmoothingQuality"), { stringForImageSmoothingQuality(quality) });
 2921
25502922 if (quality == state().imageSmoothingQuality)
25512923 return;
25522924

@@bool CanvasRenderingContext2D::imageSmoothingEnabled() const
25672939
25682940void CanvasRenderingContext2D::setImageSmoothingEnabled(bool enabled)
25692941{
 2942 if (UNLIKELY(canvas().recordingState() != HTMLCanvasElement::RecordingState::Inactive))
 2943 InspectorInstrumentation::recordCanvasAction(canvas(), ASCIILiteral("imageSmoothingEnabled"), { enabled });
 2944
25702945 if (enabled == state().imageSmoothingEnabled)
25712946 return;
25722947

Source/WebCore/html/canvas/CanvasRenderingContext2D.h

@@public:
104104 String globalCompositeOperation() const;
105105 void setGlobalCompositeOperation(const String&);
106106
107  void save() { ++m_unrealizedSaveCount; }
 107 void save();
108108 void restore();
109109
110110 // This is a no-op in a direct-2d canvas.

@@public:
215215 void setImageSmoothingEnabled(bool);
216216
217217 enum class ImageSmoothingQuality { Low, Medium, High };
 218 static inline String stringForImageSmoothingQuality(ImageSmoothingQuality quality)
 219 {
 220 switch (quality) {
 221 case ImageSmoothingQuality::Low:
 222 return ASCIILiteral("low");
 223 case ImageSmoothingQuality::Medium:
 224 return ASCIILiteral("medium");
 225 case ImageSmoothingQuality::High:
 226 return ASCIILiteral("high");
 227 }
 228
 229 ASSERT_NOT_REACHED();
 230 return "";
 231 }
 232
218233 ImageSmoothingQuality imageSmoothingQuality() const;
219234 void setImageSmoothingQuality(ImageSmoothingQuality);
220235

@@public:
227242 String displayListAsText(DisplayList::AsTextFlags) const;
228243 String replayDisplayListAsText(DisplayList::AsTextFlags) const;
229244
230 private:
231245 enum class Direction {
232246 Inherit,
233247 RTL,

@@private:
291305 FontProxy font;
292306 };
293307
 308 State& modifiableState() { ASSERT(!m_unrealizedSaveCount || m_stateStack.size() >= MaxSaveCount); return m_stateStack.last(); }
 309 const State& state() const { return m_stateStack.last(); }
 310
 311private:
294312 enum CanvasDidDrawOption {
295313 CanvasDidDrawApplyNone = 0,
296314 CanvasDidDrawApplyTransform = 1,

@@private:
299317 CanvasDidDrawApplyAll = 0xffffffff
300318 };
301319
302  State& modifiableState() { ASSERT(!m_unrealizedSaveCount || m_stateStack.size() >= MaxSaveCount); return m_stateStack.last(); }
303  const State& state() const { return m_stateStack.last(); }
304 
305320 void applyLineDash() const;
306321 void setShadow(const FloatSize& offset, float blur, const Color&);
307322 void applyShadow();

@@private:
378393 bool is2d() const override { return true; }
379394 bool isAccelerated() const override;
380395
 396 bool isCanvasRenderingContext2D() const override { return true; }
 397
381398 bool hasInvertibleTransform() const override { return state().hasInvertibleTransform; }
382399 TextDirection toTextDirection(Direction, const RenderStyle** computedStyle = nullptr) const;
383400

@@private:
399416
400417} // namespace WebCore
401418
402 SPECIALIZE_TYPE_TRAITS_CANVASRENDERINGCONTEXT(WebCore::CanvasRenderingContext2D, is2d())
 419SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::CanvasRenderingContext2D)
 420 static bool isType(const WebCore::CanvasRenderingContext& context) { return context.is2d(); }
 421 static bool isType(const WebCore::CanvasPath& canvasPath) { return canvasPath.isCanvasRenderingContext2D(); }
 422SPECIALIZE_TYPE_TRAITS_END()

Source/WebCore/html/canvas/DOMPath.h

@@public:
6363
6464 const Path& path() const { return m_path; }
6565
 66 String toString() const
 67 {
 68 String result;
 69 buildStringFromPath(m_path, result);
 70 return result;
 71 }
 72
 73 bool isDOMPath() const override { return true; }
 74
6675private:
6776 DOMPath() { }
6877 DOMPath(const Path& path)

@@private:
7180};
7281
7382} // namespace WebCore
 83
 84SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::DOMPath)
 85 static bool isType(const WebCore::CanvasPath& canvasPath) { return canvasPath.isDOMPath(); }
 86SPECIALIZE_TYPE_TRAITS_END()

Source/WebCore/inspector/InspectorCanvasActionTypes.h

 1/*
 2 * Copyright (C) 2017 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#pragma once
 27
 28#include "CanvasGradient.h"
 29#include "CanvasPattern.h"
 30#include "ImageData.h"
 31#include <wtf/RefPtr.h>
 32#include <wtf/Variant.h>
 33#include <wtf/Vector.h>
 34#include <wtf/text/WTFString.h>
 35
 36namespace WebCore {
 37
 38typedef Variant<RefPtr<CanvasGradient>, RefPtr<CanvasPattern>, RefPtr<ImageData>, Vector<float>, String, double, float, unsigned, bool> Canvas2DParameterVariant;
 39
 40} // namespace WebCore

Source/WebCore/inspector/InspectorCanvasAgent.cpp

2626#include "config.h"
2727#include "InspectorCanvasAgent.h"
2828
 29#include "CanvasGradient.h"
 30#include "CanvasPattern.h"
2931#include "CanvasRenderingContext.h"
3032#include "CanvasRenderingContext2D.h"
3133#include "Document.h"
3234#include "Frame.h"
 35#include "Gradient.h"
 36#include "ImageData.h"
3337#include "InspectorDOMAgent.h"
3438#include "InspectorPageAgent.h"
3539#include "InstrumentingAgents.h"

3943#include "JSWebGL2RenderingContext.h"
4044#include "JSWebGPURenderingContext.h"
4145#include "MainFrame.h"
 46#include "Pattern.h"
4247#include "ScriptState.h"
4348#include "WebGL2RenderingContext.h"
4449#include "ScriptState.h"

4954#include <inspector/IdentifiersFactory.h>
5055#include <inspector/InjectedScript.h>
5156#include <inspector/InjectedScriptManager.h>
52 #include <inspector/InspectorProtocolObjects.h>
5357#include <runtime/JSCInlines.h>
5458
5559using namespace Inspector;

@@InspectorCanvasAgent::InspectorCanvasAgent(WebAgentContext& context, InspectorPa
6266 , m_backendDispatcher(Inspector::CanvasBackendDispatcher::create(context.backendDispatcher, this))
6367 , m_injectedScriptManager(context.injectedScriptManager)
6468 , m_pageAgent(pageAgent)
65  , m_timer(*this, &InspectorCanvasAgent::canvasDestroyedTimerFired)
 69 , m_canvasRecordingTimer(*this, &InspectorCanvasAgent::canvasRecordingTimerFired)
 70 , m_canvasDestroyedTimer(*this, &InspectorCanvasAgent::canvasDestroyedTimerFired)
6671{
6772}
6873

@@void InspectorCanvasAgent::disable(ErrorString&)
100105 if (!m_enabled)
101106 return;
102107
103  if (m_timer.isActive())
104  m_timer.stop();
 108 if (m_canvasDestroyedTimer.isActive())
 109 m_canvasDestroyedTimer.stop();
105110
106111 m_removedCanvasIdentifiers.clear();
107112

@@void InspectorCanvasAgent::resolveCanvasContext(ErrorString& errorString, const
215220 result = injectedScript.wrapObject(value, objectGroupName);
216221}
217222
 223void InspectorCanvasAgent::toggleRecording(ErrorString& errorString, const String& canvasId, bool flag)
 224{
 225 const CanvasEntry* canvasEntry = getCanvasEntry(canvasId);
 226 if (!canvasEntry) {
 227 errorString = ASCIILiteral("Invalid canvas identifier");
 228 return;
 229 }
 230
 231 if (!flag) {
 232 clearRecordingData(*canvasEntry->element);
 233
 234 canvasEntry->element->setRecordingState(HTMLCanvasElement::RecordingState::Inactive);
 235 } else if (canvasEntry->element->recordingState() == HTMLCanvasElement::RecordingState::Inactive)
 236 canvasEntry->element->setRecordingState(HTMLCanvasElement::RecordingState::Requested);
 237}
 238
218239void InspectorCanvasAgent::frameNavigated(Frame& frame)
219240{
220241 if (frame.isMainFrame()) {

@@void InspectorCanvasAgent::didChangeCanvasMemory(HTMLCanvasElement& canvasElemen
271292 m_frontendDispatcher->canvasMemoryChanged(canvasEntry->identifier, canvasElement.memoryCost());
272293}
273294
 295static RefPtr<Inspector::Protocol::Array<double>> buildArrayForAffineTransform(const AffineTransform& affineTransform)
 296{
 297 RefPtr<Inspector::Protocol::Array<double>> array = Inspector::Protocol::Array<double>::create();
 298 array->addItem(affineTransform.a());
 299 array->addItem(affineTransform.b());
 300 array->addItem(affineTransform.c());
 301 array->addItem(affineTransform.d());
 302 array->addItem(affineTransform.e());
 303 array->addItem(affineTransform.f());
 304 return array;
 305}
 306
 307static RefPtr<InspectorObject> buildObjectForImageData(const ImageData& imageData)
 308{
 309 RefPtr<InspectorObject> object = InspectorObject::create();
 310 object->setInteger(ASCIILiteral("width"), imageData.width());
 311 object->setInteger(ASCIILiteral("height"), imageData.height());
 312
 313 RefPtr<Inspector::Protocol::Array<int>> data = Inspector::Protocol::Array<int>::create();
 314 for (size_t i = 0; i < imageData.data()->length(); ++i)
 315 data->addItem(imageData.data()->item(i));
 316 object->setArray(ASCIILiteral("data"), WTFMove(data));
 317
 318 return object;
 319}
 320
 321static RefPtr<InspectorObject> buildObjectForCanvasGradient(const CanvasGradient& canvasGradient)
 322{
 323 bool isRadial = canvasGradient.gradient().isRadial();
 324 RefPtr<InspectorObject> object = InspectorObject::create();
 325 object->setString("type", isRadial ? "radial-gradient" : "linear-gradient");
 326
 327 RefPtr<Inspector::Protocol::Array<float>> parameters = Inspector::Protocol::Array<float>::create();
 328 parameters->addItem(canvasGradient.gradient().p0().x());
 329 parameters->addItem(canvasGradient.gradient().p0().y());
 330 if (isRadial)
 331 parameters->addItem(canvasGradient.gradient().startRadius());
 332 parameters->addItem(canvasGradient.gradient().p1().x());
 333 parameters->addItem(canvasGradient.gradient().p1().y());
 334 if (isRadial)
 335 parameters->addItem(canvasGradient.gradient().endRadius());
 336 object->setArray(ASCIILiteral("parameters"), WTFMove(parameters));
 337
 338 if (!canvasGradient.gradient().stops().isEmpty()) {
 339 RefPtr<Inspector::Protocol::Array<InspectorValue>> stops = Inspector::Protocol::Array<InspectorValue>::create();
 340 for (const Gradient::ColorStop& colorStop : canvasGradient.gradient().stops()) {
 341 RefPtr<Inspector::Protocol::Array<InspectorValue>> stop = Inspector::Protocol::Array<InspectorValue>::create();
 342 stop->addItem(colorStop.offset);
 343 stop->addItem(colorStop.color.cssText());
 344 stops->addItem(WTFMove(stop));
 345 }
 346 object->setArray(ASCIILiteral("stops"), WTFMove(stops));
 347 }
 348
 349 return object;
 350}
 351
 352static RefPtr<InspectorObject> buildObjectForCanvasPattern(const CanvasPattern& canvasPattern)
 353{
 354 RefPtr<InspectorObject> object = InspectorObject::create();
 355 object->setString(ASCIILiteral("type"), ASCIILiteral("pattern"));
 356 object->setString(ASCIILiteral("image"), ASCIILiteral("data:,"));
 357 // object->setString(ASCIILiteral("image"), "data:image/png," + base64Encode(pattern->tileImage().data()));
 358
 359 String repeat;
 360 bool repeatX = canvasPattern.pattern().repeatX();
 361 bool repeatY = canvasPattern.pattern().repeatY();
 362 if (repeatX && repeatY)
 363 repeat = ASCIILiteral("repeat");
 364 else if (repeatX && !repeatY)
 365 repeat = ASCIILiteral("repeat-x");
 366 else if (!repeatX && repeatY)
 367 repeat = ASCIILiteral("repeat-y");
 368 else
 369 repeat = ASCIILiteral("no-repeat");
 370 object->setString(ASCIILiteral("repeat"), repeat);
 371
 372 return object;
 373}
 374
 375static RefPtr<Inspector::Protocol::Array<double>> buildArrayForVector(const Vector<float>& vector)
 376{
 377 RefPtr<Inspector::Protocol::Array<double>> array = Inspector::Protocol::Array<double>::create();
 378 for (double item : vector)
 379 array->addItem(item);
 380 return array;
 381}
 382
 383void InspectorCanvasAgent::didStartRecordingCanvas(HTMLCanvasElement& canvasElement, bool fromConsole)
 384{
 385 CanvasEntry* canvasEntry = getCanvasEntry(canvasElement);
 386 if (!canvasEntry)
 387 return;
 388
 389 auto initialState = Inspector::Protocol::Canvas::InitialState::create()
 390 .release();
 391
 392 RefPtr<InspectorObject> attributes = InspectorObject::create();
 393 RefPtr<InspectorObject> functions = InspectorObject::create();
 394
 395 attributes->setInteger(ASCIILiteral("width"), canvasEntry->element->width());
 396 attributes->setInteger(ASCIILiteral("height"), canvasEntry->element->height());
 397
 398 CanvasRenderingContext* context = canvasEntry->element->renderingContext();
 399 if (is<CanvasRenderingContext2D>(context)) {
 400 CanvasRenderingContext2D* context2d = downcast<CanvasRenderingContext2D>(context);
 401
 402 functions->setArray(ASCIILiteral("transform"), buildArrayForAffineTransform(context2d->state().transform));
 403 attributes->setDouble(ASCIILiteral("globalAlpha"), context2d->globalAlpha());
 404 attributes->setString(ASCIILiteral("globalCompositeOperation"), context2d->globalCompositeOperation());
 405 attributes->setDouble(ASCIILiteral("lineWidth"), context2d->lineWidth());
 406 attributes->setString(ASCIILiteral("lineCap"), context2d->lineCap());
 407 attributes->setString(ASCIILiteral("lineJoin"), context2d->lineJoin());
 408 attributes->setDouble(ASCIILiteral("miterLimit"), context2d->miterLimit());
 409 attributes->setDouble(ASCIILiteral("shadowOffsetX"), context2d->shadowOffsetX());
 410 attributes->setDouble(ASCIILiteral("shadowOffsetY"), context2d->shadowOffsetY());
 411 attributes->setDouble(ASCIILiteral("shadowBlur"), context2d->shadowBlur());
 412 attributes->setString(ASCIILiteral("shadowColor"), context2d->shadowColor());
 413 functions->setArray(ASCIILiteral("setLineDash"), buildArrayForVector(context2d->getLineDash()));
 414 attributes->setDouble(ASCIILiteral("lineDashOffset"), context2d->lineDashOffset());
 415 attributes->setString(ASCIILiteral("font"), context2d->font());
 416 attributes->setString(ASCIILiteral("textAlign"), context2d->textAlign());
 417 attributes->setString(ASCIILiteral("textBaseline"), context2d->textBaseline());
 418 attributes->setString(ASCIILiteral("direction"), context2d->direction());
 419
 420 if (const CanvasGradient* canvasGradient = context2d->state().strokeStyle.canvasGradient())
 421 attributes->setObject(ASCIILiteral("strokeStyle"), buildObjectForCanvasGradient(*canvasGradient));
 422 else if (const CanvasPattern* canvasPattern = context2d->state().strokeStyle.canvasPattern())
 423 attributes->setObject(ASCIILiteral("strokeStyle"), buildObjectForCanvasPattern(*canvasPattern));
 424 else
 425 attributes->setString(ASCIILiteral("strokeStyle"), context2d->state().strokeStyle.color());
 426
 427 if (const CanvasGradient* canvasGradient = context2d->state().fillStyle.canvasGradient())
 428 attributes->setObject(ASCIILiteral("fillStyle"), buildObjectForCanvasGradient(*canvasGradient));
 429 else if (const CanvasPattern* canvasPattern = context2d->state().fillStyle.canvasPattern())
 430 attributes->setObject(ASCIILiteral("fillStyle"), buildObjectForCanvasPattern(*canvasPattern));
 431 else
 432 attributes->setString(ASCIILiteral("fillStyle"), context2d->state().fillStyle.color());
 433
 434 attributes->setBoolean(ASCIILiteral("imageSmoothingEnabled"), context2d->imageSmoothingEnabled());
 435 attributes->setString(ASCIILiteral("imageSmoothingQuality"), CanvasRenderingContext2D::stringForImageSmoothingQuality(context2d->imageSmoothingQuality()));
 436 }
 437
 438 if (attributes->size())
 439 initialState->setAttributes(WTFMove(attributes));
 440
 441 if (functions->size())
 442 initialState->setFunctions(WTFMove(functions));
 443
 444 ExceptionOr<String> result = canvasEntry->element->toDataURL(ASCIILiteral("image/png"));
 445 if (!result.hasException())
 446 initialState->setContent(result.releaseReturnValue());
 447
 448 m_recordingData.set(canvasEntry->element, CanvasRecordingData(WTFMove(initialState), fromConsole));
 449
 450 if (!fromConsole && !m_canvasRecordingTimer.isActive())
 451 m_canvasRecordingTimer.startOneShot(0_s);
 452
 453 canvasElement.setRecordingState(HTMLCanvasElement::RecordingState::Active);
 454}
 455
 456void InspectorCanvasAgent::recordCanvasAction(HTMLCanvasElement& canvasElement, const String& name, Vector<Canvas2DParameterVariant>&& parameters)
 457{
 458 if (canvasElement.recordingState() == HTMLCanvasElement::RecordingState::Requested)
 459 didStartRecordingCanvas(canvasElement);
 460
 461 CanvasRecordingData* data = getRecordingData(canvasElement);
 462 if (!data)
 463 return;
 464
 465 auto action = Inspector::Protocol::Canvas::RecordingAction::create()
 466 .setName(name)
 467 .release();
 468
 469 if (!parameters.isEmpty()) {
 470 RefPtr<Inspector::Protocol::Array<Inspector::InspectorValue>> parametersData = Inspector::Protocol::Array<Inspector::InspectorValue>::create();
 471 for (const Canvas2DParameterVariant& item : parameters) {
 472 WTF::switchOn(item,
 473 [&] (const RefPtr<CanvasGradient>& value) { parametersData->addItem(buildObjectForCanvasGradient(*value)); },
 474 [&] (const RefPtr<CanvasPattern>& value) { parametersData->addItem(buildObjectForCanvasPattern(*value)); },
 475 [&] (const RefPtr<ImageData>& value) { parametersData->addItem(buildObjectForImageData(*value)); },
 476 [&] (const Vector<float>& value) { parametersData->addItem(buildArrayForVector(value)); },
 477 [&] (const String& value) { parametersData->addItem(value); },
 478 [&] (double value) { parametersData->addItem(value); },
 479 [&] (float value) { parametersData->addItem(value); },
 480 [&] (unsigned value) { parametersData->addItem(static_cast<int>(value)); },
 481 [&] (bool value) { parametersData->addItem(value); }
 482 );
 483 }
 484 action->setParameters(WTFMove(parametersData));
 485 }
 486
 487 data->actions->addItem(WTFMove(action));
 488}
 489
 490void InspectorCanvasAgent::didFinishRecordingCanvas(HTMLCanvasElement& canvasElement, bool fromConsole)
 491{
 492 CanvasEntry* canvasEntry = getCanvasEntry(canvasElement);
 493 if (!canvasEntry) {
 494 clearRecordingData(canvasElement);
 495 return;
 496 }
 497
 498 CanvasRecordingData* data = getRecordingData(*canvasEntry->element);
 499 if (!data) {
 500 clearRecordingData(canvasElement);
 501 return;
 502 }
 503
 504 if (!fromConsole && data->fromConsole)
 505 return;
 506
 507 m_frontendDispatcher->recordingFinished(canvasEntry->identifier, data->initialState, data->actions);
 508
 509 clearRecordingData(canvasElement);
 510}
 511
274512void InspectorCanvasAgent::canvasDestroyed(HTMLCanvasElement& canvasElement)
275513{
276514 auto it = m_canvasEntries.find(&canvasElement);

@@void InspectorCanvasAgent::canvasDestroyed(HTMLCanvasElement& canvasElement)
288526 // the frontend from making JS allocations while the GC is still active.
289527 m_removedCanvasIdentifiers.append(canvasIdentifier);
290528
291  if (!m_timer.isActive())
292  m_timer.startOneShot(0_s);
 529 if (!m_canvasDestroyedTimer.isActive())
 530 m_canvasDestroyedTimer.startOneShot(0_s);
293531}
294532
295533void InspectorCanvasAgent::canvasDestroyedTimerFired()

@@void InspectorCanvasAgent::canvasDestroyedTimerFired()
303541 m_removedCanvasIdentifiers.clear();
304542}
305543
 544void InspectorCanvasAgent::canvasRecordingTimerFired()
 545{
 546 for (HTMLCanvasElement* canvasElement : m_recordingData.keys()) {
 547 if (canvasElement->recordingState() != HTMLCanvasElement::RecordingState::Active)
 548 continue;
 549
 550 didFinishRecordingCanvas(*canvasElement);
 551 }
 552}
 553
306554void InspectorCanvasAgent::clearCanvasData()
307555{
308556 for (auto* canvasElement : m_canvasEntries.keys())

@@void InspectorCanvasAgent::clearCanvasData()
311559 m_canvasEntries.clear();
312560 m_canvasToCSSCanvasId.clear();
313561 m_removedCanvasIdentifiers.clear();
 562 m_recordingData.clear();
314563
315  if (m_timer.isActive())
316  m_timer.stop();
 564 if (m_canvasRecordingTimer.isActive())
 565 m_canvasRecordingTimer.stop();
 566
 567 if (m_canvasDestroyedTimer.isActive())
 568 m_canvasDestroyedTimer.stop();
 569}
 570
 571void InspectorCanvasAgent::clearRecordingData(HTMLCanvasElement& canvasElement)
 572{
 573 canvasElement.setRecordingState(HTMLCanvasElement::RecordingState::Inactive);
 574
 575 auto it = m_recordingData.find(&canvasElement);
 576 if (it != m_recordingData.end())
 577 m_recordingData.remove(it);
 578
 579 if (m_canvasRecordingTimer.isActive())
 580 m_canvasRecordingTimer.stop();
317581}
318582
319583InspectorCanvasAgent::CanvasEntry* InspectorCanvasAgent::getCanvasEntry(HTMLCanvasElement& canvasElement)

@@InspectorCanvasAgent::CanvasEntry* InspectorCanvasAgent::getCanvasEntry(const St
335599 return nullptr;
336600}
337601
 602InspectorCanvasAgent::CanvasRecordingData* InspectorCanvasAgent::getRecordingData(HTMLCanvasElement& canvasElement)
 603{
 604 auto findResult = m_recordingData.find(&canvasElement);
 605 if (findResult == m_recordingData.end())
 606 return nullptr;
 607
 608 return &findResult->value;
 609}
 610
338611Ref<Inspector::Protocol::Canvas::Canvas> InspectorCanvasAgent::buildObjectForCanvas(const CanvasEntry& canvasEntry, HTMLCanvasElement& canvasElement)
339612{
340613 Frame* frame = canvasElement.document().frame();

Source/WebCore/inspector/InspectorCanvasAgent.h

2626#pragma once
2727
2828#include "HTMLCanvasElement.h"
 29#include "InspectorCanvasActionTypes.h"
2930#include "InspectorWebAgentBase.h"
3031#include "Timer.h"
3132#include <inspector/InspectorBackendDispatchers.h>
3233#include <inspector/InspectorFrontendDispatchers.h>
 34#include <inspector/InspectorProtocolObjects.h>
3335#include <wtf/HashMap.h>
3436#include <wtf/HashSet.h>
3537#include <wtf/RefPtr.h>

@@public:
6567 void requestContent(ErrorString&, const String& canvasId, String* content) override;
6668 void maxPixelMemory(ErrorString&, double* maxPixelMemory) override;
6769 void resolveCanvasContext(ErrorString&, const String& canvasId, const String* const objectGroup, RefPtr<Inspector::Protocol::Runtime::RemoteObject>&) override;
 70 void toggleRecording(ErrorString&, const String& canvasId, bool flag) override;
6871
6972 // InspectorInstrumentation
7073 void frameNavigated(Frame&);
7174 void didCreateCSSCanvas(HTMLCanvasElement&, const String&);
7275 void didCreateCanvasRenderingContext(HTMLCanvasElement&);
7376 void didChangeCanvasMemory(HTMLCanvasElement&);
 77 void didStartRecordingCanvas(HTMLCanvasElement&, bool = false);
 78 void recordCanvasAction(HTMLCanvasElement&, const String&, Vector<Canvas2DParameterVariant>&& = { });
 79 void didFinishRecordingCanvas(HTMLCanvasElement&, bool = false);
7480
7581 // CanvasObserver
7682 void canvasChanged(HTMLCanvasElement&, const FloatRect&) override { }

@@private:
9298 }
9399 };
94100
 101 struct CanvasRecordingData {
 102 RefPtr<Inspector::Protocol::Array<Inspector::Protocol::Canvas::RecordingAction>> actions;
 103 RefPtr<Inspector::Protocol::Canvas::InitialState> initialState;
 104 bool fromConsole { true };
 105
 106 CanvasRecordingData() { }
 107
 108 CanvasRecordingData(Ref<Inspector::Protocol::Canvas::InitialState>&& initialState, bool fromConsole)
 109 : actions(Inspector::Protocol::Array<Inspector::Protocol::Canvas::RecordingAction>::create())
 110 , initialState(WTFMove(initialState))
 111 , fromConsole(fromConsole)
 112 {
 113 }
 114 };
 115
95116 void canvasDestroyedTimerFired();
 117 void canvasRecordingTimerFired();
96118 void clearCanvasData();
 119 void clearRecordingData(HTMLCanvasElement&);
97120 CanvasEntry* getCanvasEntry(HTMLCanvasElement&);
98121 CanvasEntry* getCanvasEntry(const String&);
 122 CanvasRecordingData* getRecordingData(HTMLCanvasElement&);
99123 Ref<Inspector::Protocol::Canvas::Canvas> buildObjectForCanvas(const CanvasEntry&, HTMLCanvasElement&);
100124
101125 std::unique_ptr<Inspector::CanvasFrontendDispatcher> m_frontendDispatcher;

@@private:
105129
106130 HashMap<HTMLCanvasElement*, CanvasEntry> m_canvasEntries;
107131 HashMap<HTMLCanvasElement*, String> m_canvasToCSSCanvasId;
 132 HashMap<HTMLCanvasElement*, CanvasRecordingData> m_recordingData;
 133 Timer m_canvasRecordingTimer;
108134 Vector<String> m_removedCanvasIdentifiers;
109  Timer m_timer;
 135 Timer m_canvasDestroyedTimer;
 136
110137 bool m_enabled { false };
111138};
112139

Source/WebCore/inspector/InspectorInstrumentation.cpp

@@void InspectorInstrumentation::didChangeCanvasMemoryImpl(InstrumentingAgents* in
10111011 canvasAgent->didChangeCanvasMemory(canvasElement);
10121012}
10131013
 1014void InspectorInstrumentation::didStartRecordingCanvasImpl(InstrumentingAgents* instrumentingAgents, HTMLCanvasElement& canvasElement, bool fromConsole)
 1015{
 1016 if (InspectorCanvasAgent* canvasAgent = instrumentingAgents->inspectorCanvasAgent())
 1017 canvasAgent->didStartRecordingCanvas(canvasElement, fromConsole);
 1018}
 1019
 1020void InspectorInstrumentation::recordCanvasActionImpl(InstrumentingAgents* instrumentingAgents, HTMLCanvasElement& canvasElement, const String& name, Vector<Canvas2DParameterVariant>&& parameters)
 1021{
 1022 if (InspectorCanvasAgent* canvasAgent = instrumentingAgents->inspectorCanvasAgent())
 1023 canvasAgent->recordCanvasAction(canvasElement, name, WTFMove(parameters));
 1024}
 1025
 1026void InspectorInstrumentation::didFinishRecordingCanvasImpl(InstrumentingAgents* instrumentingAgents, HTMLCanvasElement& canvasElement, bool fromConsole)
 1027{
 1028 if (InspectorCanvasAgent* canvasAgent = instrumentingAgents->inspectorCanvasAgent())
 1029 canvasAgent->didFinishRecordingCanvas(canvasElement, fromConsole);
 1030}
 1031
10141032#if ENABLE(WEB_REPLAY)
10151033void InspectorInstrumentation::sessionCreatedImpl(InstrumentingAgents& instrumentingAgents, RefPtr<ReplaySession>&& session)
10161034{

Source/WebCore/inspector/InspectorInstrumentation.h

3838#include "Frame.h"
3939#include "HTMLCanvasElement.h"
4040#include "HitTestResult.h"
 41#include "InspectorCanvasActionTypes.h"
4142#include "InspectorController.h"
4243#include "InspectorInstrumentationCookie.h"
4344#include "Page.h"

@@public:
248249 static void didCreateCSSCanvas(HTMLCanvasElement&, const String&);
249250 static void didCreateCanvasRenderingContext(HTMLCanvasElement&);
250251 static void didChangeCanvasMemory(HTMLCanvasElement&);
 252 static void didStartRecordingCanvas(HTMLCanvasElement&, bool = false);
 253 static void recordCanvasAction(HTMLCanvasElement&, const String&, Vector<Canvas2DParameterVariant>&& = { });
 254 static void didFinishRecordingCanvas(HTMLCanvasElement&, bool = false);
251255
252256 static void networkStateChanged(Page&);
253257 static void updateApplicationCacheStatus(Frame*);

@@private:
424428 static void didCreateCSSCanvasImpl(InstrumentingAgents*, HTMLCanvasElement&, const String&);
425429 static void didCreateCanvasRenderingContextImpl(InstrumentingAgents*, HTMLCanvasElement&);
426430 static void didChangeCanvasMemoryImpl(InstrumentingAgents*, HTMLCanvasElement&);
 431 static void didStartRecordingCanvasImpl(InstrumentingAgents*, HTMLCanvasElement&, bool = false);
 432 static void recordCanvasActionImpl(InstrumentingAgents*, HTMLCanvasElement&, const String&, Vector<Canvas2DParameterVariant>&& = { });
 433 static void didFinishRecordingCanvasImpl(InstrumentingAgents*, HTMLCanvasElement&, bool = false);
427434
428435 static void layerTreeDidChangeImpl(InstrumentingAgents&);
429436 static void renderLayerDestroyedImpl(InstrumentingAgents&, const RenderLayer&);

@@inline void InspectorInstrumentation::didCreateCanvasRenderingContext(HTMLCanvas
11971204
11981205inline void InspectorInstrumentation::didChangeCanvasMemory(HTMLCanvasElement& canvasElement)
11991206{
 1207 FAST_RETURN_IF_NO_FRONTENDS(void());
12001208 if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(&canvasElement.document()))
12011209 didChangeCanvasMemoryImpl(instrumentingAgents, canvasElement);
12021210}
12031211
 1212inline void InspectorInstrumentation::didStartRecordingCanvas(HTMLCanvasElement& canvasElement, bool fromConsole)
 1213{
 1214 FAST_RETURN_IF_NO_FRONTENDS(void());
 1215 if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(&canvasElement.document()))
 1216 didStartRecordingCanvasImpl(instrumentingAgents, canvasElement, fromConsole);
 1217}
 1218
 1219inline void InspectorInstrumentation::recordCanvasAction(HTMLCanvasElement& canvasElement, const String& name, Vector<Canvas2DParameterVariant>&& parameters)
 1220{
 1221 FAST_RETURN_IF_NO_FRONTENDS(void());
 1222 if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(&canvasElement.document()))
 1223 recordCanvasActionImpl(instrumentingAgents, canvasElement, name, WTFMove(parameters));
 1224}
 1225
 1226inline void InspectorInstrumentation::didFinishRecordingCanvas(HTMLCanvasElement& canvasElement, bool fromConsole)
 1227{
 1228 FAST_RETURN_IF_NO_FRONTENDS(void());
 1229 if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(&canvasElement.document()))
 1230 didFinishRecordingCanvasImpl(instrumentingAgents, canvasElement, fromConsole);
 1231}
 1232
12041233inline void InspectorInstrumentation::networkStateChanged(Page& page)
12051234{
12061235 FAST_RETURN_IF_NO_FRONTENDS(void());

Source/WebCore/page/PageConsoleClient.cpp

2929#include "config.h"
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"
4044#include "Page.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>
4753
4854using namespace Inspector;
4955

@@void PageConsoleClient::timeStamp(JSC::ExecState*, Ref<ScriptArguments>&& argume
208214 InspectorInstrumentation::consoleTimeStamp(m_page.mainFrame(), WTFMove(arguments));
209215}
210216
 217void PageConsoleClient::record(JSC::ExecState*, Ref<ScriptArguments>&& arguments)
 218{
 219 if (arguments->argumentCount() < 1)
 220 return;
 221
 222 const JSC::JSValue& firstArgument = arguments->argumentAt(0).jsValue();
 223 if (!firstArgument.isObject())
 224 return;
 225
 226 JSC::VM& vm = *firstArgument.getObject()->vm();
 227 JSC::JSObject* object = firstArgument.getObject();
 228 if (HTMLCanvasElement* canvasElement = JSHTMLCanvasElement::toWrapped(vm, object))
 229 InspectorInstrumentation::didStartRecordingCanvas(*canvasElement, true);
 230 else if (CanvasRenderingContext2D* context2d = JSCanvasRenderingContext2D::toWrapped(vm, object))
 231 InspectorInstrumentation::didStartRecordingCanvas(context2d->canvas(), true);
 232}
 233
 234void PageConsoleClient::recordEnd(JSC::ExecState*, Ref<ScriptArguments>&& arguments)
 235{
 236 if (arguments->argumentCount() < 1)
 237 return;
 238
 239 const JSC::JSValue& firstArgument = arguments->argumentAt(0).jsValue();
 240 if (!firstArgument.isObject())
 241 return;
 242
 243 JSC::VM& vm = *firstArgument.getObject()->vm();
 244 JSC::JSObject* object = firstArgument.getObject();
 245 if (HTMLCanvasElement* canvasElement = JSHTMLCanvasElement::toWrapped(vm, object))
 246 InspectorInstrumentation::didFinishRecordingCanvas(*canvasElement, true);
 247 else if (CanvasRenderingContext2D* context2d = JSCanvasRenderingContext2D::toWrapped(vm, object))
 248 InspectorInstrumentation::didFinishRecordingCanvas(context2d->canvas(), true);
 249}
 250
211251} // namespace WebCore

Source/WebCore/page/PageConsoleClient.h

@@protected:
7474 void time(JSC::ExecState*, const String& title) override;
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:
7981 Page& m_page;

Source/WebCore/platform/graphics/Gradient.h

@@namespace WebCore {
146146 { }
147147 };
148148
 149 const Vector<ColorStop, 2>& stops() const { return m_stops; }
 150
149151 void setStopsSorted(bool s) { m_stopsSorted = s; }
150152
151153 void setSpreadMethod(GradientSpreadMethod);

Source/WebCore/svg/SVGPathUtilities.cpp

@@bool buildPathFromString(const String& d, Path& result)
4949 return SVGPathParser::parse(source, builder);
5050}
5151
 52bool buildStringFromPath(const Path& path, String& result)
 53{
 54 if (path.isNull() || path.isEmpty())
 55 return false;
 56
 57 StringBuilder builder;
 58
 59 path.apply([&builder] (const PathElement& element) {
 60 switch (element.type) {
 61 case PathElementMoveToPoint: // The points member will contain 1 value.
 62 builder.append('M');
 63 builder.appendNumber(element.points[0].x());
 64 builder.append(' ');
 65 builder.appendNumber(element.points[0].y());
 66 break;
 67 case PathElementAddLineToPoint: // The points member will contain 1 value.
 68 builder.append('L');
 69 builder.appendNumber(element.points[0].x());
 70 builder.append(' ');
 71 builder.appendNumber(element.points[0].y());
 72 break;
 73 case PathElementAddQuadCurveToPoint: // The points member will contain 2 values.
 74 builder.append('Q');
 75 builder.appendNumber(element.points[0].x());
 76 builder.append(' ');
 77 builder.appendNumber(element.points[0].y());
 78 builder.append(',');
 79 builder.appendNumber(element.points[1].x());
 80 builder.append(' ');
 81 builder.appendNumber(element.points[1].y());
 82 break;
 83 case PathElementAddCurveToPoint: // The points member will contain 3 values.
 84 builder.append('C');
 85 builder.appendNumber(element.points[0].x());
 86 builder.append(' ');
 87 builder.appendNumber(element.points[0].y());
 88 builder.append(',');
 89 builder.appendNumber(element.points[1].x());
 90 builder.append(' ');
 91 builder.appendNumber(element.points[1].y());
 92 builder.append(',');
 93 builder.appendNumber(element.points[2].x());
 94 builder.append(' ');
 95 builder.appendNumber(element.points[2].y());
 96 break;
 97 case PathElementCloseSubpath: // The points member will contain no values.
 98 break;
 99 }
 100 });
 101
 102 result = builder.toString();
 103 return true;
 104}
 105
52106bool buildSVGPathByteStreamFromSVGPathSegListValues(const SVGPathSegListValues& list, SVGPathByteStream& result, PathParsingMode parsingMode)
53107{
54108 result.clear();

Source/WebCore/svg/SVGPathUtilities.h

@@class SVGPathSegListValues;
3636bool buildPathFromString(const String&, Path&);
3737bool buildPathFromByteStream(const SVGPathByteStream&, Path&);
3838
 39// Path -> String
 40bool buildStringFromPath(const Path&, String&);
 41
3942// SVGPathSegListValues/String -> SVGPathByteStream
4043bool buildSVGPathByteStreamFromSVGPathSegListValues(const SVGPathSegListValues&, SVGPathByteStream& result, PathParsingMode);
4144bool appendSVGPathByteStreamFromSVGPathSeg(RefPtr<SVGPathSeg>&&, SVGPathByteStream&, PathParsingMode);

Source/WebCore/workers/WorkerConsoleClient.cpp

@@void WorkerConsoleClient::profileEnd(JSC::ExecState*, const String&) { }
7676void WorkerConsoleClient::takeHeapSnapshot(JSC::ExecState*, const String&) { }
7777void WorkerConsoleClient::timeStamp(JSC::ExecState*, Ref<ScriptArguments>&&) { }
7878
 79void WorkerConsoleClient::record(JSC::ExecState*, Ref<ScriptArguments>&&) { };
 80void WorkerConsoleClient::recordEnd(JSC::ExecState*, Ref<ScriptArguments>&&) { };
 81
7982} // namespace WebCore

Source/WebCore/workers/WorkerConsoleClient.h

@@protected:
5050 void time(JSC::ExecState*, const String& title) override;
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:
5557 WorkerGlobalScope& m_workerGlobalScope;

Source/WebInspectorUI/.eslintrc

103103 "timestamp": true,
104104 "handlePromiseException": true,
105105 "insertObjectIntoSortedArray": true,
 106 "numericStringComparator": true,
106107
107108 // Image Utilities
108109 "platformImagePath": true,

Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js

@@localizedStrings["Call Trees"] = "Call Trees";
148148localizedStrings["Calls"] = "Calls";
149149localizedStrings["Cancel Automatic Continue"] = "Cancel Automatic Continue";
150150localizedStrings["Cancel comparison"] = "Cancel comparison";
 151localizedStrings["Cancel recording of next active draw frame (%s)"] = "Cancel recording of next active draw frame (%s)";
151152localizedStrings["Canvas"] = "Canvas";
152153localizedStrings["Canvas %d"] = "Canvas %d";
153154localizedStrings["Canvas %s"] = "Canvas %s";

@@localizedStrings["Count"] = "Count";
244245localizedStrings["Create %s Rule"] = "Create %s Rule";
245246localizedStrings["Create a new tab"] = "Create a new tab";
246247localizedStrings["Current"] = "Current";
 248localizedStrings["Current State"] = "Current State";
247249localizedStrings["Cursor"] = "Cursor";
248250localizedStrings["Custom"] = "Custom";
249251localizedStrings["DNS"] = "DNS";

@@localizedStrings["Expand All"] = "Expand All";
370372localizedStrings["Expand columns"] = "Expand columns";
371373localizedStrings["Expanded"] = "Expanded";
372374localizedStrings["Expires"] = "Expires";
 375localizedStrings["Export"] = "Export";
373376localizedStrings["Expression"] = "Expression";
374377localizedStrings["Extension Scripts"] = "Extension Scripts";
375378localizedStrings["Extra Scripts"] = "Extra Scripts";

@@localizedStrings["File or Resource"] = "File or Resource";
384387localizedStrings["Filename"] = "Filename";
385388localizedStrings["Fill"] = "Fill";
386389localizedStrings["Fill Mode"] = "Fill Mode";
 390localizedStrings["Filter Actions"] = "Filter Actions";
387391localizedStrings["Filter Console Log"] = "Filter Console Log";
388392localizedStrings["Filter List"] = "Filter List";
389393localizedStrings["Filter Records"] = "Filter Records";

@@localizedStrings["Image"] = "Image";
460464localizedStrings["Image Size"] = "Image Size";
461465localizedStrings["Images"] = "Images";
462466localizedStrings["Immediate Pause Requested"] = "Immediate Pause Requested";
 467localizedStrings["Import"] = "Import";
463468localizedStrings["Indent"] = "Indent";
464469localizedStrings["Indent width:"] = "Indent width:";
465470localizedStrings["Index"] = "Index";

@@localizedStrings["Indexed Databases"] = "Indexed Databases";
468473localizedStrings["Info: "] = "Info: ";
469474localizedStrings["Inherited From: "] = "Inherited From: ";
470475localizedStrings["Inherited from %s"] = "Inherited from %s";
 476localizedStrings["Initial State"] = "Initial State";
471477localizedStrings["Initial Velocity"] = "Initial Velocity";
472478localizedStrings["Initiated"] = "Initiated";
473479localizedStrings["Initiator"] = "Initiator";

@@localizedStrings["Key"] = "Key";
490496localizedStrings["Key Path"] = "Key Path";
491497localizedStrings["Label"] = "Label";
492498localizedStrings["Latency"] = "Latency";
493 localizedStrings["Layer"] = "Layer";
494499localizedStrings["Layer Count: %d"] = "Layer Count: %d";
495500localizedStrings["Layer Info"] = "Layer Info";
496501localizedStrings["Layers"] = "Layers";

@@localizedStrings["No Preview Available"] = "No Preview Available";
579584localizedStrings["No Properties"] = "No Properties";
580585localizedStrings["No Properties \u2014 Click to Edit"] = "No Properties \u2014 Click to Edit";
581586localizedStrings["No Query Parameters"] = "No Query Parameters";
 587localizedStrings["No Recording Data"] = "No Recording Data";
582588localizedStrings["No Request Headers"] = "No Request Headers";
583589localizedStrings["No Response Headers"] = "No Response Headers";
584590localizedStrings["No Results Found"] = "No Results Found";

@@localizedStrings["Range Issue"] = "Range Issue";
668674localizedStrings["Readonly"] = "Readonly";
669675localizedStrings["Reasons for compositing:"] = "Reasons for compositing:";
670676localizedStrings["Recently Closed Tabs"] = "Recently Closed Tabs";
 677localizedStrings["Recording"] = "Recording";
671678localizedStrings["Recording Timeline Data"] = "Recording Timeline Data";
 679localizedStrings["Recording error: %s"] = "Recording error: %s";
672680localizedStrings["Reference Issue"] = "Reference Issue";
673681localizedStrings["Reflection"] = "Reflection";
674682localizedStrings["Refresh"] = "Refresh";

@@localizedStrings["Request"] = "Request";
692700localizedStrings["Request & Response"] = "Request & Response";
693701localizedStrings["Request Data"] = "Request Data";
694702localizedStrings["Request Headers"] = "Request Headers";
 703localizedStrings["Request recording of next active draw frame (%s)"] = "Request recording of next active draw frame (%s)";
695704localizedStrings["Requesting: %s"] = "Requesting: %s";
696705localizedStrings["Required"] = "Required";
697706localizedStrings["Reset"] = "Reset";

@@localizedStrings["spaces"] = "spaces";
955964localizedStrings["time before stopping"] = "time before stopping";
956965localizedStrings["times before stopping"] = "times before stopping";
957966localizedStrings["toggle"] = "toggle";
 967localizedStrings["unsupported version"] = "unsupported version";
958968localizedStrings["value"] = "value";
959969localizedStrings["“%s” Profile Recorded"] = "“%s” Profile Recorded";
 970localizedStrings["“%s” is invalid"] = "“%s” is invalid";

Source/WebInspectorUI/UserInterface/Base/Main.js

@@WebInspector.contentLoaded = function()
444444 WebInspector.ElementsTabContentView,
445445 WebInspector.NetworkTabContentView,
446446 WebInspector.NewTabContentView,
 447 WebInspector.RecordingTabContentView,
447448 WebInspector.ResourcesTabContentView,
448449 WebInspector.SearchTabContentView,
449450 WebInspector.SettingsTabContentView,

@@WebInspector.contentLoaded = function()
478479 let tabContentView = this._createTabContentViewForType(tabType);
479480 if (!tabContentView)
480481 continue;
481  this.tabBrowser.addTabForContentView(tabContentView, true);
 482 this.tabBrowser.addTabForContentView(tabContentView, {doNotAnimate: true});
482483 }
483484
484485 this._restoreCookieForOpenTabs(WebInspector.StateRestorationType.Load);

@@WebInspector.contentLoaded = function()
518519// This function returns a lazily constructed instance of a class scoped to this WebInspector
519520// instance. In the unlikely event that we ever need to construct multiple WebInspector instances
520521// this allows us to scope objects within the WebInspector.
 522// Classes can prevent usage of this function via a static `disallowInstanceForClass` function that
 523// returns true. It is then their responsibility to ensure that the returned value is tracked.
521524// Currently it is only used for sidebars.
522525WebInspector.instanceForClass = function(constructor)
523526{
524527 console.assert(typeof constructor === "function");
 528 if (typeof constructor.disallowInstanceForClass === "function" && constructor.disallowInstanceForClass())
 529 return new constructor;
525530
526531 let key = `__${constructor.name}`;
527532 if (!WebInspector[key])

@@WebInspector._tryToRestorePendingTabs = function()
616621 if (!tabContentView)
617622 continue;
618623
619  this.tabBrowser.addTabForContentView(tabContentView, true, index);
 624 this.tabBrowser.addTabForContentView(tabContentView, {
 625 doNotAnimate: true,
 626 insertionIndex: index,
 627 });
620628
621629 tabContentView.restoreStateFromCookie(WebInspector.StateRestorationType.Load);
622630 }

@@WebInspector.showNewTabTab = function(shouldAnimate)
634642 let tabContentView = this.tabBrowser.bestTabContentViewForClass(WebInspector.NewTabContentView);
635643 if (!tabContentView)
636644 tabContentView = new WebInspector.NewTabContentView;
637  this.tabBrowser.showTabForContentView(tabContentView, !shouldAnimate);
 645 this.tabBrowser.showTabForContentView(tabContentView, {doNotAnimate: !shouldAnimate});
638646};
639647
640648WebInspector.isNewTabWithTypeAllowed = function(tabType)

@@WebInspector.createNewTabWithType = function(tabType, options = {})
671679 console.assert(!shouldReplaceTab || referencedView, "Must provide a reference view to replace a tab.");
672680
673681 let tabContentView = this._createTabContentViewForType(tabType);
674  const suppressAnimations = true;
675  let insertionIndex = referencedView ? this.tabBar.tabBarItems.indexOf(referencedView.tabBarItem) : undefined;
676  this.tabBrowser.addTabForContentView(tabContentView, suppressAnimations, insertionIndex);
 682 const doNotAnimate = true;
 683 this.tabBrowser.addTabForContentView(tabContentView, {
 684 doNotAnimate,
 685 insertionIndex: referencedView ? this.tabBar.tabBarItems.indexOf(referencedView.tabBarItem) : undefined,
 686 });
677687
678688 if (shouldReplaceTab)
679  this.tabBrowser.closeTabForContentView(referencedView, suppressAnimations);
 689 this.tabBrowser.closeTabForContentView(referencedView, {doNotAnimate});
680690
681691 if (shouldShowNewTab)
682692 this.tabBrowser.showTabForContentView(tabContentView);

@@WebInspector.saveDataToFile = function(saveData, forceSaveAs)
914924 });
915925};
916926
 927WebInspector.loadDataFromFile = function(callback)
 928{
 929 let inputElement = document.createElement("input");
 930 inputElement.type = "file";
 931 inputElement.addEventListener("change", (event) => {
 932 if (!inputElement.files.length)
 933 return;
 934
 935 let reader = new FileReader;
 936 reader.addEventListener("loadend", (event) => {
 937 callback(reader.result);
 938 });
 939 reader.readAsText(inputElement.files[0]);
 940 });
 941 inputElement.click();
 942};
 943
917944WebInspector.isConsoleFocused = function()
918945{
919946 return this.quickConsole.prompt.focused;

@@WebInspector.tabContentViewClassForRepresentedObject = function(representedObjec
11461173 representedObject instanceof WebInspector.IndexedDatabaseObjectStoreIndex)
11471174 return WebInspector.ResourcesTabContentView;
11481175
1149  if (representedObject instanceof WebInspector.Collection)
1150  return WebInspector.CollectionContentView;
 1176 if (representedObject instanceof WebInspector.Recording)
 1177 return WebInspector.RecordingTabContentView;
11511178
11521179 return null;
11531180};

@@WebInspector.showRepresentedObject = function(representedObject, cookie, options
11781205 if (!tabContentView)
11791206 return;
11801207
1181  this.tabBrowser.showTabForContentView(tabContentView);
 1208 this.tabBrowser.showTabForContentView(tabContentView, options);
11821209 tabContentView.showRepresentedObject(representedObject, cookie);
11831210};
11841211

Source/WebInspectorUI/UserInterface/Base/Utilities.js

@@function insertObjectIntoSortedArray(object, array, comparator)
14861486 array.splice(insertionIndexForObjectInListSortedByFunction(object, array, comparator), 0, object);
14871487}
14881488
 1489function numericStringComparator(a, b)
 1490{
 1491 return a.localeCompare(b, undefined, {numeric: true});
 1492}
 1493
14891494function decodeBase64ToBlob(base64Data, mimeType)
14901495{
14911496 mimeType = mimeType || '';

Source/WebInspectorUI/UserInterface/Controllers/CanvasManager.js

@@WebInspector.CanvasManager = class CanvasManager extends WebInspector.Object
3535
3636 if (window.CanvasAgent)
3737 CanvasAgent.enable();
 38
 39 this._revealNextRecording = false;
3840 }
3941
4042 // Public

@@WebInspector.CanvasManager = class CanvasManager extends WebInspector.Object
4446 return [...this._canvasIdentifierMap.values()];
4547 }
4648
 49 set revealNextRecording(flag) { this._revealNextRecording = !!flag; }
 50
4751 canvasAdded(canvasPayload)
4852 {
4953 // Called from WebInspector.CanvasObserver.

@@WebInspector.CanvasManager = class CanvasManager extends WebInspector.Object
8690 this.dispatchEventToListeners(WebInspector.CanvasManager.Event.CanvasMemoryChanged, {canvas});
8791 }
8892
 93 recordingFinished(canvasIdentifier, initialState, actions)
 94 {
 95 // Called from WebInspector.CanvasObserver.
 96
 97 let canvas = this._canvasIdentifierMap.get(canvasIdentifier);
 98 console.assert(canvas);
 99 if (!canvas)
 100 return;
 101
 102 this.dispatchEventToListeners(WebInspector.CanvasManager.Event.RecordingFinished, {canvas});
 103
 104 let recording = WebInspector.Recording.fromPayload({
 105 type: WebInspector.Recording.Type.Canvas2D,
 106 initialState,
 107 actions,
 108 });
 109 WebInspector.showRepresentedObject(recording, null, {skipReveal: !this._revealNextRecording});
 110
 111 this._revealNextRecording = false;
 112 }
 113
89114 // Private
90115
91116 _mainResourceDidChange(event)

@@WebInspector.CanvasManager.Event = {
108133 CanvasWasAdded: "canvas-manager-canvas-was-added",
109134 CanvasWasRemoved: "canvas-manager-canvas-was-removed",
110135 CanvasMemoryChanged: "canvas-manager-canvas-memory-changed",
 136 RecordingFinished: "canvas-managger-recording-finished",
111137};

Source/WebInspectorUI/UserInterface/Images/Recording.svg

 1<?xml version="1.0" encoding="utf-8"?>
 2<!-- Copyright © 2017 Apple Inc. All rights reserved. -->
 3<svg xmlns="http://www.w3.org/2000/svg" id="root" version="1.1" viewBox="0 0 16 16">
 4 <path fill="currentColor" d="M 13 1 L 3 1 C 1.898438 1 1 1.898438 1 3 L 1 13 C 1 14.101562 1.898438 15 3 15 L 13 15 C 14.101562 15 15 14.101562 15 13 L 15 3 C 15 1.898438 14.101562 1 13 1 M 13 2 C 13.550781 2 14 2.449219 14 3 L 14 13 C 14 13.550781 13.550781 14 13 14 L 3 14 C 2.449219 14 2 13.550781 2 13 L 2 3 C 2 2.449219 2.449219 2 3 2 L 13 2"/>
 5 <rect fill="currentColor" x="4.25" y="4.5" width="7.5" height="1"/>
 6 <rect fill="currentColor" x="4.25" y="6.5" width="7.5" height="1"/>
 7 <rect fill="currentColor" x="4.25" y="8.5" width="7.5" height="1"/>
 8 <rect fill="currentColor" x="4.25" y="10.5" width="7.5" height="1"/>
 9</svg>

Source/WebInspectorUI/UserInterface/Main.html

138138 <link rel="stylesheet" href="Views/ProfileView.css">
139139 <link rel="stylesheet" href="Views/QuickConsole.css">
140140 <link rel="stylesheet" href="Views/RadioButtonNavigationItem.css">
 141 <link rel="stylesheet" href="Views/RecordingContentView.css">
 142 <link rel="stylesheet" href="Views/RecordingDetailsSidebarPanel.css">
 143 <link rel="stylesheet" href="Views/RecordingNavigationSidebarPanel.css">
141144 <link rel="stylesheet" href="Views/RenderingFrameTimelineOverviewGraph.css">
142145 <link rel="stylesheet" href="Views/RenderingFrameTimelineView.css">
143146 <link rel="stylesheet" href="Views/ReplayDashboardView.css">

160163 <link rel="stylesheet" href="Views/Sidebar.css">
161164 <link rel="stylesheet" href="Views/SidebarPanel.css">
162165 <link rel="stylesheet" href="Views/Slider.css">
 166 <link rel="stylesheet" href="Views/ScrubberNavigationItem.css">
163167 <link rel="stylesheet" href="Views/SoftContextMenu.css">
164168 <link rel="stylesheet" href="Views/SourceCodeTextEditor.css">
165169 <link rel="stylesheet" href="Views/SpringEditor.css">

296300 <script src="Models/BreakpointAction.js"></script>
297301 <script src="Models/ConsoleMessage.js"></script>
298302 <script src="Models/Instrument.js"></script>
 303 <script src="Models/Recording.js"></script>
 304 <script src="Models/RecordingAction.js"></script>
 305 <script src="Models/RecordingInitialStateAction.js"></script>
299306 <script src="Models/SourceCode.js"></script>
300307 <script src="Models/SourceCodeLocation.js"></script>
301308 <script src="Models/Timeline.js"></script>

475482 <script src="Views/ConsoleTabContentView.js"></script>
476483 <script src="Views/DebuggerTabContentView.js"></script>
477484 <script src="Views/ElementsTabContentView.js"></script>
 485 <script src="Views/RecordingTabContentView.js"></script>
478486 <script src="Views/ResourceTreeElement.js"></script>
479487 <script src="Views/ResourcesTabContentView.js"></script>
480488 <script src="Views/SearchTabContentView.js"></script>

642650 <script src="Views/QuickConsole.js"></script>
643651 <script src="Views/QuickConsoleNavigationBar.js"></script>
644652 <script src="Views/RadioButtonNavigationItem.js"></script>
 653 <script src="Views/RecordingContentView.js"></script>
 654 <script src="Views/RecordingDetailsSidebarPanel.js"></script>
 655 <script src="Views/RecordingNavigationSidebarPanel.js"></script>
645656 <script src="Views/RenderingFrameTimelineDataGridNode.js"></script>
646657 <script src="Views/RenderingFrameTimelineOverviewGraph.js"></script>
647658 <script src="Views/RenderingFrameTimelineView.js"></script>

670681 <script src="Views/SearchSidebarPanel.js"></script>
671682 <script src="Views/Sidebar.js"></script>
672683 <script src="Views/Slider.js"></script>
 684 <script src="Views/ScrubberNavigationItem.js"></script>
673685 <script src="Views/SoftContextMenu.js"></script>
674686 <script src="Views/SourceCodeTextEditor.js"></script>
675687 <script src="Views/SourceCodeTimelineTimelineDataGridNode.js"></script>

Source/WebInspectorUI/UserInterface/Models/Canvas.js

@@WebInspector.Canvas = class Canvas extends WebInspector.Object
171171 });
172172 }
173173
 174 toggleRecording(flag, callback)
 175 {
 176 CanvasAgent.toggleRecording(this._identifier, flag, (error) => {
 177 callback(error);
 178 });
 179 }
 180
174181 saveIdentityToCookie(cookie)
175182 {
176183 cookie[WebInspector.Canvas.FrameURLCookieKey] = this._frame.url.hash;

Source/WebInspectorUI/UserInterface/Models/NativeFunctionParameters.js

@@WebInspector.NativeConstructorFunctionParameters = {
179179 time: "name = \"default\"",
180180 timeEnd: "name = \"default\"",
181181 timeStamp: "[label]",
 182 record: "object",
 183 recordEnd: "object",
182184 trace: "message, [...values]",
183185 warn: "message, [...values]",
184186 __proto__: null,

Source/WebInspectorUI/UserInterface/Models/Recording.js

 1/*
 2 * Copyright (C) 2017 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26WebInspector.Recording = class Recording extends WebInspector.Object
 27{
 28 constructor(type, initialState, actions)
 29 {
 30 super();
 31
 32 console.assert(typeof initialState === "object");
 33 console.assert(Array.isArray(actions));
 34
 35 this._type = String(type);
 36 this._initialState = typeof initialState === "object" ? initialState : {};
 37 this._actions = Array.isArray(actions) ? actions : [];
 38
 39 this._actions.unshift(new WebInspector.RecordingInitialStateAction(WebInspector.UIString("Initial State")));
 40 }
 41
 42 // Static
 43
 44 static fromPayload(payload)
 45 {
 46 let initialState = {
 47 attributes: payload.initialState.attributes || {},
 48 functions: payload.initialState.functions || {},
 49 content: payload.initialState.content || "",
 50 };
 51
 52 let actions = payload.actions.map((actionPayload) => {
 53 let action = WebInspector.RecordingAction.fromPayload(actionPayload);
 54
 55 if (payload.type === WebInspector.Recording.Type.Canvas2D) {
 56 if (!(action.name in CanvasRenderingContext2D.prototype) && action.name !== "width" && action.name !== "height") {
 57 action.valid = false;
 58
 59 WebInspector.Recording.synthesizeError(WebInspector.UIString("“%s” is invalid").format(action.name));
 60 }
 61 }
 62
 63 return action;
 64 });
 65
 66 return new WebInspector.Recording(payload.type, initialState, actions);
 67 }
 68
 69 static synthesizeError(message)
 70 {
 71 const target = WebInspector.mainTarget;
 72 const source = WebInspector.ConsoleMessage.MessageSource.Other;
 73 const level = WebInspector.ConsoleMessage.MessageLevel.Error;
 74 let consoleMessage = new WebInspector.ConsoleMessage(target, source, level, WebInspector.UIString("Recording error: %s").format(message));
 75 consoleMessage.shouldRevealConsole = true; // TODO
 76
 77 WebInspector.consoleLogViewController.appendConsoleMessage(consoleMessage);
 78 }
 79
 80 // Public
 81
 82 get type() { return this._type; }
 83 get initialState() { return this._initialState; }
 84 get actions() { return this._actions; }
 85
 86 toJSON()
 87 {
 88 let initialState = {};
 89 if (!isEmptyObject(this._initialState.attributes))
 90 initialState.attributes = this._initialState.attributes;
 91 if (!isEmptyObject(this._initialState.functions))
 92 initialState.functions = this._initialState.functions;
 93 if (this._initialState.content && this._initialState.content.length)
 94 initialState.content = this._initialState.content;
 95
 96 return {
 97 version: WebInspector.Recording.Version,
 98 type: this._type,
 99 initialState,
 100 actions: this._actions.slice(1).map((action) => action.toJSON()),
 101 };
 102 }
 103};
 104
 105WebInspector.Recording.Type = {
 106 Canvas2D: "canvas-2d",
 107};
 108
 109WebInspector.Recording.Version = 1;

Source/WebInspectorUI/UserInterface/Models/RecordingAction.js

 1/*
 2 * Copyright (C) 2017 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26WebInspector.RecordingAction = class RecordingAction extends WebInspector.Object
 27{
 28 constructor(name, parameters)
 29 {
 30 super();
 31
 32 console.assert(typeof name === "string");
 33
 34 this._name = String(name);
 35 this._parameters = Array.isArray(parameters) ? parameters : [];
 36
 37 this._valid = true;
 38 }
 39
 40 // Static
 41
 42 static fromPayload(payload)
 43 {
 44 return new WebInspector.RecordingAction(payload.name, payload.parameters);
 45 }
 46
 47 // Public
 48
 49 get name() { return this._name; }
 50 get parameters() { return this._parameters; }
 51
 52 get valid() { return this._valid; }
 53 set valid(valid) { this._valid = !!valid; }
 54
 55 unavailableParameterReplacementForType(type, parameterIndex)
 56 {
 57 let forType = WebInspector.RecordingAction._unavailableParameterReplacements[type];
 58 if (!forType)
 59 return null;
 60
 61 let forFunction = forType[this._name];
 62 if (!forFunction)
 63 return null;
 64
 65 let forArgumentsLength = forFunction[this._parameters.length];
 66 if (!forArgumentsLength)
 67 return null;
 68
 69 return forArgumentsLength[parameterIndex] || null;
 70 }
 71
 72 attributeForType(type)
 73 {
 74 let forType = WebInspector.RecordingAction._attributeNames[type];
 75 if (!forType)
 76 return false;
 77
 78 return forType.includes(this._name);
 79 }
 80
 81 visualForType(type)
 82 {
 83 let forType = WebInspector.RecordingAction._visualNames[type];
 84 if (!forType)
 85 return false;
 86
 87 return forType.includes(this._name);
 88 }
 89
 90 toJSON()
 91 {
 92 let json = {name: this._name};
 93 if (this._parameters.length)
 94 json.parameters = this._parameters;
 95 return json;
 96 }
 97};
 98
 99WebInspector.RecordingAction._replacementData = {
 100 CanvasStyle: {
 101 name(data) {
 102 if (typeof data === "string")
 103 return data;
 104 if (data.type === "pattern")
 105 return "CanvasPattern";
 106 if (data.type === "linear-gradient" || data.type === "radial-gradient")
 107 return "CanvasGradient";
 108 return "";
 109 },
 110 callback(data, context) {
 111 if (typeof data === "string")
 112 return data;
 113
 114 if (data.type === "pattern") {
 115 let image = new Image;
 116 image.src = data.image;
 117 return context.createPattern(image, data.repeat);
 118 }
 119
 120 if (data.type === "linear-gradient" || data.type === "radial-gradient") {
 121 let gradient = data.type === "radial-gradient" ? context.createRadialGradient(...data.parameters) : context.createLinearGradient(...data.parameters);
 122 if (Array.isArray(data.stops)) {
 123 for (let stop of data.stops)
 124 gradient.addColorStop(...stop);
 125 }
 126 return gradient;
 127 }
 128
 129 return null;
 130 },
 131 },
 132 Element: {
 133 name(data) { return "Element"; },
 134 },
 135 Image: {
 136 name(data) { return "Image"; },
 137 callback(data, context) {
 138 let image = new Image;
 139 image.src = data;
 140 return image;
 141 },
 142 },
 143 ImageData: {
 144 name(data) { return "ImageData"; },
 145 callback(data, context) { return new ImageData(new Uint8ClampedArray(data.data), data.width, data.height); },
 146 },
 147 Path2D: {
 148 name(data) { return "Path2D"; },
 149 callback(data, context) { return new Path2D(data); },
 150 },
 151};
 152
 153WebInspector.RecordingAction._unavailableParameterReplacements = {
 154 [WebInspector.Recording.Type.Canvas2D]: {
 155 "clip": {
 156 2: {0: WebInspector.RecordingAction._replacementData.Path2D},
 157 },
 158 "createImageData": {
 159 1: {0: WebInspector.RecordingAction._replacementData.ImageData},
 160 },
 161 "createPattern": {
 162 2: {0: WebInspector.RecordingAction._replacementData.Image},
 163 },
 164 "drawImage": {
 165 3: {0: WebInspector.RecordingAction._replacementData.Image},
 166 5: {0: WebInspector.RecordingAction._replacementData.Image},
 167 9: {0: WebInspector.RecordingAction._replacementData.Image},
 168 },
 169 "drawImageFromRect": {
 170 10: {0: WebInspector.RecordingAction._replacementData.Image},
 171 },
 172 "drawFocusIfNeeded": {
 173 1: {0: WebInspector.RecordingAction._replacementData.Element},
 174 2: {0: WebInspector.RecordingAction._replacementData.Path2D, 1: WebInspector.RecordingAction._replacementData.Element},
 175 },
 176 "fill": {
 177 2: {0: WebInspector.RecordingAction._replacementData.Path2D},
 178 },
 179 "fillStyle": {
 180 1: {0: WebInspector.RecordingAction._replacementData.CanvasStyle},
 181 },
 182 "isPointInPath": {
 183 4: {0: WebInspector.RecordingAction._replacementData.Path2D},
 184 },
 185 "isPointInStroke": {
 186 3: {0: WebInspector.RecordingAction._replacementData.Path2D},
 187 },
 188 "putImageData": {
 189 3: {0: WebInspector.RecordingAction._replacementData.ImageData},
 190 7: {0: WebInspector.RecordingAction._replacementData.ImageData},
 191 },
 192 "stroke": {
 193 1: {0: WebInspector.RecordingAction._replacementData.Path2D},
 194 },
 195 "strokeStyle": {
 196 1: {0: WebInspector.RecordingAction._replacementData.CanvasStyle},
 197 },
 198 "webkitPutImageData": {
 199 3: {0: WebInspector.RecordingAction._replacementData.ImageData},
 200 7: {0: WebInspector.RecordingAction._replacementData.ImageData},
 201 },
 202 },
 203};
 204
 205WebInspector.RecordingAction._attributeNames = {
 206 [WebInspector.Recording.Type.Canvas2D]: [
 207 "direction",
 208 "fillStyle",
 209 "font",
 210 "globalAlpha",
 211 "globalCompositeOperation",
 212 "height",
 213 "imageSmoothingEnabled",
 214 "imageSmoothingQuality",
 215 "lineCap",
 216 "lineDashOffset",
 217 "lineJoin",
 218 "lineWidth",
 219 "miterLimit",
 220 "shadowBlur",
 221 "shadowColor",
 222 "shadowOffsetX",
 223 "shadowOffsetY",
 224 "strokeStyle",
 225 "textAlign",
 226 "textBaseline",
 227 "webkitImageSmoothingEnabled",
 228 "webkitLineDash",
 229 "webkitLineDashOffset",
 230 "width",
 231 ],
 232};
 233
 234WebInspector.RecordingAction._visualNames = {
 235 [WebInspector.Recording.Type.Canvas2D]: [
 236 "clearRect",
 237 "drawFocusIfNeeded",
 238 "drawImage",
 239 "drawImageFromRect",
 240 "fill",
 241 "fillRect",
 242 "fillText",
 243 "height",
 244 "putImageData",
 245 "stroke",
 246 "strokeRect",
 247 "strokeText",
 248 "webkitPutImageDataHD",
 249 "width",
 250 ],
 251};

Source/WebInspectorUI/UserInterface/Models/RecordingInitialStateAction.js

 1/*
 2 * Copyright (C) 2017 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26WebInspector.RecordingInitialStateAction = class RecordingInitialStateAction extends WebInspector.RecordingAction
 27{
 28 constructor(name)
 29 {
 30 const parameters = [];
 31 const properties = {"initial-state": true};
 32 super(name, parameters, properties);
 33
 34 this.valid = false;
 35 }
 36};

Source/WebInspectorUI/UserInterface/Protocol/CanvasObserver.js

@@WebInspector.CanvasObserver = class CanvasObserver
4141 {
4242 WebInspector.canvasManager.canvasMemoryChanged(canvasId, memoryCost);
4343 }
 44
 45 recordingFinished(canvasId, initialState, actions)
 46 {
 47 WebInspector.canvasManager.recordingFinished(canvasId, initialState, actions);
 48 }
4449};

Source/WebInspectorUI/UserInterface/Views/ApplicationCacheDetailsSidebarPanel.js

@@WebInspector.ApplicationCacheDetailsSidebarPanel = class ApplicationCacheDetails
2727{
2828 constructor()
2929 {
30  super("application-cache-details", WebInspector.UIString("Storage"), WebInspector.UIString("Storage"));
 30 super("application-cache-details", WebInspector.UIString("Storage"));
3131
3232 this.element.classList.add("application-cache");
3333

Source/WebInspectorUI/UserInterface/Views/ApplicationCacheFrameTreeElement.js

@@WebInspector.ApplicationCacheFrameTreeElement = class ApplicationCacheFrameTreeE
2929 {
3030 console.assert(representedObject instanceof WebInspector.ApplicationCacheFrame);
3131
32  super("application-cache-frame", "", "", representedObject, false);
 32 super("application-cache-frame", "", "", representedObject);
3333
3434 this.updateTitles();
3535 }

Source/WebInspectorUI/UserInterface/Views/BreakpointTreeElement.js

@@WebInspector.BreakpointTreeElement = class BreakpointTreeElement extends WebInsp
3232 if (!className)
3333 className = WebInspector.BreakpointTreeElement.GenericLineIconStyleClassName;
3434
35  super(["breakpoint", className], title, null, breakpoint, false);
 35 super(["breakpoint", className], title, null, breakpoint);
3636
3737 this._breakpoint = breakpoint;
3838 this._probeSet = null;

Source/WebInspectorUI/UserInterface/Views/CSSStyleDetailsSidebarPanel.js

@@WebInspector.CSSStyleDetailsSidebarPanel = class CSSStyleDetailsSidebarPanel ext
2727{
2828 constructor()
2929 {
30  super("css-style", WebInspector.UIString("Styles"), WebInspector.UIString("Style"), null, true);
 30 const dontCreateNavigationItem = true;
 31 super("css-style", WebInspector.UIString("Styles"), dontCreateNavigationItem);
3132
3233 this._selectedPanel = null;
3334 this._computedStyleDetailsPanel = new WebInspector.ComputedStyleDetailsPanel(this);

Source/WebInspectorUI/UserInterface/Views/CSSStyleSheetTreeElement.js

@@WebInspector.CSSStyleSheetTreeElement = class CSSStyleSheetTreeElement extends W
3333 const classNames = ["stylesheet", "stylesheet-icon"];
3434 const title = WebInspector.UIString("Inspector Style Sheet");
3535 const subtitle = null;
36  const hasChildren = false;
37  super(styleSheet, classNames, title, subtitle, styleSheet, hasChildren);
 36 super(styleSheet, classNames, title, subtitle, styleSheet);
3837 }
3938};

Source/WebInspectorUI/UserInterface/Views/CallFrameTreeElement.js

@@WebInspector.CallFrameTreeElement = class CallFrameTreeElement extends WebInspec
3232 let className = WebInspector.CallFrameView.iconClassNameForCallFrame(callFrame);
3333 let title = callFrame.functionName || WebInspector.UIString("(anonymous function)");
3434
35  super(["call-frame", className], title, null, callFrame, false);
 35 super(["call-frame", className], title, null, callFrame);
3636
3737 this._callFrame = callFrame;
3838 this._isActiveCallFrame = false;

Source/WebInspectorUI/UserInterface/Views/CanvasContentView.js

@@WebInspector.CanvasContentView = class CanvasContentView extends WebInspector.Co
3737 this._previewImageElement = null;
3838 this._errorElement = null;
3939
 40 if (representedObject.contextType === WebInspector.Canvas.ContextType.Canvas2D) {
 41 const modifiers = null;
 42 this._toggleRequestRecordingShortcut = new WebInspector.KeyboardShortcut(modifiers, WebInspector.KeyboardShortcut.Key.Space, this._toggleRecording.bind(this));
 43 this._toggleRequestRecordingShortcut.implicitlyPreventsDefault = false;
 44 this._toggleRequestRecordingShortcut.disabled = true;
 45
 46 let toolTip = WebInspector.UIString("Request recording of next active draw frame (%s)").format(this._toggleRequestRecordingShortcut.displayName);
 47 let altToolTip = WebInspector.UIString("Cancel recording of next active draw frame (%s)").format(this._toggleRequestRecordingShortcut.displayName);
 48 this._recordButtonNavigationItem = new WebInspector.ToggleButtonNavigationItem("canvas-record", toolTip, altToolTip, "Images/Record.svg", "Images/Stop.svg", 13, 13);
 49 this._recordButtonNavigationItem.addEventListener(WebInspector.ButtonNavigationItem.Event.Clicked, this._toggleRecording, this);
 50 }
 51
4052 this._refreshButtonNavigationItem = new WebInspector.ButtonNavigationItem("canvas-refresh", WebInspector.UIString("Refresh"), "Images/ReloadFull.svg", 13, 13);
4153 this._refreshButtonNavigationItem.addEventListener(WebInspector.ButtonNavigationItem.Event.Clicked, this._showPreview, this);
4254

@@WebInspector.CanvasContentView = class CanvasContentView extends WebInspector.Co
4961
5062 get navigationItems()
5163 {
52  return [this._refreshButtonNavigationItem, this._showGridButtonNavigationItem];
 64 let navigationItems = [this._refreshButtonNavigationItem, this._showGridButtonNavigationItem];
 65 if (this._recordButtonNavigationItem)
 66 navigationItems.unshift(this._recordButtonNavigationItem);
 67 return navigationItems;
 68 }
 69
 70 initialLayout()
 71 {
 72 super.initialLayout();
 73
 74 WebInspector.canvasManager.addEventListener(WebInspector.CanvasManager.Event.RecordingFinished, this._recordingFinished, this);
5375 }
5476
5577 shown()

@@WebInspector.CanvasContentView = class CanvasContentView extends WebInspector.Co
6890 super.hidden();
6991 }
7092
 93 closed()
 94 {
 95 WebInspector.canvasManager.removeEventListener(null, null, this);
 96
 97 super.closed();
 98 }
 99
71100 // Private
72101
 102 _toggleRecording(event)
 103 {
 104 let toggled = this._recordButtonNavigationItem.toggled;
 105 this.representedObject.toggleRecording(!toggled, (error) => {
 106 if (error)
 107 return;
 108
 109 this._recordButtonNavigationItem.toggled = !toggled;
 110 WebInspector.canvasManager.revealNextRecording = !toggled;
 111 });
 112 }
 113
 114 _recordingFinished(event)
 115 {
 116 if (event.data.canvas !== this.representedObject)
 117 return;
 118
 119 if (this._recordButtonNavigationItem)
 120 this._recordButtonNavigationItem.toggled = false;
 121 }
 122
73123 _showPreview()
74124 {
75125 let showError = () => {

Source/WebInspectorUI/UserInterface/Views/ContentBrowser.js

2525
2626WebInspector.ContentBrowser = class ContentBrowser extends WebInspector.View
2727{
28  constructor(element, delegate, disableBackForward, disableFindBanner)
 28 constructor(element, delegate, disableBackForward, disableFindBanner, flexibleNavigationItem)
2929 {
3030 super(element);
3131

@@WebInspector.ContentBrowser = class ContentBrowser extends WebInspector.View
7979
8080 this._contentViewSelectionPathNavigationItem = new WebInspector.HierarchicalPathNavigationItem;
8181
82  this._dividingFlexibleSpaceNavigationItem = new WebInspector.FlexibleSpaceNavigationItem;
83  this._navigationBar.addNavigationItem(this._dividingFlexibleSpaceNavigationItem);
 82 this._flexibleNavigationItem = flexibleNavigationItem || new WebInspector.FlexibleSpaceNavigationItem;
 83 this._navigationBar.addNavigationItem(this._flexibleNavigationItem);
8484
8585 WebInspector.ContentView.addEventListener(WebInspector.ContentView.Event.SelectionPathComponentsDidChange, this._contentViewSelectionPathComponentDidChange, this);
8686 WebInspector.ContentView.addEventListener(WebInspector.ContentView.Event.SupplementalRepresentedObjectsDidChange, this._contentViewSupplementalRepresentedObjectsDidChange, this);

@@WebInspector.ContentBrowser = class ContentBrowser extends WebInspector.View
392392 this._removeAllNavigationItems();
393393
394394 let navigationBar = this.navigationBar;
395  let insertionIndex = navigationBar.navigationItems.indexOf(this._dividingFlexibleSpaceNavigationItem) + 1;
 395 let insertionIndex = navigationBar.navigationItems.indexOf(this._flexibleNavigationItem) + 1;
396396 console.assert(insertionIndex >= 0);
397397
398398 // Keep track of items we'll be adding to the navigation bar.

Source/WebInspectorUI/UserInterface/Views/ContentBrowserTabContentView.js

2525
2626WebInspector.ContentBrowserTabContentView = class ContentBrowserTabContentView extends WebInspector.TabContentView
2727{
28  constructor(identifier, styleClassNames, tabBarItem, navigationSidebarPanelConstructor, detailsSidebarPanelConstructors, disableBackForward)
 28 constructor(identifier, styleClassNames, tabBarItem, navigationSidebarPanelConstructor, detailsSidebarPanelConstructors, disableBackForward, flexibleNavigationItem)
2929 {
3030 if (typeof styleClassNames === "string")
3131 styleClassNames = [styleClassNames];
3232
3333 styleClassNames.push("content-browser");
3434
35  var contentBrowser = new WebInspector.ContentBrowser(null, null, disableBackForward);
 35 var contentBrowser = new WebInspector.ContentBrowser(null, null, disableBackForward, false, flexibleNavigationItem);
3636
3737 super(identifier, styleClassNames, tabBarItem, navigationSidebarPanelConstructor, detailsSidebarPanelConstructors);
3838

Source/WebInspectorUI/UserInterface/Views/ContentFlowTreeElement.js

@@WebInspector.ContentFlowTreeElement = class ContentFlowTreeElement extends WebIn
3434 {
3535 console.assert(representedObject instanceof WebInspector.ContentFlow);
3636
37  super("content-flow-icon", representedObject.name, null, representedObject, false);
 37 super("content-flow-icon", representedObject.name, null, representedObject);
3838 }
3939};

Source/WebInspectorUI/UserInterface/Views/ContentView.js

@@WebInspector.ContentView = class ContentView extends WebInspector.View
158158 if (representedObject instanceof WebInspector.HeapSnapshotProxy || representedObject instanceof WebInspector.HeapSnapshotDiffProxy)
159159 return new WebInspector.HeapSnapshotClusterContentView(representedObject, extraArguments);
160160
 161 if (representedObject instanceof WebInspector.Recording)
 162 return new WebInspector.RecordingContentView(representedObject, extraArguments);
 163
161164 if (representedObject instanceof WebInspector.Collection)
162165 return new WebInspector.CollectionContentView(representedObject, extraArguments);
163166

@@WebInspector.ContentView = class ContentView extends WebInspector.View
280283 return true;
281284 if (representedObject instanceof WebInspector.HeapSnapshotProxy || representedObject instanceof WebInspector.HeapSnapshotDiffProxy)
282285 return true;
 286 if (representedObject instanceof WebInspector.Recording)
 287 return true;
283288 if (representedObject instanceof WebInspector.Collection)
284289 return true;
285290 if (typeof representedObject === "string" || representedObject instanceof String)

Source/WebInspectorUI/UserInterface/Views/DOMDetailsSidebarPanel.js

2525
2626WebInspector.DOMDetailsSidebarPanel = class DOMDetailsSidebarPanel extends WebInspector.DetailsSidebarPanel
2727{
28  constructor(identifier, displayName, singularDisplayName, element, dontCreateNavigationItem)
 28 constructor(identifier, displayName, dontCreateNavigationItem)
2929 {
30  super(identifier, displayName, singularDisplayName, element, dontCreateNavigationItem);
 30 super(identifier, displayName, dontCreateNavigationItem);
3131
3232 this.element.addEventListener("click", this._mouseWasClicked.bind(this), true);
3333

Source/WebInspectorUI/UserInterface/Views/DOMNodeDetailsSidebarPanel.js

@@WebInspector.DOMNodeDetailsSidebarPanel = class DOMNodeDetailsSidebarPanel exten
2727{
2828 constructor()
2929 {
30  super("dom-node-details", WebInspector.UIString("Node"), WebInspector.UIString("Node"));
 30 super("dom-node-details", WebInspector.UIString("Node"));
3131
3232 this._eventListenerGroupingMethodSetting = new WebInspector.Setting("dom-node-event-listener-grouping-method", WebInspector.DOMNodeDetailsSidebarPanel.EventListenerGroupingMethod.Event);
3333

Source/WebInspectorUI/UserInterface/Views/DOMNodeTreeElement.js

@@WebInspector.DOMNodeTreeElement = class DOMNodeTreeElement extends WebInspector.
2929 {
3030 console.assert(domNode instanceof WebInspector.DOMNode);
3131
32  super("dom-node", domNode.displayName, null, domNode, true);
 32 super("dom-node", domNode.displayName, null, domNode, {hasChildren: true});
3333
3434 this.status = WebInspector.linkifyNodeReferenceElement(domNode, WebInspector.createGoToArrowButton());
3535 }

Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.css

@@body[dir=rtl] .tree-outline.dom li.parent.shadow::after {
289289}
290290
291291@keyframes node-state-changed {
292  from { background-color: hsla(83, 100%, 48%, 0.4); }
 292 from { background-color: var(--value-changed-highlight); }
293293}
294294
295295.node-state-changed {

Source/WebInspectorUI/UserInterface/Views/DataGridNode.js

2525
2626WebInspector.DataGridNode = class DataGridNode extends WebInspector.Object
2727{
28  constructor(data, hasChildren)
 28 constructor(data, hasChildren, classNames)
2929 {
3030 super();
3131

@@WebInspector.DataGridNode = class DataGridNode extends WebInspector.Object
4242 this.previousSibling = null;
4343 this.nextSibling = null;
4444 this.disclosureToggleWidth = 10;
 45 this._classNames = classNames || [];
4546 }
4647
4748 get hidden()

@@WebInspector.DataGridNode = class DataGridNode extends WebInspector.Object
100101 this._element.classList.add("revealed");
101102 if (this._hidden)
102103 this._element.classList.add("hidden");
 104 this._element.classList.add(...this._classNames);
103105
104106 this.createCells();
105107 return this._element;

Source/WebInspectorUI/UserInterface/Views/DatabaseTableTreeElement.js

@@WebInspector.DatabaseTableTreeElement = class DatabaseTableTreeElement extends W
2929 {
3030 console.assert(representedObject instanceof WebInspector.DatabaseTableObject);
3131
32  super("database-table-icon", representedObject.name, null, representedObject, false);
 32 super("database-table-icon", representedObject.name, null, representedObject);
3333 }
3434};

Source/WebInspectorUI/UserInterface/Views/DatabaseTreeElement.js

@@WebInspector.DatabaseTreeElement = class DatabaseTreeElement extends WebInspecto
2929 {
3030 console.assert(representedObject instanceof WebInspector.DatabaseObject);
3131
32  super("database-icon", representedObject.name, null, representedObject, true);
 32 super("database-icon", representedObject.name, null, representedObject, {hasChildren: true});
3333
3434 this.hasChildren = false;
3535

Source/WebInspectorUI/UserInterface/Views/DetailsSidebarPanel.js

2525
2626WebInspector.DetailsSidebarPanel = class DetailsSidebarPanel extends WebInspector.SidebarPanel
2727{
28  constructor(identifier, displayName, singularDisplayName, element, dontCreateNavigationItem)
 28 constructor(identifier, displayName, dontCreateNavigationItem)
2929 {
30  super(identifier, displayName, element);
 30 super(identifier, displayName);
3131
3232 this.element.classList.add("details");
3333

Source/WebInspectorUI/UserInterface/Views/FolderTreeElement.js

@@WebInspector.FolderTreeElement = class FolderTreeElement extends WebInspector.Ge
3131
3232 const classNames = [WebInspector.FolderTreeElement.FolderIconStyleClassName];
3333 const subtitle = null;
34  const hasChildren = true;
35  super(classNames, title, subtitle, representedObject, hasChildren);
 34 super(classNames, title, subtitle, representedObject, {hasChildren: true});
3635 }
3736};
3837

Source/WebInspectorUI/UserInterface/Views/FolderizedTreeElement.js

2525
2626WebInspector.FolderizedTreeElement = class FolderizedTreeElement extends WebInspector.GeneralTreeElement
2727{
28  constructor(classNames, title, subtitle, representedObject, hasChildren)
 28 constructor(classNames, title, subtitle, representedObject)
2929 {
30  super(classNames, title, subtitle, representedObject, hasChildren);
 30 super(classNames, title, subtitle, representedObject);
3131
3232 this.shouldRefreshChildren = true;
3333

@@WebInspector.FolderizedTreeElement = class FolderizedTreeElement extends WebInsp
237237 return 1;
238238
239239 // Then sort by title.
240  return a.mainTitle.localeCompare(b.mainTitle, undefined, {numeric: true});
 240 return numericStringComparator(a.mainTitle, b.mainTitle);
241241 }
242242
243243 _insertFolderTreeElement(folderTreeElement)

Source/WebInspectorUI/UserInterface/Views/GeneralTreeElement.js

2525
2626WebInspector.GeneralTreeElement = class GeneralTreeElement extends WebInspector.TreeElement
2727{
28  constructor(classNames, title, subtitle, representedObject, hasChildren)
 28 constructor(classNames, title, subtitle, representedObject, options)
2929 {
30  super("", representedObject, hasChildren);
 30 super("", representedObject, options);
3131
3232 this.classNames = classNames;
3333

Source/WebInspectorUI/UserInterface/Views/IndexedDatabaseDetailsSidebarPanel.js

@@WebInspector.IndexedDatabaseDetailsSidebarPanel = class IndexedDatabaseDetailsSi
2727{
2828 constructor()
2929 {
30  super("indexed-database-details", WebInspector.UIString("Storage"), WebInspector.UIString("Storage"));
 30 super("indexed-database-details", WebInspector.UIString("Storage"));
3131
3232 this.element.classList.add("indexed-database");
3333

Source/WebInspectorUI/UserInterface/Views/IndexedDatabaseObjectStoreIndexTreeElement.js

@@WebInspector.IndexedDatabaseObjectStoreIndexTreeElement = class IndexedDatabaseO
2929 {
3030 console.assert(objectStoreIndex instanceof WebInspector.IndexedDatabaseObjectStoreIndex);
3131
32  super("database-table-icon", objectStoreIndex.name, null, objectStoreIndex, false);
 32 super("database-table-icon", objectStoreIndex.name, null, objectStoreIndex);
3333
3434 this._objectStoreIndex = objectStoreIndex;
3535 }

Source/WebInspectorUI/UserInterface/Views/IndexedDatabaseObjectStoreTreeElement.js

@@WebInspector.IndexedDatabaseObjectStoreTreeElement = class IndexedDatabaseObject
2929 {
3030 console.assert(objectStore instanceof WebInspector.IndexedDatabaseObjectStore);
3131
32  super("database-table-icon", objectStore.name, null, objectStore, !!objectStore.indexes.length);
 32 super("database-table-icon", objectStore.name, null, objectStore, {hasChildren: !!objectStore.indexes.length});
3333
3434 this._objectStore = objectStore;
3535 }

Source/WebInspectorUI/UserInterface/Views/IndexedDatabaseTreeElement.js

@@WebInspector.IndexedDatabaseTreeElement = class IndexedDatabaseTreeElement exten
2929 {
3030 console.assert(indexedDatabase instanceof WebInspector.IndexedDatabase);
3131
32  super("database-icon", indexedDatabase.name, null, indexedDatabase, !!indexedDatabase.objectStores.length);
 32 super("database-icon", indexedDatabase.name, null, indexedDatabase, {hasChildren: !!indexedDatabase.objectStores.length});
3333
3434 this._indexedDatabase = indexedDatabase;
3535 }

Source/WebInspectorUI/UserInterface/Views/IssueTreeElement.js

@@WebInspector.IssueTreeElement = class IssueTreeElement extends WebInspector.Gene
3737 break;
3838 }
3939
40  super([WebInspector.IssueTreeElement.StyleClassName, levelStyleClassName], null, null, issueMessage, false);
 40 super([WebInspector.IssueTreeElement.StyleClassName, levelStyleClassName], null, null, issueMessage);
4141
4242 this._issueMessage = issueMessage;
4343 this._updateTitles();

Source/WebInspectorUI/UserInterface/Views/LayerTreeDetailsSidebarPanel.js

@@WebInspector.LayerTreeDetailsSidebarPanel = class LayerTreeDetailsSidebarPanel e
2727{
2828 constructor()
2929 {
30  super("layer-tree", WebInspector.UIString("Layers"), WebInspector.UIString("Layer"));
 30 super("layer-tree", WebInspector.UIString("Layers"));
3131
3232 this._dataGridNodesByLayerId = new Map;
3333

Source/WebInspectorUI/UserInterface/Views/LogTreeElement.js

@@WebInspector.LogTreeElement = class LogTreeElement extends WebInspector.GeneralT
2929 {
3030 console.assert(representedObject instanceof WebInspector.LogObject);
3131
32  super("log-icon", WebInspector.UIString("Console"), representedObject.startDate.toLocaleTimeString(), representedObject, false);
 32 super("log-icon", WebInspector.UIString("Console"), representedObject.startDate.toLocaleTimeString(), representedObject);
3333
3434 this._logObject = representedObject;
3535 }

Source/WebInspectorUI/UserInterface/Views/Main.css

@@body[dir=rtl] .go-to-link:not(.dont-float) {
408408 }
409409}
410410
411 img.show-grid {
 411:matches(img, canvas).show-grid {
412412 background-image: linear-gradient(315deg, transparent 75%, hsl(0, 0%, 95%) 75%),
413413 linear-gradient(45deg, transparent 75%, hsl(0, 0%, 95%) 75%),
414414 linear-gradient(315deg, hsl(0, 0%, 95%) 25%, transparent 25%),

Source/WebInspectorUI/UserInterface/Views/NavigationBar.css

2626.navigation-bar {
2727 display: flex;
2828 justify-content: center;
 29 align-items: center;
2930 flex-wrap: wrap;
3031
3132 border-bottom: 1px solid var(--border-color);

Source/WebInspectorUI/UserInterface/Views/NavigationSidebarPanel.css

4848 border-bottom: 1px solid var(--border-color);
4949}
5050
51 .sidebar > .panel.navigation > .overflow-shadow.top {
52  top: calc(var(--navigation-bar-height) - 1px);
53  bottom: initial;
54 }
55 
5651.sidebar > .panel.navigation > .content .empty-content-placeholder {
5752 left: 0;
5853 right: 0;

Source/WebInspectorUI/UserInterface/Views/NavigationSidebarPanel.js

2525
2626WebInspector.NavigationSidebarPanel = class NavigationSidebarPanel extends WebInspector.SidebarPanel
2727{
28  constructor(identifier, displayName, shouldAutoPruneStaleTopLevelResourceTreeElements, wantsTopOverflowShadow, element, role, label)
 28 constructor(identifier, displayName, shouldAutoPruneStaleTopLevelResourceTreeElements)
2929 {
30  super(identifier, displayName, element, role, label || displayName);
 30 super(identifier, displayName);
3131
3232 this.element.classList.add("navigation");
3333

@@WebInspector.NavigationSidebarPanel = class NavigationSidebarPanel extends WebIn
4444 this._bottomOverflowShadowElement.className = WebInspector.NavigationSidebarPanel.OverflowShadowElementStyleClassName;
4545 this.element.appendChild(this._bottomOverflowShadowElement);
4646
47  if (wantsTopOverflowShadow) {
48  this._topOverflowShadowElement = document.createElement("div");
49  this._topOverflowShadowElement.classList.add(WebInspector.NavigationSidebarPanel.OverflowShadowElementStyleClassName);
50  this._topOverflowShadowElement.classList.add(WebInspector.NavigationSidebarPanel.TopOverflowShadowElementStyleClassName);
51  this.element.appendChild(this._topOverflowShadowElement);
52  }
53 
5447 this._boundUpdateContentOverflowShadowVisibility = this.soon._updateContentOverflowShadowVisibility;
5548 window.addEventListener("resize", this._boundUpdateContentOverflowShadowVisibility);
5649

@@WebInspector.NavigationSidebarPanel.SuppressFilteringSymbol = Symbol("suppress-f
760753WebInspector.NavigationSidebarPanel.WasExpandedDuringFilteringSymbol = Symbol("was-expanded-during-filtering");
761754
762755WebInspector.NavigationSidebarPanel.OverflowShadowElementStyleClassName = "overflow-shadow";
763 WebInspector.NavigationSidebarPanel.TopOverflowShadowElementStyleClassName = "top";
764756WebInspector.NavigationSidebarPanel.ContentTreeOutlineElementStyleClassName = "navigation-sidebar-panel-content-tree-outline";
765757WebInspector.NavigationSidebarPanel.EmptyContentPlaceholderElementStyleClassName = "empty-content-placeholder";
766758WebInspector.NavigationSidebarPanel.EmptyContentPlaceholderMessageElementStyleClassName = "message";

Source/WebInspectorUI/UserInterface/Views/NetworkSidebarPanel.css

9292}
9393
9494.sidebar > .panel.navigation.network.network-grid-content-view-showing > .content > .tree-outline {
95  background-image: linear-gradient(to bottom, transparent, transparent 50%, hsla(0, 0%, 0%, 0.03) 50%, hsla(0, 0%, 0%, 0.03));
96  background-size: 100% 40px;
 95 background: var(--transparent-stripe-background-gradient);
9796}
9897
9998.sidebar > .panel.navigation.network .tree-outline > .preserved:not(.selected) > :not(.status) {

Source/WebInspectorUI/UserInterface/Views/ObjectTreeBaseTreeElement.js

@@WebInspector.ObjectTreeBaseTreeElement = class ObjectTreeBaseTreeElement extends
3131 console.assert(propertyPath instanceof WebInspector.PropertyPath);
3232 console.assert(!property || property instanceof WebInspector.PropertyDescriptor);
3333
34  super(null, null, null, representedObject, false);
 34 super(null, null, null, representedObject);
3535
3636 this._property = property;
3737 this._propertyPath = propertyPath;

Source/WebInspectorUI/UserInterface/Views/ProbeDetailsSidebarPanel.js

@@WebInspector.ProbeDetailsSidebarPanel = class ProbeDetailsSidebarPanel extends W
2828{
2929 constructor()
3030 {
31  super("probe", WebInspector.UIString("Probes"), WebInspector.UIString("Probes"));
 31 super("probe", WebInspector.UIString("Probes"));
3232
3333 this._probeSetSections = new Map;
3434 this._inspectedProbeSets = [];

Source/WebInspectorUI/UserInterface/Views/ProfileNodeTreeElement.js

@@WebInspector.ProfileNodeTreeElement = class ProfileNodeTreeElement extends WebIn
7272 if (profileNode.functionName && profileNode.functionName.startsWith("on") && profileNode.functionName.length >= 5)
7373 className = WebInspector.CallFrameView.EventListenerIconStyleClassName;
7474
75  var hasChildren = !!profileNode.childNodes.length;
76 
77  super([className], title, subtitle, profileNode, hasChildren);
 75 super([className], title, subtitle, profileNode, {hasChildren: !!profileNode.childNodes.length});
7876
7977 this._profileNode = profileNode;
8078 this._delegate = delegate || null;

Source/WebInspectorUI/UserInterface/Views/RecordingContentView.css

 1/*
 2 * Copyright (C) 2017 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26.content-view.recording {
 27 display: flex;
 28 align-items: center;
 29 justify-content: center;
 30 padding: 15px;
 31}
 32
 33.content-view.recording > canvas {
 34 max-width: 100%;
 35 max-height: 100%;
 36}

Source/WebInspectorUI/UserInterface/Views/RecordingContentView.js

 1/*
 2 * Copyright (C) 2017 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26WebInspector.RecordingContentView = class RecordingContentView extends WebInspector.ContentView
 27{
 28 constructor(representedObject)
 29 {
 30 console.assert(representedObject instanceof WebInspector.Recording);
 31
 32 super(representedObject);
 33
 34 this._index = NaN;
 35
 36 this.element.classList.add("recording", this.representedObject.type);
 37
 38 if (this.representedObject.type === WebInspector.Recording.Type.Canvas2D) {
 39 this._showGridButtonNavigationItem = new WebInspector.ActivateButtonNavigationItem("show-grid", WebInspector.UIString("Show Grid"), WebInspector.UIString("Hide Grid"), "Images/NavigationItemCheckers.svg", 13, 13);
 40 this._showGridButtonNavigationItem.addEventListener(WebInspector.ButtonNavigationItem.Event.Clicked, this._showGridButtonClicked, this);
 41 this._showGridButtonNavigationItem.activated = !!WebInspector.settings.showImageGrid.value;
 42
 43 this._context = this.element.appendChild(document.createElement("canvas")).getContext("2d");
 44 this._content = null;
 45 }
 46 }
 47
 48 // Public
 49
 50 get navigationItems()
 51 {
 52 if (this.representedObject.type === WebInspector.Recording.Type.Canvas2D)
 53 return [this._showGridButtonNavigationItem];
 54 return [];
 55 }
 56
 57 set actionIndex(index)
 58 {
 59 console.assert(!this.representedObject || (index >= 0 && index < this.representedObject.actions.length));
 60 if (!this.representedObject || index < 0 || index >= this.representedObject.actions.length || index === this._index)
 61 return;
 62
 63 this._index = index;
 64
 65 if (this.representedObject.type === WebInspector.Recording.Type.Canvas2D) {
 66 let initialState = this.representedObject.initialState;
 67
 68 if (initialState.content && !this._content) {
 69 let image = new Image;
 70 image.src = initialState.content;
 71 image.addEventListener("load", (event) => {
 72 // Loading took too long and the current action index has already changed.
 73 if (index !== this._index)
 74 return;
 75
 76 this._content = image;
 77
 78 this._index = NaN;
 79 this.actionIndex = index;
 80 });
 81 image.addEventListener("error", (event) => {
 82 // Loading took too long and the current action index has already changed.
 83 if (index !== this._index)
 84 return;
 85
 86 this._index = NaN;
 87 this.actionIndex = index;
 88 });
 89 return;
 90 }
 91
 92 if ("width" in initialState.attributes)
 93 this._context.canvas.width = initialState.attributes.width;
 94
 95 if ("height" in initialState.attributes)
 96 this._context.canvas.height = initialState.attributes.height;
 97
 98 this._context.clearRect(0, 0, this._context.canvas.width, this._context.canvas.height);
 99
 100 if (this._content)
 101 this._context.drawImage(this._content, 0, 0);
 102
 103 for (let name in initialState.attributes) {
 104 if (!(name in this._context))
 105 continue;
 106
 107 try {
 108 this._context[name] = initialState.attributes[name];
 109 } catch (e) {
 110 // Ignore
 111 }
 112 }
 113
 114 for (let name in initialState.functions) {
 115 if (!(name in this._context))
 116 continue;
 117
 118 try {
 119 this._context[name](...initialState.functions[name]);
 120 } catch (e) {
 121 // Ignore
 122 }
 123 }
 124
 125 let actions = this.representedObject.actions;
 126 for (let i = 0; i <= this._index; ++i) {
 127 if (!actions[i].valid)
 128 continue;
 129
 130 let hasIrreplaceableParameter = false;
 131 let parameters = actions[i].parameters.map((parameter, parameterIndex) => {
 132 let unavailableReplacement = actions[i].unavailableParameterReplacementForType(this.representedObject.type, parameterIndex);
 133 if (unavailableReplacement) {
 134 if (typeof unavailableReplacement.callback === "function")
 135 return unavailableReplacement.callback(parameter, this._context);
 136
 137 hasIrreplaceableParameter = true;
 138 }
 139 return parameter;
 140 });
 141
 142 if (hasIrreplaceableParameter)
 143 continue;
 144
 145 try {
 146 if (actions[i].attributeForType(this.representedObject.type)) {
 147 if (actions[i].name === "width" || actions[i].name === "height")
 148 this._context.canvas[actions[i].name] = parameters[0];
 149 else
 150 this._context[actions[i].name] = parameters[0];
 151 } else
 152 this._context[actions[i].name](...parameters);
 153 } catch (e) {
 154 // Ignore
 155 }
 156 }
 157 }
 158 }
 159
 160 // Protected
 161
 162 shown()
 163 {
 164 super.shown();
 165
 166 this._updateImageGrid();
 167 }
 168
 169 // Private
 170
 171 _updateImageGrid()
 172 {
 173 let activated = WebInspector.settings.showImageGrid.value;
 174 this._showGridButtonNavigationItem.activated = activated;
 175 this._context.canvas.classList.toggle("show-grid", activated);
 176 }
 177
 178 _showGridButtonClicked(event)
 179 {
 180 WebInspector.settings.showImageGrid.value = !this._showGridButtonNavigationItem.activated;
 181
 182 this._updateImageGrid();
 183 }
 184};

Source/WebInspectorUI/UserInterface/Views/RecordingDetailsSidebarPanel.css

 1/*
 2 * Copyright (C) 2017 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26.sidebar > .panel.details.recording > .content > .data-grid {
 27 min-height: 100%;
 28}
 29
 30.sidebar > .panel.details.recording > .content > .data-grid tr.modified {
 31 background-color: var(--value-changed-highlight);
 32}
 33
 34.sidebar > .panel.details.recording > .content > .data-grid tr:not(.selected) .parameter.unavailable {
 35 color: grey;
 36}

Source/WebInspectorUI/UserInterface/Views/RecordingDetailsSidebarPanel.js

 1/*
 2 * Copyright (C) 2017 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26WebInspector.RecordingDetailsSidebarPanel = class RecordingDetailsSidebarPanel extends WebInspector.DetailsSidebarPanel
 27{
 28 constructor()
 29 {
 30 super("recording", WebInspector.UIString("Current State"));
 31
 32 this.recording = null;
 33
 34 this._dataGrid = null;
 35 }
 36
 37 // Static
 38
 39 static disallowInstanceForClass()
 40 {
 41 return true;
 42 }
 43
 44 // Public
 45
 46 inspect(objects)
 47 {
 48 // Always show this sidebar, as it will have it's data populated by the model object.
 49 return true;
 50 }
 51
 52 set recording(recording)
 53 {
 54 this._recording = recording;
 55
 56 for (let subview of this.contentView.subviews)
 57 this.contentView.removeSubview(subview);
 58
 59 this._index = NaN;
 60 }
 61
 62 set actionIndex(index)
 63 {
 64 console.assert(!this._recording || (index >= 0 && index < this._recording.actions.length));
 65 if (!this._recording || index < 0 || index > this._recording.actions.length || index === this._index)
 66 return;
 67
 68 this._index = index;
 69
 70 if (this._recording.type === WebInspector.Recording.Type.Canvas2D) {
 71 if (!this._dataGrid) {
 72 this._dataGrid = new WebInspector.DataGrid({
 73 name: {title: WebInspector.UIString("Name")},
 74 value: {title: WebInspector.UIString("Value")},
 75 });
 76 }
 77 if (!this._dataGrid.parentView)
 78 this.contentView.addSubview(this._dataGrid);
 79
 80 this._dataGrid.removeChildren();
 81
 82 let initialState = this._recording.initialState;
 83 let data = Object.shallowMerge(initialState.attributes, initialState.functions);
 84
 85 let actions = this._recording.actions;
 86 for (let i = 0; i <= this._index; ++i) {
 87 if (!(actions[i].name in data) || !actions[i].valid)
 88 continue;
 89
 90 data[actions[i].name] = actions[i];
 91 }
 92
 93 for (let name of Object.keys(data).sort(numericStringComparator)) {
 94 let valueFragment = document.createDocumentFragment();
 95
 96 let parameters = data[name];
 97 if (parameters instanceof WebInspector.RecordingAction)
 98 parameters = parameters.parameters;
 99 else
 100 parameters = [parameters];
 101
 102 for (let i = 0; i < parameters.length; ++i) {
 103 if (i)
 104 valueFragment.append(", ");
 105
 106 let parameterElement = valueFragment.appendChild(document.createElement("span"));
 107 parameterElement.classList.add("parameter");
 108
 109 let textContent = "";
 110 if (data[name] instanceof WebInspector.RecordingAction) {
 111 let unavailableReplacement = data[name].unavailableParameterReplacementForType(this._recording.type, i);
 112 if (unavailableReplacement) {
 113 let replacement = unavailableReplacement.name(parameters[i]);
 114 if (replacement !== parameters[i]) {
 115 parameterElement.classList.add("unavailable");
 116 textContent = replacement;
 117 }
 118 }
 119 }
 120 if (!textContent.length) {
 121 textContent = parameters[i];
 122
 123 if (name in initialState.functions)
 124 textContent = JSON.stringify(textContent);
 125 }
 126
 127 parameterElement.textContent = textContent;
 128
 129 if (name in initialState.attributes)
 130 break;
 131 }
 132
 133 let classNames = [];
 134 if (name === actions[this._index].name)
 135 classNames.push("modified");
 136
 137 const hasChildren = false;
 138 this._dataGrid.appendChild(new WebInspector.DataGridNode({name, value: valueFragment}, hasChildren, classNames));
 139 }
 140
 141 this.updateLayoutIfNeeded();
 142 }
 143 }
 144};

Source/WebInspectorUI/UserInterface/Views/RecordingNavigationSidebarPanel.css

 1/*
 2 * Copyright (C) 2017 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26.sidebar > .panel.navigation.recording > :matches(.content, .empty-content-placeholder) {
 27 top: var(--navigation-bar-height);
 28}
 29
 30.sidebar > .panel.navigation.recording > .content > .tree-outline {
 31 min-height: 100%;
 32 background: var(--transparent-stripe-background-gradient);
 33 counter-reset: actions -1; /* Ensures that the "Initial State" item has the index 0. */
 34}
 35
 36.sidebar > .panel.navigation.recording > .content > .tree-outline > .item.action::before {
 37 position: relative;
 38 top: 3px;
 39 float: left;
 40 margin-right: 4px;
 41 counter-increment: actions;
 42 content: counter(actions);
 43 font-family: Menlo, monospace;
 44}
 45
 46.sidebar > .panel.navigation.recording > .content .action > .icon {
 47 content: url("../Images/Source.svg");
 48}
 49
 50.sidebar > .panel.navigation.recording > .content .action.function > .icon {
 51 content: url(../Images/Function.svg);
 52}
 53
 54.sidebar > .panel.navigation.recording > .content .action.attribute.boolean > .icon {
 55 content: url(../Images/TypeBoolean.svg);
 56}
 57
 58.sidebar > .panel.navigation.recording > .content .action.attribute.number > .icon {
 59 content: url(../Images/TypeNumber.svg);
 60}
 61
 62.sidebar > .panel.navigation.recording > .content .action.attribute.object > .icon {
 63 content: url(../Images/TypeObject.svg);
 64}
 65
 66.sidebar > .panel.navigation.recording > .content .action.attribute.string > .icon {
 67 content: url(../Images/TypeString.svg);
 68}
 69
 70.sidebar > .panel.navigation.recording > .content .action:matches(.invalid, .unavailable) > .icon {
 71 filter: grayscale();
 72}
 73
 74.sidebar > .panel.navigation.recording > .content .action.visual:not(.selected, .invalid, .unavailable) {
 75 background-color: var(--value-visual-highlight);
 76}
 77
 78.sidebar > .panel.navigation.recording > .content .action:not(.selected, .initial-state) > .titles .parameter.unavailable {
 79 color: grey;
 80}
 81
 82.sidebar > .panel.navigation.recording > .content .action.invalid:not(.selected, .initial-state) > .titles .name,
 83.sidebar > .panel.navigation.recording > .content .action.unavailable:not(.selected, .initial-state) > .titles .parameter.unavailable {
 84 color: red;
 85}

Source/WebInspectorUI/UserInterface/Views/RecordingNavigationSidebarPanel.js

 1/*
 2 * Copyright (C) 2015 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26WebInspector.RecordingNavigationSidebarPanel = class RecordingNavigationSidebarPanel extends WebInspector.NavigationSidebarPanel
 27{
 28 constructor()
 29 {
 30 super("recording", WebInspector.UIString("Recording"));
 31
 32 this.contentTreeOutline.disclosureButtons = false;
 33
 34 this.filterBar.placeholder = WebInspector.UIString("Filter Actions");
 35
 36 this.recording = null;
 37
 38 this._importButton = null;
 39 this._exportButton = null;
 40 }
 41
 42 // Static
 43
 44 static disallowInstanceForClass()
 45 {
 46 return true;
 47 }
 48
 49 // Public
 50
 51 set recording(recording)
 52 {
 53 if (recording === this._recording)
 54 return;
 55
 56 this.contentTreeOutline.removeChildren();
 57
 58 this._recording = recording;
 59 if (this._recording) {
 60 for (let action of this._recording.actions) {
 61 let classNames = ["action"];
 62
 63 let attribute = action.attributeForType(this._recording.type);
 64 if (attribute)
 65 classNames.push("attribute", typeof action.parameters[0]);
 66 else
 67 classNames.push("function");
 68
 69 if (action.visualForType(this._recording.type))
 70 classNames.push("visual");
 71
 72 if (!action.valid)
 73 classNames.push("invalid");
 74
 75 let titleFragment = document.createDocumentFragment();
 76
 77 let nameContainer = titleFragment.appendChild(document.createElement("span"));
 78 nameContainer.classList.add("name");
 79 nameContainer.textContent = action.name;
 80
 81 if (!(action instanceof WebInspector.RecordingInitialStateAction)) {
 82 let hasIrreplaceableParameter = false;
 83
 84 titleFragment.append(attribute ? " = " : "(");
 85
 86 for (let i = 0; i < action.parameters.length; ++i) {
 87 if (i)
 88 titleFragment.append(", ");
 89
 90 let parameterElement = titleFragment.appendChild(document.createElement("span"));
 91 parameterElement.classList.add("parameter");
 92
 93 let textContent = "";
 94
 95 let unavailableReplacement = action.unavailableParameterReplacementForType(this._recording.type, i);
 96 if (unavailableReplacement) {
 97 if (typeof unavailableReplacement.callback !== "function")
 98 hasIrreplaceableParameter = true;
 99
 100 let name = unavailableReplacement.name(action.parameters[i]);
 101 if (name !== action.parameters[i]) {
 102 parameterElement.classList.add("unavailable");
 103 textContent = name;
 104 }
 105 }
 106
 107 if (!textContent.length)
 108 textContent = JSON.stringify(action.parameters[i]);
 109
 110 parameterElement.textContent = textContent;
 111
 112 if (attribute)
 113 break;
 114 }
 115
 116 if (!attribute)
 117 titleFragment.append(")");
 118
 119 if (hasIrreplaceableParameter)
 120 classNames.push("unavailable");
 121 } else
 122 classNames.push("initial-state");
 123
 124 const subtitle = null;
 125 let treeElement = new WebInspector.GeneralTreeElement(classNames, titleFragment, subtitle, action);
 126 this.contentTreeOutline.appendChild(treeElement);
 127 }
 128 }
 129
 130 this.updateEmptyContentPlaceholder(WebInspector.UIString("No Recording Data"));
 131
 132 if (this._exportButton)
 133 this._exportButton.disabled = !this.contentTreeOutline.hasChildren;
 134 }
 135
 136 set actionIndex(index)
 137 {
 138 console.assert(!this._recording || (index >= 0 && index < this._recording.actions.length));
 139 if (!this._recording || index < 0 || index >= this._recording.actions.length)
 140 return;
 141
 142 const omitFocus = true;
 143 const selectedByUser = false;
 144 const suppressOnSelect = true;
 145 const suppressOnDeselect = true;
 146 this.contentTreeOutline.children[index].select(omitFocus, selectedByUser, suppressOnSelect, suppressOnDeselect);
 147 }
 148
 149 // Protected
 150
 151 initialLayout()
 152 {
 153 super.initialLayout();
 154
 155 const role = "button";
 156
 157 const importLabel = WebInspector.UIString("Import");
 158 let importNavigationItem = new WebInspector.NavigationItem("recording-import", role, importLabel);
 159
 160 this._importButton = importNavigationItem.element.appendChild(document.createElement("button"));
 161 this._importButton.textContent = importLabel;
 162 this._importButton.addEventListener("click", this._importNavigationItemClicked.bind(this));
 163
 164 const exportLabel = WebInspector.UIString("Export");
 165 let exportNavigationItem = new WebInspector.NavigationItem("recording-export", role, exportLabel);
 166
 167 this._exportButton = exportNavigationItem.element.appendChild(document.createElement("button"));
 168 this._exportButton.textContent = exportLabel;
 169 this._exportButton.disabled = true;
 170 this._exportButton.addEventListener("click", this._exportNavigationItemClicked.bind(this));
 171
 172 const element = null;
 173 this.addSubview(new WebInspector.NavigationBar(element, [importNavigationItem, exportNavigationItem]));
 174 }
 175
 176 // Private
 177
 178 _importNavigationItemClicked(event)
 179 {
 180 WebInspector.loadDataFromFile((data) => {
 181 let payload = null;
 182 try {
 183 payload = JSON.parse(data);
 184 } catch (e) {
 185 WebInspector.Recording.synthesizeError(e);
 186 return;
 187 }
 188
 189 if (payload.version !== WebInspector.Recording.Version) {
 190 WebInspector.Recording.synthesizeError(WebInspector.UIString("unsupported version"));
 191 return;
 192 }
 193
 194 this.dispatchEventToListeners(WebInspector.RecordingNavigationSidebarPanel.Event.Import, {payload});
 195 });
 196 }
 197
 198 _exportNavigationItemClicked(event)
 199 {
 200 if (!this._recording)
 201 return;
 202
 203 const forceSaveAs = true;
 204 WebInspector.saveDataToFile({
 205 url: "web-inspector:///Recording.json",
 206 content: JSON.stringify(this._recording.toJSON()),
 207 }, forceSaveAs);
 208 }
 209};
 210
 211WebInspector.RecordingNavigationSidebarPanel.Event = {
 212 Import: "recording-navigation-sidebar-panel-import",
 213};

Source/WebInspectorUI/UserInterface/Views/RecordingTabContentView.js

 1/*
 2 * Copyright (C) 2017 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26WebInspector.RecordingTabContentView = class RecordingTabContentView extends WebInspector.ContentBrowserTabContentView
 27{
 28 constructor()
 29 {
 30 let {image, title} = WebInspector.RecordingTabContentView.tabInfo();
 31 let tabBarItem = new WebInspector.GeneralTabBarItem(image, title);
 32
 33 const navigationSidebarPanelConstructor = WebInspector.RecordingNavigationSidebarPanel;
 34 const detailsSidebarPanelConstructors = [WebInspector.RecordingDetailsSidebarPanel];
 35 const disableBackForward = true;
 36 let flexibleNavigationItem = new WebInspector.ScrubberNavigationItem;
 37 super("recording", "recording", tabBarItem, navigationSidebarPanelConstructor, detailsSidebarPanelConstructors, disableBackForward, flexibleNavigationItem);
 38
 39 this._visualActionIndexes = [];
 40
 41 this._scrubberNavigationItem = flexibleNavigationItem;
 42 this._scrubberNavigationItem.value = 0;
 43 this._scrubberNavigationItem.disabled = true;
 44 this._scrubberNavigationItem.addEventListener(WebInspector.ScrubberNavigationItem.Event.ValueChanged, this._scrubberNavigationItemValueChanged, this);
 45
 46 this.navigationSidebarPanel.addEventListener(WebInspector.RecordingNavigationSidebarPanel.Event.Import, this._navigationSidebarImport, this);
 47 this.navigationSidebarPanel.contentTreeOutline.addEventListener(WebInspector.TreeOutline.Event.SelectionDidChange, this._navigationSidebarTreeOutlineSelectionChanged, this);
 48
 49 this._recording = null;
 50 }
 51
 52 // Static
 53
 54 static tabInfo()
 55 {
 56 return {
 57 image: "Images/Recording.svg",
 58 title: WebInspector.UIString("Recording"),
 59 };
 60 }
 61
 62 // Public
 63
 64 get type()
 65 {
 66 return WebInspector.RecordingTabContentView.Type;
 67 }
 68
 69 canShowRepresentedObject(representedObject)
 70 {
 71 // Once a recording has been loaded for this tab, do not allow another one to be loaded.
 72 // This will cause new tabs to be opened for each recording, which is the desired behavior.
 73 if (this._recording)
 74 return false;
 75
 76 return representedObject instanceof WebInspector.Recording;
 77 }
 78
 79 showRepresentedObject(representedObject, cookie)
 80 {
 81 super.showRepresentedObject(representedObject, cookie);
 82
 83 this._recording = representedObject;
 84
 85 this._visualActionIndexes = [];
 86 representedObject.actions.forEach((action, i) => {
 87 if (action.visualForType(representedObject.type))
 88 this._visualActionIndexes.push(i);
 89 });
 90
 91 this._scrubberNavigationItem.value = 0;
 92 this._scrubberNavigationItem.min = 0;
 93 this._scrubberNavigationItem.max = representedObject.actions.length - 1;
 94 this._scrubberNavigationItem.disabled = false;
 95
 96 this.navigationSidebarPanel.recording = representedObject;
 97 for (let detailsSidebarPanel of this.detailsSidebarPanels)
 98 detailsSidebarPanel.recording = representedObject;
 99
 100 this._actionIndex = this._scrubberNavigationItem.value;
 101 }
 102
 103 // Protected
 104
 105 restoreStateFromCookie(restorationType)
 106 {
 107 // Don't attempt to do anything to this tab.
 108 }
 109
 110 saveStateToCookie(cookie)
 111 {
 112 // Don't attempt to do anything to this tab.
 113 }
 114
 115 closed()
 116 {
 117 super.closed();
 118
 119 this.navigationSidebarPanel.recording = null;
 120 for (let detailsSidebarPanel of this.detailsSidebarPanels)
 121 detailsSidebarPanel.recording = null;
 122 }
 123
 124 // Private
 125
 126 set _actionIndex(index)
 127 {
 128 this._scrubberNavigationItem.value = index;
 129
 130 this.navigationSidebarPanel.actionIndex = index;
 131 this.contentBrowser.currentContentView.actionIndex = index;
 132 for (let detailsSidebarPanel of this.detailsSidebarPanels)
 133 detailsSidebarPanel.actionIndex = index;
 134 }
 135
 136 _scrubberNavigationItemValueChanged(event)
 137 {
 138 for (let i = 0; i <= this._visualActionIndexes.length; ++i) {
 139 if (this._visualActionIndexes[i] < this._scrubberNavigationItem.value)
 140 continue;
 141
 142 let min = i ? this._visualActionIndexes[i - 1] : this._scrubberNavigationItem.min;
 143 let max = i < this._visualActionIndexes.length ? this._visualActionIndexes[i] : this._scrubberNavigationItem.max;
 144 this._actionIndex = (this._scrubberNavigationItem.value >= (min + max) / 2) ? max : min;
 145 return;
 146 }
 147 }
 148
 149 _navigationSidebarImport(event)
 150 {
 151 this.showRepresentedObject(WebInspector.Recording.fromPayload(event.data.payload));
 152 }
 153
 154 _navigationSidebarTreeOutlineSelectionChanged(event)
 155 {
 156 // Ignore deselect events.
 157 if (!event.data.selectedElement)
 158 return;
 159
 160 this._actionIndex = this.navigationSidebarPanel.contentTreeOutline.selectedTreeElementIndex;
 161 }
 162};
 163
 164WebInspector.RecordingTabContentView.Type = "recording";

Source/WebInspectorUI/UserInterface/Views/ResourceDetailsSidebarPanel.js

@@WebInspector.ResourceDetailsSidebarPanel = class ResourceDetailsSidebarPanel ext
2727{
2828 constructor()
2929 {
30  super("resource-details", WebInspector.UIString("Resource"), WebInspector.UIString("Resource"));
 30 super("resource-details", WebInspector.UIString("Resource"));
3131
3232 this.element.classList.add("resource");
3333

Source/WebInspectorUI/UserInterface/Views/ResourceTreeElement.js

@@WebInspector.ResourceTreeElement = class ResourceTreeElement extends WebInspecto
2929 {
3030 console.assert(resource instanceof WebInspector.Resource);
3131
32  super(resource, ["resource", WebInspector.ResourceTreeElement.ResourceIconStyleClassName, resource.type], "", "", representedObject || resource, false);
 32 super(resource, ["resource", WebInspector.ResourceTreeElement.ResourceIconStyleClassName, resource.type], "", "", representedObject || resource);
3333
3434 this._updateResource(resource);
3535 }

Source/WebInspectorUI/UserInterface/Views/ScopeChainDetailsSidebarPanel.js

@@WebInspector.ScopeChainDetailsSidebarPanel = class ScopeChainDetailsSidebarPanel
2727{
2828 constructor()
2929 {
30  super("scope-chain", WebInspector.UIString("Scope Chain"), WebInspector.UIString("Scope Chain"));
 30 super("scope-chain", WebInspector.UIString("Scope Chain"));
3131
3232 this._callFrame = null;
3333

Source/WebInspectorUI/UserInterface/Views/ScriptTreeElement.js

@@WebInspector.ScriptTreeElement = class ScriptTreeElement extends WebInspector.So
2929 {
3030 console.assert(script instanceof WebInspector.Script);
3131
32  super(script, "script", null, null, script, false);
 32 super(script, "script", null, null, script);
3333
3434 this.mainTitle = script.displayName;
3535

Source/WebInspectorUI/UserInterface/Views/ScrubberNavigationItem.css

 1/*
 2 * Copyright (C) 2017 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26.navigation-bar .item.scrubber {
 27 padding: 0 4px;
 28}
 29
 30.navigation-bar .item.scrubber > input {
 31 width: 100%;
 32}
 33
 34.navigation-bar .item.scrubber > input[disabled] {
 35 opacity: 0.5;
 36 pointer-events: none;
 37}

Source/WebInspectorUI/UserInterface/Views/ScrubberNavigationItem.js

 1/*
 2 * Copyright (C) 2017 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26WebInspector.ScrubberNavigationItem = class ScrubberNavigationItem extends WebInspector.FlexibleSpaceNavigationItem
 27{
 28 constructor(identifier)
 29 {
 30 super(identifier);
 31
 32 this._sliderElement = this._element.appendChild(document.createElement("input"));
 33 this._sliderElement.type = "range";
 34 this._sliderElement.addEventListener("input", this._sliderChanged.bind(this));
 35 }
 36
 37 // Public
 38
 39 get value() { return parseInt(this._sliderElement.value); }
 40 set value(value) { this._sliderElement.value = value; }
 41
 42 get min() { return parseInt(this._sliderElement.min); }
 43 set min(min) { this._sliderElement.min = min; }
 44
 45 get max() { return parseInt(this._sliderElement.max); }
 46 set max(max) { this._sliderElement.max = max; }
 47
 48 set disabled(flag)
 49 {
 50 this._sliderElement.disabled = !!flag;
 51 }
 52
 53 // Protected
 54
 55 get additionalClassNames()
 56 {
 57 return super.additionalClassNames.concat(["scrubber"]);
 58 }
 59
 60 // Private
 61
 62 _sliderChanged(event)
 63 {
 64 this.dispatchEventToListeners(WebInspector.ScrubberNavigationItem.Event.ValueChanged);
 65 }
 66};
 67
 68WebInspector.ScrubberNavigationItem.Event = {
 69 ValueChanged: "slider-navigation-item-value-changed",
 70};

Source/WebInspectorUI/UserInterface/Views/SearchResultTreeElement.js

@@WebInspector.SearchResultTreeElement = class SearchResultTreeElement extends Web
3131
3232 var title = WebInspector.SearchResultTreeElement.truncateAndHighlightTitle(representedObject.title, representedObject.searchTerm, representedObject.sourceCodeTextRange);
3333
34  super(representedObject.className, title, null, representedObject, false);
 34 super(representedObject.className, title, null, representedObject);
3535 }
3636
3737 // Static

Source/WebInspectorUI/UserInterface/Views/SidebarPanel.js

2525
2626WebInspector.SidebarPanel = class SidebarPanel extends WebInspector.View
2727{
28  constructor(identifier, displayName, element, role, label)
 28 constructor(identifier, displayName)
2929 {
30  super(element);
 30 super();
3131
3232 this._identifier = identifier;
3333 this._displayName = displayName;

@@WebInspector.SidebarPanel = class SidebarPanel extends WebInspector.View
3737
3838 this.element.classList.add("panel", identifier);
3939
40  this.element.setAttribute("role", role || "group");
41  this.element.setAttribute("aria-label", label || displayName);
 40 this.element.setAttribute("role", "group");
 41 this.element.setAttribute("aria-label", displayName);
4242
4343 this._contentView = new WebInspector.View;
4444 this._contentView.element.classList.add("content");

Source/WebInspectorUI/UserInterface/Views/SourceCodeTreeElement.js

2525
2626WebInspector.SourceCodeTreeElement = class SourceCodeTreeElement extends WebInspector.FolderizedTreeElement
2727{
28  constructor(sourceCode, classNames, title, subtitle, representedObject, hasChildren)
 28 constructor(sourceCode, classNames, title, subtitle, representedObject)
2929 {
3030 console.assert(sourceCode instanceof WebInspector.SourceCode);
3131
32  super(classNames, title, subtitle, representedObject || sourceCode, hasChildren);
 32 super(classNames, title, subtitle, representedObject || sourceCode);
3333
3434 this._updateSourceCode(sourceCode);
3535 }

Source/WebInspectorUI/UserInterface/Views/StorageTreeElement.js

@@WebInspector.StorageTreeElement = class StorageTreeElement extends WebInspector.
2727{
2828 constructor(classNames, title, representedObject)
2929 {
30  super(classNames, title, null, representedObject, false);
 30 super(classNames, title, null, representedObject);
3131
3232 this.flattened = false;
3333 }

Source/WebInspectorUI/UserInterface/Views/TabBar.js

@@WebInspector.TabBar = class TabBar extends WebInspector.View
4444 this.addTabBarItem(tabBarItem);
4545 }
4646
47  this.addTabBarItem(WebInspector.settingsTabContentView.tabBarItem, true);
 47 this.addTabBarItem(WebInspector.settingsTabContentView.tabBarItem, {doNotAnimate: true});
4848
4949 this._newTabTabBarItem = new WebInspector.PinnedTabBarItem("Images/NewTabPlus.svg", WebInspector.UIString("Create a new tab"));
5050 this._newTabTabBarItem.element.addEventListener("mouseenter", this._handleNewTabMouseEnter.bind(this));
5151 this._newTabTabBarItem.element.addEventListener("click", this._handleNewTabClick.bind(this));
52  this.addTabBarItem(this._newTabTabBarItem, true);
 52 this.addTabBarItem(this._newTabTabBarItem, {doNotAnimate: true});
5353 }
5454
5555 // Public

@@WebInspector.TabBar = class TabBar extends WebInspector.View
6262 this._newTabTabBarItem.disabled = newTabExists;
6363 }
6464
65  addTabBarItem(tabBarItem, doNotAnimate)
 65 addTabBarItem(tabBarItem, options = {})
6666 {
67  return this.insertTabBarItem(tabBarItem, this._tabBarItems.length, doNotAnimate);
 67 return this.insertTabBarItem(tabBarItem, this._tabBarItems.length, options);
6868 }
6969
70  insertTabBarItem(tabBarItem, index, doNotAnimate)
 70 insertTabBarItem(tabBarItem, index, options = {})
7171 {
7272 console.assert(tabBarItem instanceof WebInspector.TabBarItem);
7373 if (!(tabBarItem instanceof WebInspector.TabBarItem))

@@WebInspector.TabBar = class TabBar extends WebInspector.View
7979 if (this._tabAnimatedClosedSinceMouseEnter) {
8080 // Delay adding the new tab until we can expand the tabs after a closed tab.
8181 this._finishExpandingTabsAfterClose().then(() => {
82  this.insertTabBarItem(tabBarItem, index, doNotAnimate);
 82 this.insertTabBarItem(tabBarItem, index, options);
8383 });
8484 return;
8585 }

@@WebInspector.TabBar = class TabBar extends WebInspector.View
9393
9494 if (this.element.classList.contains("animating")) {
9595 requestAnimationFrame(removeStyles.bind(this));
96  doNotAnimate = true;
 96 options.doNotAnimate = true;
9797 }
9898
9999 var beforeTabSizesAndPositions;
100  if (!doNotAnimate)
 100 if (!options.doNotAnimate)
101101 beforeTabSizesAndPositions = this._recordTabBarItemSizesAndPositions();
102102
103103 this._tabBarItems.splice(index, 0, tabBarItem);

@@WebInspector.TabBar = class TabBar extends WebInspector.View
138138 this.element.removeEventListener("webkitTransitionEnd", removeStylesListener);
139139 }
140140
141  if (!doNotAnimate) {
 141 if (!options.doNotAnimate) {
142142 var afterTabSizesAndPositions = this._recordTabBarItemSizesAndPositions();
143143
144144 this.updateLayout();

@@WebInspector.TabBar = class TabBar extends WebInspector.View
171171 return tabBarItem;
172172 }
173173
174  removeTabBarItem(tabBarItemOrIndex, doNotAnimate, doNotExpand)
 174 removeTabBarItem(tabBarItemOrIndex, options = {})
175175 {
176176 let tabBarItem = this._findTabBarItem(tabBarItemOrIndex);
177177 if (!tabBarItem || tabBarItem instanceof WebInspector.PinnedTabBarItem)

@@WebInspector.TabBar = class TabBar extends WebInspector.View
190190
191191 if (this.element.classList.contains("animating")) {
192192 requestAnimationFrame(removeStyles.bind(this));
193  doNotAnimate = true;
 193 options.doNotAnimate = true;
194194 }
195195
196196 var beforeTabSizesAndPositions;
197  if (!doNotAnimate)
 197 if (!options.doNotAnimate)
198198 beforeTabSizesAndPositions = this._recordTabBarItemSizesAndPositions();
199199
200200 // Subtract 1 from normalTabCount since arrays begin indexing at 0.

@@WebInspector.TabBar = class TabBar extends WebInspector.View
208208
209209 const shouldOpenDefaultTab = !tabBarItem.isDefaultTab && !this.normalTabCount;
210210 if (shouldOpenDefaultTab)
211  doNotAnimate = true;
 211 options.doNotAnimate = true;
212212
213  if (!hasMoreThanOneNormalTab || wasLastNormalTab || !doNotExpand) {
214  if (!doNotAnimate) {
 213 if (!hasMoreThanOneNormalTab || wasLastNormalTab || !options.doNotExpand) {
 214 if (!options.doNotAnimate) {
215215 this._tabAnimatedClosedSinceMouseEnter = true;
216216 this._finishExpandingTabsAfterClose(beforeTabSizesAndPositions);
217217 } else

@@WebInspector.TabBar = class TabBar extends WebInspector.View
280280 this.element.removeEventListener("webkitTransitionEnd", removeStylesListener);
281281 }
282282
283  if (!doNotAnimate) {
 283 if (!options.doNotAnimate) {
284284 this.element.classList.add("static-layout");
285285
286286 this._tabAnimatedClosedSinceMouseEnter = true;

@@WebInspector.TabBar = class TabBar extends WebInspector.View
615615 return;
616616
617617 if (!event.altKey) {
618  this.removeTabBarItem(tabBarItem, false, true);
 618 this.removeTabBarItem(tabBarItem, {doNotExpand: true});
619619 return;
620620 }
621621

Source/WebInspectorUI/UserInterface/Views/TabBrowser.js

@@WebInspector.TabBrowser = class TabBrowser extends WebInspector.View
136136 return null;
137137 }
138138
139  addTabForContentView(tabContentView, doNotAnimate, insertionIndex)
 139 addTabForContentView(tabContentView, options = {})
140140 {
141141 console.assert(tabContentView instanceof WebInspector.TabContentView);
142142 if (!(tabContentView instanceof WebInspector.TabContentView))

@@WebInspector.TabBrowser = class TabBrowser extends WebInspector.View
163163 else
164164 this._recentTabContentViews.push(tabContentView);
165165
166  if (typeof insertionIndex === "number")
167  this._tabBar.insertTabBarItem(tabBarItem, insertionIndex, doNotAnimate);
 166 if (typeof options.insertionIndex === "number")
 167 this._tabBar.insertTabBarItem(tabBarItem, options.insertionIndex, options);
168168 else
169  this._tabBar.addTabBarItem(tabBarItem, doNotAnimate);
 169 this._tabBar.addTabBarItem(tabBarItem, options);
170170
171171 console.assert(this._recentTabContentViews.length === this._tabBar.normalTabCount);
172172 console.assert(!this.selectedTabContentView || this.selectedTabContentView === this._recentTabContentViews[0]);

@@WebInspector.TabBrowser = class TabBrowser extends WebInspector.View
174174 return true;
175175 }
176176
177  showTabForContentView(tabContentView, doNotAnimate, insertionIndex)
 177 showTabForContentView(tabContentView, options = {})
178178 {
179  if (!this.addTabForContentView(tabContentView, doNotAnimate, insertionIndex))
 179 if (!this.addTabForContentView(tabContentView, options))
180180 return false;
181181
182  this._tabBar.selectedTabBarItem = tabContentView.tabBarItem;
 182 if (!options.skipReveal)
 183 this._tabBar.selectedTabBarItem = tabContentView.tabBarItem;
183184
184185 // FIXME: this is a workaround for <https://webkit.org/b/151876>.
185186 // Without this extra call, we might never lay out the child tab

@@WebInspector.TabBrowser = class TabBrowser extends WebInspector.View
191192 return true;
192193 }
193194
194  closeTabForContentView(tabContentView, doNotAnimate)
 195 closeTabForContentView(tabContentView, options = {})
195196 {
196197 console.assert(tabContentView instanceof WebInspector.TabContentView);
197198 if (!(tabContentView instanceof WebInspector.TabContentView))

@@WebInspector.TabBrowser = class TabBrowser extends WebInspector.View
204205 if (tabContentView.tabBarItem.parentTabBar !== this._tabBar)
205206 return false;
206207
207  this._tabBar.removeTabBarItem(tabContentView.tabBarItem, doNotAnimate);
 208 this._tabBar.removeTabBarItem(tabContentView.tabBarItem, options);
208209
209210 console.assert(this._recentTabContentViews.length === this._tabBar.normalTabCount);
210211 console.assert(!this.selectedTabContentView || this.selectedTabContentView === this._recentTabContentViews[0]);

Source/WebInspectorUI/UserInterface/Views/TabContentView.js

@@WebInspector.TabContentView = class TabContentView extends WebInspector.ContentV
177177 {
178178 if (!this._navigationSidebarPanelConstructor)
179179 return null;
180  return WebInspector.instanceForClass(this._navigationSidebarPanelConstructor);
 180 if (!this._navigationSidebarPanel)
 181 this._navigationSidebarPanel = WebInspector.instanceForClass(this._navigationSidebarPanelConstructor);
 182 return this._navigationSidebarPanel;
181183 }
182184
183185 get navigationSidebarCollapsedSetting() { return this._navigationSidebarCollapsedSetting; }

Source/WebInspectorUI/UserInterface/Views/TimelineRecordTreeElement.js

@@WebInspector.TimelineRecordTreeElement = class TimelineRecordTreeElement extends
5555 let iconStyleClass = WebInspector.TimelineTabContentView.iconClassNameForRecord(timelineRecord);
5656 let title = WebInspector.TimelineTabContentView.displayNameForRecord(timelineRecord);
5757
58  super([iconStyleClass], title, subtitle, representedObject || timelineRecord, false);
 58 super([iconStyleClass], title, subtitle, representedObject || timelineRecord);
5959
6060 this._record = timelineRecord;
6161 this._sourceCodeLocation = sourceCodeLocation;

Source/WebInspectorUI/UserInterface/Views/TimelineTabContentView.css

4141}
4242
4343.timeline.tab.content-view .navigation-bar > .item.radio {
44  margin-top: 5px;
4544 height: 17px;
4645}

Source/WebInspectorUI/UserInterface/Views/TimelineView.css

4242}
4343
4444.panel.navigation.timeline.timeline-recording-content-view-showing > .content > .tree-outline {
45  background-image: linear-gradient(to bottom, transparent, transparent 50%, hsla(0, 0%, 0%, 0.03) 50%, hsla(0, 0%, 0%, 0.03));
46  background-size: 100% 40px;
 45 background: var(--transparent-stripe-background-gradient);
4746}

Source/WebInspectorUI/UserInterface/Views/TreeElement.js

2828
2929WebInspector.TreeElement = class TreeElement extends WebInspector.Object
3030{
31  constructor(title, representedObject, hasChildren)
 31 constructor(title, representedObject, {hasChildren} = {})
3232 {
3333 super();
3434

Source/WebInspectorUI/UserInterface/Views/TreeOutline.js

@@WebInspector.TreeOutline = class TreeOutline extends WebInspector.Object
313313 }
314314
315315 this.children = [];
 316 this.hasChildren = false;
316317 }
317318
318319 removeChildrenRecursive(suppressOnDeselect)

Source/WebInspectorUI/UserInterface/Views/TypeTreeElement.js

@@WebInspector.TypeTreeElement = class TypeTreeElement extends WebInspector.Genera
2727{
2828 constructor(name, structureDescription, isPrototype)
2929 {
30  super(null, null, null, structureDescription || null, false);
 30 super(null, null, null, structureDescription || null);
3131
3232 console.assert(!structureDescription || structureDescription instanceof WebInspector.StructureDescription);
3333

Source/WebInspectorUI/UserInterface/Views/Variables.css

6161 --text-color-gray-medium: hsl(0, 0%, 50%);
6262 --error-text-color: hsl(0, 86%, 47%);
6363
 64 --value-changed-highlight: hsla(83, 100%, 48%, 0.4);
 65 --value-visual-highlight: hsla(60, 100%, 50%, 0.4);
 66
6467 --breakpoint-fill-color: hsl(212, 45%, 54%);
6568 --breakpoint-stroke-color: hsl(212, 45%, 48%);
6669 --breakpoint-disabled-fill-color: hsl(212, 40%, 84%);

9194
9295 --even-zebra-stripe-row-background-color: white;
9396 --odd-zebra-stripe-row-background-color: hsl(0, 0%, 95%);
 97 --transparent-stripe-background-gradient: linear-gradient(to bottom, transparent, transparent 50%, hsla(0, 0%, 0%, 0.03) 50%, hsla(0, 0%, 0%, 0.03)) top left / 100% 40px;
9498
9599 --toolbar-height: 36px;
96100 --tab-bar-height: 24px;