Diff
Modified: trunk/LayoutTests/ChangeLog (238685 => 238686)
--- trunk/LayoutTests/ChangeLog 2018-11-29 20:52:46 UTC (rev 238685)
+++ trunk/LayoutTests/ChangeLog 2018-11-29 21:01:15 UTC (rev 238686)
@@ -1,3 +1,22 @@
+2018-11-29 Justin Michaud <justin_mich...@apple.com>
+
+ CSS Painting API should pass 'this' correctly to paint callback, and repaint when properties change.
+ https://bugs.webkit.org/show_bug.cgi?id=191443
+
+ Reviewed by Dean Jackson.
+
+ * fast/css-custom-paint/animate-expected.html: Added.
+ * fast/css-custom-paint/animate-repaint-expected.txt: Added.
+ * fast/css-custom-paint/animate-repaint.html: Added.
+ * fast/css-custom-paint/animate.html: Added.
+ * fast/css-custom-paint/constructor-expected.html: Added.
+ * fast/css-custom-paint/constructor.html: Added.
+ * fast/css-custom-paint/leaks-expected.txt: Added.
+ * fast/css-custom-paint/leaks.html: Added.
+ * fast/css-custom-paint/properties.html:
+ * fast/css-custom-paint/resources/leaks-frame.html: Added.
+ * platform/mac/fast/css-custom-paint/raf-leak-expected.txt: Added.
+
2018-11-29 Youenn Fablet <you...@apple.com>
A sender created through addTransceiver and populated using addTrack should have its source set
Added: trunk/LayoutTests/fast/css-custom-paint/animate-expected.html (0 => 238686)
--- trunk/LayoutTests/fast/css-custom-paint/animate-expected.html (rev 0)
+++ trunk/LayoutTests/fast/css-custom-paint/animate-expected.html 2018-11-29 21:01:15 UTC (rev 238686)
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<style>
+ #paint {
+ background: green;
+ width: 150px;
+ height: 150px;
+ }
+</style>
+
+<body>
+ <div id="paint"></div>
+</body>
Added: trunk/LayoutTests/fast/css-custom-paint/animate-repaint-expected.txt (0 => 238686)
--- trunk/LayoutTests/fast/css-custom-paint/animate-repaint-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/css-custom-paint/animate-repaint-expected.txt 2018-11-29 21:01:15 UTC (rev 238686)
@@ -0,0 +1,11 @@
+(repaint rects
+ (rect 0 0 800 600)
+ (rect 0 0 150 150)
+ (rect 8 8 784 150)
+ (rect 0 0 800 166)
+ (rect 0 0 800 600)
+ (rect 8 8 150 150)
+ (rect 8 8 150 150)
+ (rect 8 8 150 150)
+)
+
Added: trunk/LayoutTests/fast/css-custom-paint/animate-repaint.html (0 => 238686)
--- trunk/LayoutTests/fast/css-custom-paint/animate-repaint.html (rev 0)
+++ trunk/LayoutTests/fast/css-custom-paint/animate-repaint.html 2018-11-29 21:01:15 UTC (rev 238686)
@@ -0,0 +1,66 @@
+<!DOCTYPE html><!-- webkit-test-runner [ experimental:CSSPaintingAPIEnabled=true ] -->
+<meta name="author" title="Justin Michaud" href=""
+<meta name="assert" content="Test that paint worklets repaint when properties change">
+<link rel="help" content="https://drafts.css-houdini.org/css-paint-api-1/">
+<script src=""
+
+<script id="code" type="text/worklet">
+ class MyPaint {
+ static get inputProperties() { return ['--my-prop']; }
+
+ paint(ctx, geom, properties) {
+ if (properties.get('--my-prop').toString() != "goodbye") {
+ ctx.fillStyle = "red";
+ } else {
+ ctx.fillStyle = "green";
+ }
+
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+ }
+ registerPaint('my-paint', MyPaint);
+</script>
+
+<script type="text/_javascript_">
+ if (window.testRunner && window.internals) {
+ window.testRunner.dumpAsText(false);
+ window.internals.startTrackingRepaints();
+ }
+ importWorklet(CSS.paintWorklet, document.getElementById('code').textContent);
+
+ // FIXME: Once importWorklet returns a promise, these setTimeouts should go away.
+ setTimeout(function() {
+ document.getElementById('paint').style.setProperty('--my-prop', 'goodbye');
+ }, 500);
+
+ setTimeout(function() {
+ var repaintRects = "No test runner";
+ if (window.testRunner && window.internals) {
+ window.internals.startTrackingRepaints();
+
+ // force a style recalc.
+ var dummy = document.body.offsetTop;
+
+ repaintRects = window.internals.repaintRectsAsText();
+
+ window.internals.stopTrackingRepaints();
+ }
+
+ var pre = document.createElement('pre');
+ document.body.appendChild(pre);
+ pre.innerHTML = repaintRects;
+ }, 1000);
+</script>
+
+<style>
+ #paint {
+ background-image: paint(my-paint);
+ --my-prop: hello;
+ width: 150px;
+ height: 150px;
+ }
+</style>
+
+<body>
+ <div id="paint"></div>
+</body>
Added: trunk/LayoutTests/fast/css-custom-paint/animate.html (0 => 238686)
--- trunk/LayoutTests/fast/css-custom-paint/animate.html (rev 0)
+++ trunk/LayoutTests/fast/css-custom-paint/animate.html 2018-11-29 21:01:15 UTC (rev 238686)
@@ -0,0 +1,44 @@
+<!DOCTYPE html><!-- webkit-test-runner [ experimental:CSSPaintingAPIEnabled=true ] -->
+<meta name="author" title="Justin Michaud" href=""
+<meta name="assert" content="Test that paint worklets repaint when properties change">
+<link rel="help" content="https://drafts.css-houdini.org/css-paint-api-1/">
+<script src=""
+
+<script id="code" type="text/worklet">
+ class MyPaint {
+ static get inputProperties() { return ['--my-prop']; }
+
+ paint(ctx, geom, properties) {
+ if (properties.get('--my-prop').toString() != "goodbye") {
+ ctx.fillStyle = "red";
+ } else {
+ ctx.fillStyle = "green";
+ }
+
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+ }
+ registerPaint('my-paint', MyPaint);
+</script>
+
+<script type="text/_javascript_">
+ importWorklet(CSS.paintWorklet, document.getElementById('code').textContent);
+
+ // FIXME: Once importWorklet returns a promise, these setTimeouts should go away.
+ setTimeout(function() {
+ document.getElementById('paint').style.setProperty('--my-prop', 'goodbye');
+ }, 500);
+</script>
+
+<style>
+ #paint {
+ background-image: paint(my-paint);
+ --my-prop: hello;
+ width: 150px;
+ height: 150px;
+ }
+</style>
+
+<body>
+ <div id="paint"></div>
+</body>
Added: trunk/LayoutTests/fast/css-custom-paint/constructor-expected.html (0 => 238686)
--- trunk/LayoutTests/fast/css-custom-paint/constructor-expected.html (rev 0)
+++ trunk/LayoutTests/fast/css-custom-paint/constructor-expected.html 2018-11-29 21:01:15 UTC (rev 238686)
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<style>
+ .paint {
+ width: 150px;
+ height: 150px;
+ }
+</style>
+
+<body>
+ <div class="paint" style="background: white;"></div>
+ <div class="paint" style="background: green;"></div>
+ <div class="paint" style="background: green;"></div>
+</body>
Added: trunk/LayoutTests/fast/css-custom-paint/constructor.html (0 => 238686)
--- trunk/LayoutTests/fast/css-custom-paint/constructor.html (rev 0)
+++ trunk/LayoutTests/fast/css-custom-paint/constructor.html 2018-11-29 21:01:15 UTC (rev 238686)
@@ -0,0 +1,52 @@
+<!DOCTYPE html><!-- webkit-test-runner [ experimental:CSSPaintingAPIEnabled=true ] -->
+<meta name="author" title="Justin Michaud" href=""
+<meta name="assert" content="Test that paint worklets do not crash if the constructor throws">
+<link rel="help" content="https://drafts.css-houdini.org/css-paint-api-1/">
+<script src=""
+
+<script id="code" type="text/worklet">
+ class MyPaint {
+ constructor() {
+ throw "Hello!";
+ }
+
+ paint(ctx, geom) {
+ ctx.fillStyle = "green";
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+ }
+
+ class MyPaint2 {
+ constructor() {
+ }
+
+ paint(ctx, geom) {
+ ctx.fillStyle = "green";
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+ }
+ registerPaint('my-paint', MyPaint);
+ registerPaint('my-paint2', MyPaint2);
+</script>
+
+<script type="text/_javascript_">
+ importWorklet(CSS.paintWorklet, document.getElementById('code').textContent);
+ setTimeout(function() {
+ if (window.internals && window.internals.isAnyWorkletGlobalScopeAlive()) {
+ document.getElementById('leaks').style.background = ""
+ }
+ }, 500);
+</script>
+
+<style>
+ .paint {
+ width: 150px;
+ height: 150px;
+ }
+</style>
+
+<body>
+ <div class="paint" style="background-image: paint(my-paint);"></div>
+ <div class="paint" style="background-image: paint(my-paint2);"></div>
+ <div id="leaks" style="background: red; width: 150px; height: 150px;"></div>
+</body>
Added: trunk/LayoutTests/fast/css-custom-paint/leaks-expected.txt (0 => 238686)
--- trunk/LayoutTests/fast/css-custom-paint/leaks-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/css-custom-paint/leaks-expected.txt 2018-11-29 21:01:15 UTC (rev 238686)
@@ -0,0 +1,10 @@
+Tests that using custom paint does not cause the paint worklet global scope to get leaked.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Worklet global scope did not leak
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/css-custom-paint/leaks.html (0 => 238686)
--- trunk/LayoutTests/fast/css-custom-paint/leaks.html (rev 0)
+++ trunk/LayoutTests/fast/css-custom-paint/leaks.html 2018-11-29 21:01:15 UTC (rev 238686)
@@ -0,0 +1,37 @@
+<!DOCTYPE html><!-- webkit-test-runner [ experimental:CSSPaintingAPIEnabled=true ] -->
+<meta name="author" title="Justin Michaud" href=""
+<meta name="assert" content="Test that paint worklets don't leak">
+<link rel="help" content="https://drafts.css-houdini.org/css-paint-api-1/">
+<script src=""
+
+<iframe id="testFrame" src=""
+
+<script>
+description("Tests that using custom paint does not cause the paint worklet global scope to get leaked.");
+window.jsTestIsAsync = true;
+
+function paintShouldDie()
+{
+ return new Promise(function(resolve, reject) {
+ handle = setInterval(function() {
+ gc();
+ if (!internals.isAnyWorkletGlobalScopeAlive()) {
+ clearInterval(handle);
+ resolve();
+ }
+ }, 10);
+ });
+}
+
+var testFrame = document.getElementById("testFrame");
+testFrame._onload_ = function() {
+ setTimeout(function() {
+ testFrame.remove();
+ paintShouldDie().then(function() {
+ testPassed("Worklet global scope did not leak");
+ finishJSTest();
+ });
+ }, 10);
+}
+</script>
+<script src=""
Modified: trunk/LayoutTests/fast/css-custom-paint/properties.html (238685 => 238686)
--- trunk/LayoutTests/fast/css-custom-paint/properties.html 2018-11-29 20:52:46 UTC (rev 238685)
+++ trunk/LayoutTests/fast/css-custom-paint/properties.html 2018-11-29 21:01:15 UTC (rev 238686)
@@ -21,6 +21,11 @@
class MyPaint {
static get inputProperties() { return ['height', '--my-prop', '--my-registered-prop', "--never-specified"]; }
static get inputArguments() { return ['*', '*', '*']; }
+
+ constructor() { this.myAttribute = 42; }
+
+ testThis() { return this.myAttribute; }
+
paint(ctx, geom, properties, args) {
assert_equals(properties.get('height').toString(), args[0].toString());
assert_equals(properties.get('height').value, 150);
@@ -30,6 +35,8 @@
assert_equals(properties.get('width'), null);
assert_equals(properties.get('--never-specified').toString(), '');
+ assert_equals(this.testThis(), 42);
+
for (var i = 0; i < 6; i++){
for (var j = 0; j < 6; j++){
ctx.fillStyle = 'rgb(' + Math.floor(255 - 42.5 * i) + ',' +
Added: trunk/LayoutTests/fast/css-custom-paint/resources/leaks-frame.html (0 => 238686)
--- trunk/LayoutTests/fast/css-custom-paint/resources/leaks-frame.html (rev 0)
+++ trunk/LayoutTests/fast/css-custom-paint/resources/leaks-frame.html 2018-11-29 21:01:15 UTC (rev 238686)
@@ -0,0 +1,31 @@
+<!DOCTYPE html><!-- webkit-test-runner [ experimental:CSSPaintingAPIEnabled=true ] -->
+<meta name="author" title="Justin Michaud" href=""
+<meta name="assert" content="Test that paint worklets don't leak">
+<link rel="help" content="https://drafts.css-houdini.org/css-paint-api-1/">
+
+<style>
+ .paint {
+ background-image: paint(my-paint);
+ width: 150px;
+ height: 150px;
+ }
+</style>
+
+<div class="paint"></div>
+
+<script id="code" type="text/worklet">
+const globalScope = this;
+class MyPaint {
+ paint(ctx, geom, properties, args) {
+ const dummy = globalScope; // Leak!
+ ctx.fillStyle = "green";
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+}
+MyPaint.createALeak = this;
+registerPaint('my-paint', MyPaint);
+</script>
+
+<script>
+CSS.paintWorklet.addModule(document.getElementById('code').textContent);
+</script>
Added: trunk/LayoutTests/platform/mac/fast/css-custom-paint/raf-leak-expected.txt (0 => 238686)
--- trunk/LayoutTests/platform/mac/fast/css-custom-paint/raf-leak-expected.txt (rev 0)
+++ trunk/LayoutTests/platform/mac/fast/css-custom-paint/raf-leak-expected.txt 2018-11-29 21:01:15 UTC (rev 238686)
@@ -0,0 +1,5 @@
+layer at (0,0) size 800x600
+ RenderView at (0,0) size 800x600
+layer at (0,0) size 800x8
+ RenderBlock {HTML} at (0,0) size 800x8
+ RenderBody {BODY} at (8,8) size 784x0
Modified: trunk/Source/_javascript_Core/ChangeLog (238685 => 238686)
--- trunk/Source/_javascript_Core/ChangeLog 2018-11-29 20:52:46 UTC (rev 238685)
+++ trunk/Source/_javascript_Core/ChangeLog 2018-11-29 21:01:15 UTC (rev 238686)
@@ -1,3 +1,14 @@
+2018-11-29 Justin Michaud <justin_mich...@apple.com>
+
+ CSS Painting API should pass 'this' correctly to paint callback, and repaint when properties change.
+ https://bugs.webkit.org/show_bug.cgi?id=191443
+
+ Reviewed by Dean Jackson.
+
+ Export the simpler construct() method for use in WebCore.
+
+ * runtime/ConstructData.h:
+
2018-11-28 Mark Lam <mark....@apple.com>
ENABLE_SEPARATED_WX_HEAP needs to be defined in Platform.h.
Modified: trunk/Source/_javascript_Core/runtime/ConstructData.h (238685 => 238686)
--- trunk/Source/_javascript_Core/runtime/ConstructData.h 2018-11-29 20:52:46 UTC (rev 238685)
+++ trunk/Source/_javascript_Core/runtime/ConstructData.h 2018-11-29 21:01:15 UTC (rev 238686)
@@ -59,7 +59,7 @@
};
// Convenience wrapper so you don't need to deal with CallData and CallType unless you are going to use them.
-JSObject* construct(ExecState*, JSValue functionObject, const ArgList&, const char* errorMessage);
+JS_EXPORT_PRIVATE JSObject* construct(ExecState*, JSValue functionObject, const ArgList&, const char* errorMessage);
JS_EXPORT_PRIVATE JSObject* construct(ExecState*, JSValue constructor, ConstructType, const ConstructData&, const ArgList&, JSValue newTarget);
ALWAYS_INLINE JSObject* construct(ExecState* exec, JSValue constructorObject, ConstructType constructType, const ConstructData& constructData, const ArgList& args)
Modified: trunk/Source/WebCore/ChangeLog (238685 => 238686)
--- trunk/Source/WebCore/ChangeLog 2018-11-29 20:52:46 UTC (rev 238685)
+++ trunk/Source/WebCore/ChangeLog 2018-11-29 21:01:15 UTC (rev 238686)
@@ -1,3 +1,77 @@
+2018-11-29 Justin Michaud <justin_mich...@apple.com>
+
+ CSS Painting API should pass 'this' correctly to paint callback, and repaint when properties change.
+ https://bugs.webkit.org/show_bug.cgi?id=191443
+
+ Reviewed by Dean Jackson.
+
+ Instantiate a new instance of the paint class, and pass it as 'this' object when the paint callback is called.
+ Also, this patch makes sure that custom paint elements get repainted when properties that they care about get changed.
+ Finally, we fix two reference cycles that caused WorkletGlobalScope to never be destroyed.
+
+ Tests: fast/css-custom-paint/animate-repaint.html
+ fast/css-custom-paint/animate.html
+
+ * bindings/js/JSDOMWrapper.cpp:
+ * bindings/js/JSPaintWorkletGlobalScopeCustom.cpp:
+ (WebCore::JSPaintWorkletGlobalScope::visitAdditionalChildren):
+ * bindings/js/JSWorkletGlobalScopeBase.cpp:
+ (WebCore::toJS):
+ * bindings/js/ScriptState.cpp:
+ (WebCore::execStateFromWorkletGlobalScope):
+ * css/CSSPaintCallback.h:
+ * css/CSSPaintCallback.idl:
+ * css/CSSPaintImageValue.h:
+ * css/StyleResolver.cpp:
+ (WebCore::StyleResolver::applyProperty):
+ * dom/Document.cpp:
+ (WebCore::Document::prepareForDestruction):
+ * dom/ScriptExecutionContext.cpp:
+ (WebCore::ScriptExecutionContext::vm):
+ * platform/graphics/CustomPaintImage.cpp:
+ (WebCore::CustomPaintImage::CustomPaintImage):
+ (WebCore::CustomPaintImage::doCustomPaint):
+ * platform/graphics/CustomPaintImage.h:
+ * rendering/style/RenderStyle.cpp:
+ (WebCore::RenderStyle::addCustomPaintWatchProperty):
+ (WebCore::RenderStyle::changeRequiresRepaint const):
+ * rendering/style/RenderStyle.h:
+ * rendering/style/StyleRareNonInheritedData.cpp:
+ (WebCore::StyleRareNonInheritedData::StyleRareNonInheritedData):
+ (WebCore::StyleRareNonInheritedData::operator== const):
+ * rendering/style/StyleRareNonInheritedData.h:
+ * testing/Internals.cpp:
+ (WebCore::Internals::isAnyWorkletGlobalScopeAlive const):
+ * testing/Internals.h:
+ * testing/Internals.idl:
+ * worklets/PaintWorkletGlobalScope.cpp:
+ (WebCore::PaintWorkletGlobalScope::devicePixelRatio const):
+ (WebCore::PaintWorkletGlobalScope::PaintDefinition::PaintDefinition):
+ (WebCore::PaintWorkletGlobalScope::registerPaint):
+ * worklets/PaintWorkletGlobalScope.h:
+ (WebCore::PaintWorkletGlobalScope::~PaintWorkletGlobalScope):
+ * worklets/WorkletGlobalScope.cpp:
+ (WebCore::WorkletGlobalScope::WorkletGlobalScope):
+ (WebCore::WorkletGlobalScope::~WorkletGlobalScope):
+ (WebCore::WorkletGlobalScope::prepareForDestruction):
+ (WebCore::WorkletGlobalScope::allWorkletGlobalScopesSet):
+ (WebCore::WorkletGlobalScope::isJSExecutionForbidden const):
+ (WebCore::WorkletGlobalScope::logExceptionToConsole):
+ (WebCore::WorkletGlobalScope::addConsoleMessage):
+ (WebCore::WorkletGlobalScope::addMessage):
+ * worklets/WorkletGlobalScope.h:
+ (WebCore::WorkletGlobalScope::script):
+ (WebCore::WorkletGlobalScope::responsibleDocument):
+ (WebCore::WorkletGlobalScope::responsibleDocument const):
+ (WebCore::WorkletGlobalScope::identifier const): Deleted.
+ (WebCore::WorkletGlobalScope::responsableDocument): Deleted.
+ (WebCore::WorkletGlobalScope::responsableDocument const): Deleted.
+ * worklets/WorkletScriptController.cpp:
+ (WebCore::WorkletScriptController::~WorkletScriptController):
+ (WebCore::WorkletScriptController::disableEval):
+ (WebCore::WorkletScriptController::disableWebAssembly):
+ (WebCore::WorkletScriptController::initScript):
+
2018-11-29 Alexey Proskuryakov <a...@apple.com>
Modernize the check for kCFURLRequestContentDecoderSkipURLCheck existence
Modified: trunk/Source/WebCore/bindings/js/JSDOMWrapper.cpp (238685 => 238686)
--- trunk/Source/WebCore/bindings/js/JSDOMWrapper.cpp 2018-11-29 20:52:46 UTC (rev 238685)
+++ trunk/Source/WebCore/bindings/js/JSDOMWrapper.cpp 2018-11-29 21:01:15 UTC (rev 238686)
@@ -35,6 +35,7 @@
#include <_javascript_Core/Error.h>
namespace WebCore {
+using namespace JSC;
STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSDOMObject);
Modified: trunk/Source/WebCore/bindings/js/JSPaintWorkletGlobalScopeCustom.cpp (238685 => 238686)
--- trunk/Source/WebCore/bindings/js/JSPaintWorkletGlobalScopeCustom.cpp 2018-11-29 20:52:46 UTC (rev 238685)
+++ trunk/Source/WebCore/bindings/js/JSPaintWorkletGlobalScopeCustom.cpp 2018-11-29 21:01:15 UTC (rev 238686)
@@ -34,8 +34,10 @@
void JSPaintWorkletGlobalScope::visitAdditionalChildren(JSC::SlotVisitor& visitor)
{
auto locker = holdLock(wrapped().paintDefinitionLock());
- for (auto& registered : wrapped().paintDefinitionMap().values())
+ for (auto& registered : wrapped().paintDefinitionMap().values()) {
registered->paintCallback->visitJSFunction(visitor);
+ visitor.appendUnbarriered(registered->paintConstructor);
+ }
}
}
Modified: trunk/Source/WebCore/bindings/js/JSWorkletGlobalScopeBase.cpp (238685 => 238686)
--- trunk/Source/WebCore/bindings/js/JSWorkletGlobalScopeBase.cpp 2018-11-29 20:52:46 UTC (rev 238685)
+++ trunk/Source/WebCore/bindings/js/JSWorkletGlobalScopeBase.cpp 2018-11-29 21:01:15 UTC (rev 238686)
@@ -128,7 +128,8 @@
JSValue toJS(ExecState*, WorkletGlobalScope& workletGlobalScope)
{
- auto* contextWrapper = workletGlobalScope.script().workletGlobalScopeWrapper();
+ ASSERT(workletGlobalScope.script());
+ auto* contextWrapper = workletGlobalScope.script()->workletGlobalScopeWrapper();
ASSERT(contextWrapper);
return contextWrapper->proxy();
}
Modified: trunk/Source/WebCore/bindings/js/ScriptState.cpp (238685 => 238686)
--- trunk/Source/WebCore/bindings/js/ScriptState.cpp 2018-11-29 20:52:46 UTC (rev 238685)
+++ trunk/Source/WebCore/bindings/js/ScriptState.cpp 2018-11-29 21:01:15 UTC (rev 238686)
@@ -106,7 +106,9 @@
#if ENABLE(CSS_PAINTING_API)
JSC::ExecState* execStateFromWorkletGlobalScope(WorkletGlobalScope& workletGlobalScope)
{
- return workletGlobalScope.script().workletGlobalScopeWrapper()->globalExec();
+ if (!workletGlobalScope.script())
+ return nullptr;
+ return workletGlobalScope.script()->workletGlobalScopeWrapper()->globalExec();
}
#endif
Modified: trunk/Source/WebCore/css/CSSPaintCallback.h (238685 => 238686)
--- trunk/Source/WebCore/css/CSSPaintCallback.h 2018-11-29 20:52:46 UTC (rev 238685)
+++ trunk/Source/WebCore/css/CSSPaintCallback.h 2018-11-29 21:01:15 UTC (rev 238686)
@@ -31,16 +31,18 @@
#include "CSSPaintSize.h"
#include "CallbackResult.h"
#include "StylePropertyMapReadOnly.h"
+#include <_javascript_Core/JSCJSValue.h>
#include <wtf/RefCounted.h>
+#include <wtf/WeakPtr.h>
namespace WebCore {
class PaintRenderingContext2D;
-class CSSPaintCallback : public RefCounted<CSSPaintCallback>, public ActiveDOMCallback {
+class CSSPaintCallback : public RefCounted<CSSPaintCallback>, public CanMakeWeakPtr<CSSPaintCallback>, public ActiveDOMCallback {
public:
using ActiveDOMCallback::ActiveDOMCallback;
- virtual CallbackResult<void> handleEvent(PaintRenderingContext2D&, CSSPaintSize&, StylePropertyMapReadOnly&, const Vector<String>&) = 0;
+ virtual CallbackResult<void> handleEvent(JSC::JSValue, PaintRenderingContext2D&, CSSPaintSize&, StylePropertyMapReadOnly&, const Vector<String>&) = 0;
virtual ~CSSPaintCallback()
{
Modified: trunk/Source/WebCore/css/CSSPaintCallback.idl (238685 => 238686)
--- trunk/Source/WebCore/css/CSSPaintCallback.idl 2018-11-29 20:52:46 UTC (rev 238685)
+++ trunk/Source/WebCore/css/CSSPaintCallback.idl 2018-11-29 21:01:15 UTC (rev 238686)
@@ -26,4 +26,5 @@
[
EnabledAtRuntime=CSSPaintingAPI,
Conditional=CSS_PAINTING_API,
+ CallbackThisObject=any
] callback CSSPaintCallback = void (PaintRenderingContext2D context, CSSPaintSize size, StylePropertyMapReadOnly styleMap, sequence<USVString> arguments);
Modified: trunk/Source/WebCore/css/CSSPaintImageValue.h (238685 => 238686)
--- trunk/Source/WebCore/css/CSSPaintImageValue.h 2018-11-29 20:52:46 UTC (rev 238685)
+++ trunk/Source/WebCore/css/CSSPaintImageValue.h 2018-11-29 21:01:15 UTC (rev 238686)
@@ -40,6 +40,8 @@
return adoptRef(*new CSSPaintImageValue(name, WTFMove(arguments)));
}
+ const String& name() const { return m_name; }
+
RefPtr<Image> image(RenderElement&, const FloatSize&);
bool equals(const CSSPaintImageValue& other) const { return m_name == other.m_name; }
Modified: trunk/Source/WebCore/css/StyleResolver.cpp (238685 => 238686)
--- trunk/Source/WebCore/css/StyleResolver.cpp 2018-11-29 20:52:46 UTC (rev 238685)
+++ trunk/Source/WebCore/css/StyleResolver.cpp 2018-11-29 21:01:15 UTC (rev 238686)
@@ -42,6 +42,7 @@
#include "CSSImageValue.h"
#include "CSSKeyframeRule.h"
#include "CSSKeyframesRule.h"
+#include "CSSPaintImageValue.h"
#include "CSSParser.h"
#include "CSSPrimitiveValueMappings.h"
#include "CSSPropertyNames.h"
@@ -73,6 +74,7 @@
#include "MediaQueryEvaluator.h"
#include "NodeRenderStyle.h"
#include "PageRuleCollector.h"
+#include "PaintWorkletGlobalScope.h"
#include "Pair.h"
#include "RenderScrollbar.h"
#include "RenderStyleConstants.h"
@@ -1717,6 +1719,18 @@
if (isInherit && !CSSProperty::isInheritedProperty(id))
state.style()->setHasExplicitlyInheritedProperties();
+#if ENABLE(CSS_PAINTING_API)
+ if (is<CSSPaintImageValue>(*valueToApply) && document().paintWorkletGlobalScope()) {
+ // FIXME: This should use the "document paint registration map" from the spec, once it is implemented.
+ auto& paintWorklet = *document().paintWorkletGlobalScope();
+ auto locker = holdLock(paintWorklet.paintDefinitionLock());
+ if (auto* registration = paintWorklet.paintDefinitionMap().get(downcast<CSSPaintImageValue>(*valueToApply).name())) {
+ for (auto& property : registration->inputProperties)
+ state.style()->addCustomPaintWatchProperty(property);
+ }
+ }
+#endif
+
// Use the generated StyleBuilder.
StyleBuilder::applyProperty(id, *this, *valueToApply, isInitial, isInherit, customPropertyRegistered);
}
Modified: trunk/Source/WebCore/dom/Document.cpp (238685 => 238686)
--- trunk/Source/WebCore/dom/Document.cpp 2018-11-29 20:52:46 UTC (rev 238685)
+++ trunk/Source/WebCore/dom/Document.cpp 2018-11-29 21:01:15 UTC (rev 238686)
@@ -2531,6 +2531,13 @@
}
#endif
+#if ENABLE(CSS_PAINTING_API)
+ if (m_paintWorkletGlobalScope) {
+ m_paintWorkletGlobalScope->prepareForDestruction();
+ m_paintWorkletGlobalScope = nullptr;
+ }
+#endif
+
m_hasPreparedForDestruction = true;
// Note that m_pageCacheState can be Document::AboutToEnterPageCache if our frame
Modified: trunk/Source/WebCore/dom/ScriptExecutionContext.cpp (238685 => 238686)
--- trunk/Source/WebCore/dom/ScriptExecutionContext.cpp 2018-11-29 20:52:46 UTC (rev 238685)
+++ trunk/Source/WebCore/dom/ScriptExecutionContext.cpp 2018-11-29 21:01:15 UTC (rev 238686)
@@ -482,7 +482,7 @@
return downcast<WorkerGlobalScope>(*this).script()->vm();
#if ENABLE(CSS_PAINTING_API)
if (is<WorkletGlobalScope>(*this))
- return downcast<WorkletGlobalScope>(*this).script().vm();
+ return downcast<WorkletGlobalScope>(*this).script()->vm();
#endif
RELEASE_ASSERT_NOT_REACHED();
Modified: trunk/Source/WebCore/platform/graphics/CustomPaintImage.cpp (238685 => 238686)
--- trunk/Source/WebCore/platform/graphics/CustomPaintImage.cpp 2018-11-29 20:52:46 UTC (rev 238685)
+++ trunk/Source/WebCore/platform/graphics/CustomPaintImage.cpp 2018-11-29 21:01:15 UTC (rev 238686)
@@ -40,11 +40,12 @@
#include "JSCSSPaintCallback.h"
#include "PaintRenderingContext2D.h"
#include "RenderElement.h"
+#include <_javascript_Core/ConstructData.h>
namespace WebCore {
-CustomPaintImage::CustomPaintImage(const PaintWorkletGlobalScope::PaintDefinition& definition, const FloatSize& size, RenderElement& element, const Vector<String>& arguments)
- : m_paintCallback(definition.paintCallback.get())
+CustomPaintImage::CustomPaintImage(PaintWorkletGlobalScope::PaintDefinition& definition, const FloatSize& size, RenderElement& element, const Vector<String>& arguments)
+ : m_paintDefinition(makeWeakPtr(definition))
, m_inputProperties(definition.inputProperties)
, m_element(makeWeakPtr(element))
, m_arguments(arguments)
@@ -56,13 +57,20 @@
ImageDrawResult CustomPaintImage::doCustomPaint(GraphicsContext& destContext, const FloatSize& destSize)
{
- if (!m_element || !m_element->element())
+ if (!m_element || !m_element->element() || !m_paintDefinition)
return ImageDrawResult::DidNothing;
+ JSC::JSValue paintConstructor(m_paintDefinition->paintConstructor);
+
+ if (!paintConstructor)
+ return ImageDrawResult::DidNothing;
+
+ auto& paintCallback = m_paintDefinition->paintCallback.get();
+
ASSERT(!m_element->needsLayout());
ASSERT(!m_element->element()->document().needsStyleRecalc());
- JSCSSPaintCallback& callback = static_cast<JSCSSPaintCallback&>(m_paintCallback.get());
+ JSCSSPaintCallback& callback = static_cast<JSCSSPaintCallback&>(paintCallback);
auto* scriptExecutionContext = callback.scriptExecutionContext();
if (!scriptExecutionContext)
return ImageDrawResult::DidNothing;
@@ -103,7 +111,21 @@
auto size = CSSPaintSize::create(destSize.width(), destSize.height());
auto propertyMap = StylePropertyMapReadOnly::create(WTFMove(propertyValues));
- auto result = m_paintCallback->handleEvent(*context, size, propertyMap, m_arguments);
+ auto& vm = *paintConstructor.getObject()->vm();
+ JSC::JSLockHolder lock(vm);
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ auto& globalObject = *paintConstructor.getObject()->globalObject();
+
+ auto& state = *globalObject.globalExec();
+ JSC::ArgList noArgs;
+ JSC::JSValue thisObject = { JSC::construct(&state, WTFMove(paintConstructor), noArgs, "Failed to construct paint class") };
+
+ if (UNLIKELY(scope.exception())) {
+ reportException(&state, scope.exception());
+ return ImageDrawResult::DidNothing;
+ }
+
+ auto result = paintCallback.handleEvent(WTFMove(thisObject), *context, size, propertyMap, m_arguments);
if (result.type() != CallbackResultType::Success)
return ImageDrawResult::DidNothing;
Modified: trunk/Source/WebCore/platform/graphics/CustomPaintImage.h (238685 => 238686)
--- trunk/Source/WebCore/platform/graphics/CustomPaintImage.h 2018-11-29 20:52:46 UTC (rev 238685)
+++ trunk/Source/WebCore/platform/graphics/CustomPaintImage.h 2018-11-29 21:01:15 UTC (rev 238686)
@@ -29,6 +29,8 @@
#include "GeneratedImage.h"
#include "PaintWorkletGlobalScope.h"
+#include <_javascript_Core/JSObject.h>
+#include <_javascript_Core/Weak.h>
#include <wtf/WeakPtr.h>
namespace WebCore {
@@ -38,7 +40,7 @@
class CustomPaintImage final : public GeneratedImage {
public:
- static Ref<CustomPaintImage> create(const PaintWorkletGlobalScope::PaintDefinition& definition, const FloatSize& size, RenderElement& element, const Vector<String>& arguments)
+ static Ref<CustomPaintImage> create(PaintWorkletGlobalScope::PaintDefinition& definition, const FloatSize& size, RenderElement& element, const Vector<String>& arguments)
{
return adoptRef(*new CustomPaintImage(definition, size, element, arguments));
}
@@ -47,7 +49,7 @@
bool isCustomPaintImage() const override { return true; }
private:
- CustomPaintImage(const PaintWorkletGlobalScope::PaintDefinition&, const FloatSize&, RenderElement&, const Vector<String>& arguments);
+ CustomPaintImage(PaintWorkletGlobalScope::PaintDefinition&, const FloatSize&, RenderElement&, const Vector<String>& arguments);
ImageDrawResult doCustomPaint(GraphicsContext&, const FloatSize&);
@@ -54,7 +56,7 @@
ImageDrawResult draw(GraphicsContext&, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator, BlendMode, DecodingMode, ImageOrientationDescription) final;
void drawPattern(GraphicsContext&, const FloatRect& destRect, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, const FloatSize& spacing, CompositeOperator, BlendMode) final;
- Ref<CSSPaintCallback> m_paintCallback;
+ WeakPtr<PaintWorkletGlobalScope::PaintDefinition> m_paintDefinition;
Vector<String> m_inputProperties;
WeakPtr<RenderElement> m_element;
Vector<String> m_arguments;
Modified: trunk/Source/WebCore/rendering/style/RenderStyle.cpp (238685 => 238686)
--- trunk/Source/WebCore/rendering/style/RenderStyle.cpp 2018-11-29 20:52:46 UTC (rev 238685)
+++ trunk/Source/WebCore/rendering/style/RenderStyle.cpp 2018-11-29 21:01:15 UTC (rev 238686)
@@ -23,10 +23,12 @@
#include "config.h"
#include "RenderStyle.h"
-#include "ContentData.h"
+#include "CSSComputedStyleDeclaration.h"
#include "CSSCustomPropertyValue.h"
#include "CSSParser.h"
#include "CSSPropertyNames.h"
+#include "CSSPropertyParser.h"
+#include "ContentData.h"
#include "CursorList.h"
#include "FloatRoundedRect.h"
#include "FontCascade.h"
@@ -962,6 +964,16 @@
;
}
+#if ENABLE(CSS_PAINTING_API)
+void RenderStyle::addCustomPaintWatchProperty(const String& name)
+{
+ auto& data = ""
+ if (!data.customPaintWatchedProperties)
+ data.customPaintWatchedProperties = std::make_unique<HashSet<String>>();
+ data.customPaintWatchedProperties->add(name);
+}
+#endif
+
bool RenderStyle::changeRequiresRepaint(const RenderStyle& other, OptionSet<StyleDifferenceContextSensitiveProperty>& changedContextSensitiveProperties) const
{
if (!requiresPainting(*this) && !requiresPainting(other))
@@ -983,6 +995,45 @@
&& rareInheritedDataChangeRequiresRepaint(*m_rareInheritedData, *other.m_rareInheritedData))
return true;
+#if ENABLE(CSS_PAINTING_API)
+ auto* propertiesA = m_rareNonInheritedData.ptr()->customPaintWatchedProperties.get();
+ auto* propertiesB = other.m_rareNonInheritedData.ptr()->customPaintWatchedProperties.get();
+
+ if (UNLIKELY(propertiesA || propertiesB)) {
+ // FIXME: We should not need to use ComputedStyleExtractor here.
+ ComputedStyleExtractor extractor((Element*) nullptr);
+
+ for (auto* watchPropertiesMap : { propertiesA, propertiesB }) {
+ if (!watchPropertiesMap)
+ continue;
+
+ for (auto& name : *watchPropertiesMap) {
+ RefPtr<CSSValue> valueA;
+ RefPtr<CSSValue> valueB;
+ if (isCustomPropertyName(name) && getCustomProperty(name) && other.getCustomProperty(name)) {
+ valueA = CSSCustomPropertyValue::create(*getCustomProperty(name));
+ valueB = CSSCustomPropertyValue::create(*other.getCustomProperty(name));
+ } else {
+ CSSPropertyID propertyID = cssPropertyID(name);
+ if (!propertyID)
+ continue;
+ valueA = extractor.valueForPropertyinStyle(*this, propertyID);
+ valueB = extractor.valueForPropertyinStyle(other, propertyID);
+ }
+
+ if ((valueA && !valueB) || (!valueA && valueB))
+ return true;
+
+ if (!valueA)
+ continue;
+
+ if (!(*valueA == *valueB))
+ return true;
+ }
+ }
+ }
+#endif
+
return false;
}
Modified: trunk/Source/WebCore/rendering/style/RenderStyle.h (238685 => 238686)
--- trunk/Source/WebCore/rendering/style/RenderStyle.h 2018-11-29 20:52:46 UTC (rev 238685)
+++ trunk/Source/WebCore/rendering/style/RenderStyle.h 2018-11-29 21:01:15 UTC (rev 238686)
@@ -1267,6 +1267,10 @@
void setApplePayButtonType(ApplePayButtonType type) { SET_VAR(m_rareNonInheritedData, applePayButtonType, static_cast<unsigned>(type)); }
#endif
+#if ENABLE(CSS_PAINTING_API)
+ void addCustomPaintWatchProperty(const String& name);
+#endif
+
// Support for paint-order, stroke-linecap, stroke-linejoin, and stroke-miterlimit from https://drafts.fxtf.org/paint/.
void setPaintOrder(PaintOrder order) { SET_VAR(m_rareInheritedData, paintOrder, static_cast<unsigned>(order)); }
PaintOrder paintOrder() const { return static_cast<PaintOrder>(m_rareInheritedData->paintOrder); }
Modified: trunk/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp (238685 => 238686)
--- trunk/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp 2018-11-29 20:52:46 UTC (rev 238685)
+++ trunk/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp 2018-11-29 21:01:15 UTC (rev 238686)
@@ -169,6 +169,7 @@
, justifyItems(o.justifyItems)
, justifySelf(o.justifySelf)
, customProperties(o.customProperties)
+ , customPaintWatchedProperties(o.customPaintWatchedProperties ? std::make_unique<HashSet<String>>(*o.customPaintWatchedProperties) : nullptr)
#if ENABLE(TOUCH_EVENTS)
, touchAction(o.touchAction)
#endif
@@ -271,6 +272,8 @@
&& justifyItems == o.justifyItems
&& justifySelf == o.justifySelf
&& customProperties == o.customProperties
+ && ((customPaintWatchedProperties && o.customPaintWatchedProperties && *customPaintWatchedProperties == *o.customPaintWatchedProperties)
+ || (!customPaintWatchedProperties && !o.customPaintWatchedProperties))
&& pageSizeType == o.pageSizeType
&& transformStyle3D == o.transformStyle3D
&& backfaceVisibility == o.backfaceVisibility
Modified: trunk/Source/WebCore/rendering/style/StyleRareNonInheritedData.h (238685 => 238686)
--- trunk/Source/WebCore/rendering/style/StyleRareNonInheritedData.h 2018-11-29 20:52:46 UTC (rev 238685)
+++ trunk/Source/WebCore/rendering/style/StyleRareNonInheritedData.h 2018-11-29 21:01:15 UTC (rev 238686)
@@ -172,6 +172,7 @@
StyleSelfAlignmentData justifySelf;
DataRef<StyleCustomPropertyData> customProperties;
+ std::unique_ptr<HashSet<String>> customPaintWatchedProperties;
#if ENABLE(TOUCH_EVENTS)
unsigned touchAction : 1; // TouchAction
Modified: trunk/Source/WebCore/testing/Internals.cpp (238685 => 238686)
--- trunk/Source/WebCore/testing/Internals.cpp 2018-11-29 20:52:46 UTC (rev 238685)
+++ trunk/Source/WebCore/testing/Internals.cpp 2018-11-29 21:01:15 UTC (rev 238686)
@@ -173,6 +173,7 @@
#include "WebCoreJSClientData.h"
#include "WindowProxy.h"
#include "WorkerThread.h"
+#include "WorkletGlobalScope.h"
#include "WritingDirection.h"
#include "XMLHttpRequest.h"
#include <_javascript_Core/CodeBlock.h>
@@ -2387,6 +2388,15 @@
return Document::allDocumentsMap().contains(makeObjectIdentifier<DocumentIdentifierType>(documentIdentifier));
}
+bool Internals::isAnyWorkletGlobalScopeAlive() const
+{
+#if ENABLE(CSS_PAINTING_API)
+ return !WorkletGlobalScope::allWorkletGlobalScopesSet().isEmpty();
+#else
+ return false;
+#endif
+}
+
String Internals::serviceWorkerClientIdentifier(const Document& document) const
{
#if ENABLE(SERVICE_WORKER)
Modified: trunk/Source/WebCore/testing/Internals.h (238685 => 238686)
--- trunk/Source/WebCore/testing/Internals.h 2018-11-29 20:52:46 UTC (rev 238685)
+++ trunk/Source/WebCore/testing/Internals.h 2018-11-29 21:01:15 UTC (rev 238686)
@@ -388,6 +388,8 @@
uint64_t documentIdentifier(const Document&) const;
bool isDocumentAlive(uint64_t documentIdentifier) const;
+ bool isAnyWorkletGlobalScopeAlive() const;
+
String serviceWorkerClientIdentifier(const Document&) const;
RefPtr<WindowProxy> openDummyInspectorFrontend(const String& url);
Modified: trunk/Source/WebCore/testing/Internals.idl (238685 => 238686)
--- trunk/Source/WebCore/testing/Internals.idl 2018-11-29 20:52:46 UTC (rev 238685)
+++ trunk/Source/WebCore/testing/Internals.idl 2018-11-29 21:01:15 UTC (rev 238686)
@@ -675,6 +675,8 @@
unsigned long long documentIdentifier(Document document);
boolean isDocumentAlive(unsigned long long documentIdentifier);
+ boolean isAnyWorkletGlobalScopeAlive();
+
DOMString serviceWorkerClientIdentifier(Document document);
Promise<void> clearCacheStorageMemoryRepresentation();
Modified: trunk/Source/WebCore/worklets/PaintWorkletGlobalScope.cpp (238685 => 238686)
--- trunk/Source/WebCore/worklets/PaintWorkletGlobalScope.cpp 2018-11-29 20:52:46 UTC (rev 238685)
+++ trunk/Source/WebCore/worklets/PaintWorkletGlobalScope.cpp 2018-11-29 21:01:15 UTC (rev 238686)
@@ -33,6 +33,7 @@
#include "JSCSSPaintCallback.h"
#include "JSDOMConvertCallbacks.h"
#include "JSDOMConvertSequences.h"
+#include "RenderView.h"
#include <wtf/SetForScope.h>
namespace WebCore {
@@ -50,15 +51,25 @@
double PaintWorkletGlobalScope::devicePixelRatio() const
{
- if (!responsableDocument() || !responsableDocument()->domWindow())
+ if (!responsibleDocument() || !responsibleDocument()->domWindow())
return 1.0;
- return responsableDocument()->domWindow()->devicePixelRatio();
+ return responsibleDocument()->domWindow()->devicePixelRatio();
}
+PaintWorkletGlobalScope::PaintDefinition::PaintDefinition(const AtomicString& name, JSC::JSObject* paintConstructor, Ref<CSSPaintCallback>&& paintCallback, Vector<String>&& inputProperties, Vector<String>&& inputArguments)
+ : name(name)
+ , paintConstructor(paintConstructor)
+ , paintCallback(WTFMove(paintCallback))
+ , inputProperties(WTFMove(inputProperties))
+ , inputArguments(WTFMove(inputArguments))
+{
+}
+
// https://drafts.css-houdini.org/css-paint-api/#registering-custom-paint
ExceptionOr<void> PaintWorkletGlobalScope::registerPaint(JSC::ExecState& state, JSDOMGlobalObject& globalObject, const String& name, Strong<JSObject> paintConstructor)
{
auto& vm = *paintConstructor->vm();
+ JSC::JSLockHolder lock(vm);
auto scope = DECLARE_THROW_SCOPE(vm);
// Validate that paintConstructor is a VoidFunction
@@ -69,62 +80,70 @@
if (name.isEmpty())
return Exception { TypeError, "The first argument must not be the empty string" };
- auto locker = holdLock(paintDefinitionLock());
+ {
+ auto locker = holdLock(paintDefinitionLock());
- if (paintDefinitionMap().contains(name))
- return Exception { InvalidModificationError, "This name has already been registered" };
+ if (paintDefinitionMap().contains(name))
+ return Exception { InvalidModificationError, "This name has already been registered" };
- Vector<String> inputProperties;
+ Vector<String> inputProperties;
- JSValue inputPropertiesIterableValue = paintConstructor->get(&state, Identifier::fromString(&vm, "inputProperties"));
- RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
+ JSValue inputPropertiesIterableValue = paintConstructor->get(&state, Identifier::fromString(&vm, "inputProperties"));
+ RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
- if (!inputPropertiesIterableValue.isUndefined())
- inputProperties = convert<IDLSequence<IDLDOMString>>(state, inputPropertiesIterableValue);
- RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
+ if (!inputPropertiesIterableValue.isUndefined())
+ inputProperties = convert<IDLSequence<IDLDOMString>>(state, inputPropertiesIterableValue);
+ RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
- // FIXME: Validate input properties here (step 7).
+ // FIXME: Validate input properties here (step 7).
- Vector<String> inputArguments;
+ Vector<String> inputArguments;
- JSValue inputArgumentsIterableValue = paintConstructor->get(&state, Identifier::fromString(&vm, "inputArguments"));
- RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
+ JSValue inputArgumentsIterableValue = paintConstructor->get(&state, Identifier::fromString(&vm, "inputArguments"));
+ RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
- if (!inputArgumentsIterableValue.isUndefined())
- inputArguments = convert<IDLSequence<IDLDOMString>>(state, inputArgumentsIterableValue);
- RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
+ if (!inputArgumentsIterableValue.isUndefined())
+ inputArguments = convert<IDLSequence<IDLDOMString>>(state, inputArgumentsIterableValue);
+ RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
- // FIXME: Parse syntax for inputArguments here (steps 11 and 12).
+ // FIXME: Parse syntax for inputArguments here (steps 11 and 12).
- JSValue contextOptionsValue = paintConstructor->get(&state, Identifier::fromString(&vm, "contextOptions"));
- RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
- UNUSED_PARAM(contextOptionsValue);
+ JSValue contextOptionsValue = paintConstructor->get(&state, Identifier::fromString(&vm, "contextOptions"));
+ RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
+ UNUSED_PARAM(contextOptionsValue);
- // FIXME: Convert to PaintRenderingContext2DSettings here (step 14).
+ // FIXME: Convert to PaintRenderingContext2DSettings here (step 14).
- if (!paintConstructor->isConstructor(vm))
- return Exception { TypeError, "The second argument must be a constructor" };
+ if (!paintConstructor->isConstructor(vm))
+ return Exception { TypeError, "The second argument must be a constructor" };
- JSValue prototypeValue = paintConstructor->get(&state, vm.propertyNames->prototype);
- RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
+ JSValue prototypeValue = paintConstructor->get(&state, vm.propertyNames->prototype);
+ RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
- if (!prototypeValue.isObject())
- return Exception { TypeError, "The second argument must have a prototype that is an object" };
+ if (!prototypeValue.isObject())
+ return Exception { TypeError, "The second argument must have a prototype that is an object" };
- JSValue paintValue = prototypeValue.get(&state, Identifier::fromString(&vm, "paint"));
- RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
+ JSValue paintValue = prototypeValue.get(&state, Identifier::fromString(&vm, "paint"));
+ RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
- if (paintValue.isUndefined())
- return Exception { TypeError, "The class must have a paint method" };
+ if (paintValue.isUndefined())
+ return Exception { TypeError, "The class must have a paint method" };
- RefPtr<JSCSSPaintCallback> paint = convert<IDLCallbackFunction<JSCSSPaintCallback>>(state, paintValue, globalObject);
- RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
+ RefPtr<JSCSSPaintCallback> paint = convert<IDLCallbackFunction<JSCSSPaintCallback>>(state, paintValue, globalObject);
+ RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
- auto paintDefinition = std::unique_ptr<PaintDefinition>(new PaintDefinition { name, paint.releaseNonNull(), inputProperties, inputArguments });
- paintDefinitionMap().add(name, WTFMove(paintDefinition));
+ auto paintDefinition = std::make_unique<PaintDefinition>(name, paintConstructor.get(), paint.releaseNonNull(), WTFMove(inputProperties), WTFMove(inputArguments));
+ paintDefinitionMap().add(name, WTFMove(paintDefinition));
+ }
+ // This is for the case when we have already visited the paint definition map, and the GC is currently running in the background.
+ vm.heap.writeBarrier(&globalObject);
+
// FIXME: construct documentDefinition (step 22).
+ if (responsibleDocument() && responsibleDocument()->renderView())
+ responsibleDocument()->renderView()->repaintRootContents();
+
return { };
}
Modified: trunk/Source/WebCore/worklets/PaintWorkletGlobalScope.h (238685 => 238686)
--- trunk/Source/WebCore/worklets/PaintWorkletGlobalScope.h 2018-11-29 20:52:46 UTC (rev 238685)
+++ trunk/Source/WebCore/worklets/PaintWorkletGlobalScope.h 2018-11-29 21:01:15 UTC (rev 238686)
@@ -29,6 +29,7 @@
#include "CSSPaintCallback.h"
#include "WorkletGlobalScope.h"
+#include <_javascript_Core/JSObject.h>
#include <_javascript_Core/Strong.h>
namespace JSC {
@@ -45,8 +46,12 @@
ExceptionOr<void> registerPaint(JSC::ExecState&, JSDOMGlobalObject&, const String& name, JSC::Strong<JSC::JSObject> paintConstructor);
double devicePixelRatio() const;
- struct PaintDefinition {
+ struct PaintDefinition : public CanMakeWeakPtr<PaintDefinition> {
+ PaintDefinition(const AtomicString& name, JSC::JSObject* paintConstructor, Ref<CSSPaintCallback>&&, Vector<String>&& inputProperties, Vector<String>&& inputArguments);
+
const AtomicString name;
+ // This map must be cleared before the vm is destroyed!
+ JSC::JSObject* paintConstructor { nullptr };
const Ref<CSSPaintCallback> paintCallback;
const Vector<String> inputProperties;
const Vector<String> inputArguments;
@@ -55,9 +60,26 @@
HashMap<String, std::unique_ptr<PaintDefinition>>& paintDefinitionMap() { ASSERT(m_paintDefinitionLock.isLocked()); return m_paintDefinitionMap; }
Lock& paintDefinitionLock() { return m_paintDefinitionLock; }
+ void prepareForDestruction() final
+ {
+ {
+ auto locker = holdLock(paintDefinitionLock());
+ paintDefinitionMap().clear();
+ }
+ WorkletGlobalScope::prepareForDestruction();
+ }
+
private:
PaintWorkletGlobalScope(Document&, ScriptSourceCode&&);
+ ~PaintWorkletGlobalScope()
+ {
+#if !ASSERT_DISABLED
+ auto locker = holdLock(paintDefinitionLock());
+ ASSERT(paintDefinitionMap().isEmpty());
+#endif
+ }
+
bool isPaintWorkletGlobalScope() const final { return true; }
HashMap<String, std::unique_ptr<PaintDefinition>> m_paintDefinitionMap;
Modified: trunk/Source/WebCore/worklets/WorkletGlobalScope.cpp (238685 => 238686)
--- trunk/Source/WebCore/worklets/WorkletGlobalScope.cpp 2018-11-29 20:52:46 UTC (rev 238685)
+++ trunk/Source/WebCore/worklets/WorkletGlobalScope.cpp 2018-11-29 21:01:15 UTC (rev 238686)
@@ -39,7 +39,6 @@
#include "WorkletScriptController.h"
#include <_javascript_Core/Exception.h>
-#include <_javascript_Core/IdentifiersFactory.h>
#include <_javascript_Core/JSLock.h>
#include <_javascript_Core/ScriptCallStack.h>
@@ -49,12 +48,14 @@
WorkletGlobalScope::WorkletGlobalScope(Document& document, ScriptSourceCode&& code)
: m_document(makeWeakPtr(document))
, m_sessionID(m_document->sessionID())
- , m_script(makeUniqueRef<WorkletScriptController>(this))
+ , m_script(std::make_unique<WorkletScriptController>(this))
, m_topOrigin(SecurityOrigin::createUnique())
- , m_identifier(makeString("WorkletGlobalScope:"_s, Inspector::IdentifiersFactory::createIdentifier()))
, m_eventQueue(*this)
, m_code(WTFMove(code))
{
+ auto addResult = allWorkletGlobalScopesSet().add(this);
+ ASSERT_UNUSED(addResult, addResult);
+
auto* frame = document.frame();
m_jsRuntimeFlags = frame ? frame->settings()._javascript_RuntimeFlags() : JSC::RuntimeFlags();
ASSERT(document.page());
@@ -65,10 +66,28 @@
WorkletGlobalScope::~WorkletGlobalScope()
{
+ ASSERT(!m_script);
removeFromContextsMap();
- m_script->workletGlobalScopeWrapper()->setConsoleClient(nullptr);
+ auto removeResult = allWorkletGlobalScopesSet().remove(this);
+ ASSERT_UNUSED(removeResult, removeResult);
}
+void WorkletGlobalScope::prepareForDestruction()
+{
+ ASSERT(m_script);
+ stopActiveDOMObjects();
+ removeRejectedPromiseTracker();
+ removeAllEventListeners();
+ m_script->vm().notifyNeedTermination();
+ m_script = nullptr;
+}
+
+auto WorkletGlobalScope::allWorkletGlobalScopesSet() -> WorkletGlobalScopesSet&
+{
+ static NeverDestroyed<WorkletGlobalScopesSet> scopes;
+ return scopes;
+}
+
String WorkletGlobalScope::origin() const
{
return m_topOrigin->toString();
@@ -88,7 +107,7 @@
bool WorkletGlobalScope::isJSExecutionForbidden() const
{
- return m_script->isExecutionForbidden();
+ return !m_script || m_script->isExecutionForbidden();
}
void WorkletGlobalScope::disableEval(const String& errorMessage)
@@ -110,7 +129,7 @@
void WorkletGlobalScope::logExceptionToConsole(const String& errorMessage, const String& sourceURL, int lineNumber, int columnNumber, RefPtr<ScriptCallStack>&& stack)
{
- if (!m_document)
+ if (!m_document || isJSExecutionForbidden())
return;
m_document->logExceptionToConsole(errorMessage, sourceURL, lineNumber, columnNumber, WTFMove(stack));
}
@@ -117,23 +136,23 @@
void WorkletGlobalScope::addConsoleMessage(std::unique_ptr<Inspector::ConsoleMessage>&& message)
{
- if (!m_document)
+ if (!m_document || isJSExecutionForbidden() || !message)
return;
- m_document->addConsoleMessage(WTFMove(message));
+ m_document->addConsoleMessage(std::make_unique<Inspector::ConsoleMessage>(message->source(), message->type(), message->level(), message->message(), 0));
}
void WorkletGlobalScope::addConsoleMessage(MessageSource source, MessageLevel level, const String& message, unsigned long requestIdentifier)
{
- if (!m_document)
+ if (!m_document || isJSExecutionForbidden())
return;
m_document->addConsoleMessage(source, level, message, requestIdentifier);
}
-void WorkletGlobalScope::addMessage(MessageSource source, MessageLevel level, const String& messageText, const String& sourceURL, unsigned lineNumber, unsigned columnNumber, RefPtr<ScriptCallStack>&& callStack, JSC::ExecState* state, unsigned long requestIdentifier)
+void WorkletGlobalScope::addMessage(MessageSource source, MessageLevel level, const String& messageText, const String& sourceURL, unsigned lineNumber, unsigned columnNumber, RefPtr<ScriptCallStack>&& callStack, JSC::ExecState*, unsigned long requestIdentifier)
{
- if (!m_document)
+ if (!m_document || isJSExecutionForbidden())
return;
- m_document->addMessage(source, level, messageText, sourceURL, lineNumber, columnNumber, WTFMove(callStack), state, requestIdentifier);
+ m_document->addMessage(source, level, messageText, sourceURL, lineNumber, columnNumber, WTFMove(callStack), nullptr, requestIdentifier);
}
} // namespace WebCore
Modified: trunk/Source/WebCore/worklets/WorkletGlobalScope.h (238685 => 238686)
--- trunk/Source/WebCore/worklets/WorkletGlobalScope.h 2018-11-29 20:52:46 UTC (rev 238685)
+++ trunk/Source/WebCore/worklets/WorkletGlobalScope.h 2018-11-29 21:01:15 UTC (rev 238686)
@@ -38,7 +38,7 @@
#include <_javascript_Core/ConsoleMessage.h>
#include <_javascript_Core/RuntimeFlags.h>
#include <pal/SessionID.h>
-#include <wtf/UniqueRef.h>
+#include <wtf/ObjectIdentifier.h>
#include <wtf/WeakPtr.h>
namespace WebCore {
@@ -45,15 +45,20 @@
class WorkletScriptController;
class ScriptSourceCode;
+enum WorkletGlobalScopeIdentifierType { };
+using WorkletGlobalScopeIdentifier = ObjectIdentifier<WorkletGlobalScopeIdentifierType>;
+
class WorkletGlobalScope : public RefCounted<WorkletGlobalScope>, public ScriptExecutionContext, public EventTargetWithInlineData {
public:
- ~WorkletGlobalScope();
+ virtual ~WorkletGlobalScope();
+ using WorkletGlobalScopesSet = HashSet<const WorkletGlobalScope*>;
+ WEBCORE_EXPORT static WorkletGlobalScopesSet& allWorkletGlobalScopesSet();
+
virtual bool isPaintWorkletGlobalScope() const { return false; }
const URL& url() const final { return m_code.url(); }
String origin() const final;
- const String& identifier() const { return m_identifier; }
void evaluate();
@@ -60,7 +65,7 @@
using RefCounted::ref;
using RefCounted::deref;
- WorkletScriptController& script() { return m_script.get(); }
+ WorkletScriptController* script() { return m_script.get(); }
void addConsoleMessage(std::unique_ptr<Inspector::ConsoleMessage>&&) final;
@@ -74,11 +79,15 @@
JSC::RuntimeFlags jsRuntimeFlags() const { return m_jsRuntimeFlags; }
+ virtual void prepareForDestruction();
+
protected:
WorkletGlobalScope(Document&, ScriptSourceCode&&);
+ WorkletGlobalScope(const WorkletGlobalScope&) = delete;
+ WorkletGlobalScope(WorkletGlobalScope&&) = delete;
- Document* responsableDocument() { return m_document.get(); }
- const Document* responsableDocument() const { return m_document.get(); }
+ Document* responsibleDocument() { return m_document.get(); }
+ const Document* responsibleDocument() const { return m_document.get(); }
private:
#if ENABLE(INDEXED_DATABASE)
@@ -118,10 +127,9 @@
WeakPtr<Document> m_document;
PAL::SessionID m_sessionID;
- UniqueRef<WorkletScriptController> m_script;
+ std::unique_ptr<WorkletScriptController> m_script;
Ref<SecurityOrigin> m_topOrigin;
- String m_identifier;
// FIXME: This is not implemented properly, it just satisfies the compiler.
// https://bugs.webkit.org/show_bug.cgi?id=191136
Modified: trunk/Source/WebCore/worklets/WorkletScriptController.cpp (238685 => 238686)
--- trunk/Source/WebCore/worklets/WorkletScriptController.cpp 2018-11-29 20:52:46 UTC (rev 238685)
+++ trunk/Source/WebCore/worklets/WorkletScriptController.cpp 2018-11-29 21:01:15 UTC (rev 238686)
@@ -59,13 +59,15 @@
WorkletScriptController::~WorkletScriptController()
{
JSLockHolder lock(vm());
- m_workletGlobalScopeWrapper.clear();
- m_vm = nullptr;
+ forbidExecution();
+
if (m_workletGlobalScopeWrapper) {
m_workletGlobalScopeWrapper->clearDOMGuardedObjects();
m_workletGlobalScopeWrapper->setConsoleClient(nullptr);
m_consoleClient = nullptr;
}
+ m_workletGlobalScopeWrapper.clear();
+ m_vm = nullptr;
}
void WorkletScriptController::forbidExecution()
@@ -82,6 +84,9 @@
void WorkletScriptController::disableEval(const String& errorMessage)
{
+ if (isExecutionForbidden())
+ return;
+
initScriptIfNeeded();
JSLockHolder lock { vm() };
@@ -90,6 +95,9 @@
void WorkletScriptController::disableWebAssembly(const String& errorMessage)
{
+ if (isExecutionForbidden())
+ return;
+
initScriptIfNeeded();
JSLockHolder lock { vm() };
@@ -132,6 +140,9 @@
void WorkletScriptController::initScript()
{
+ if (isExecutionForbidden())
+ return;
+
if (is<PaintWorkletGlobalScope>(m_workletGlobalScope)) {
initScriptWithSubclass<JSPaintWorkletGlobalScopePrototype, JSPaintWorkletGlobalScope, PaintWorkletGlobalScope>();
return;