PaintWorkletGlobalScope.cpp [plain text]
#include "config.h"
#include "PaintWorkletGlobalScope.h"
#if ENABLE(CSS_PAINTING_API)
#include "DOMWindow.h"
#include "Document.h"
#include "JSCSSPaintCallback.h"
#include "JSDOMConvert.h"
#include "RenderView.h"
#include <wtf/IsoMallocInlines.h>
#include <wtf/SetForScope.h>
namespace WebCore {
using namespace JSC;
WTF_MAKE_ISO_ALLOCATED_IMPL(PaintWorkletGlobalScope);
Ref<PaintWorkletGlobalScope> PaintWorkletGlobalScope::create(Document& document, ScriptSourceCode&& code)
{
return adoptRef(*new PaintWorkletGlobalScope(document, WTFMove(code)));
}
PaintWorkletGlobalScope::PaintWorkletGlobalScope(Document& document, ScriptSourceCode&& code)
: WorkletGlobalScope(document, WTFMove(code))
{
}
double PaintWorkletGlobalScope::devicePixelRatio() const
{
if (!responsibleDocument() || !responsibleDocument()->domWindow())
return 1.0;
return responsibleDocument()->domWindow()->devicePixelRatio();
}
PaintWorkletGlobalScope::PaintDefinition::PaintDefinition(const AtomString& 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))
{
}
ExceptionOr<void> PaintWorkletGlobalScope::registerPaint(JSC::JSGlobalObject& globalObject, const String& name, Strong<JSObject> paintConstructor)
{
auto& vm = paintConstructor->vm();
JSC::JSLockHolder lock(vm);
auto scope = DECLARE_THROW_SCOPE(vm);
CallData callData;
if (JSC::getCallData(vm, paintConstructor.get(), callData) == JSC::CallType::None)
return Exception { TypeError, "paintConstructor must be callable" };
if (name.isEmpty())
return Exception { TypeError, "The first argument must not be the empty string" };
{
auto locker = holdLock(paintDefinitionLock());
if (paintDefinitionMap().contains(name))
return Exception { InvalidModificationError, "This name has already been registered" };
Vector<String> inputProperties;
JSValue inputPropertiesIterableValue = paintConstructor->get(&globalObject, Identifier::fromString(vm, "inputProperties"));
RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
if (!inputPropertiesIterableValue.isUndefined())
inputProperties = convert<IDLSequence<IDLDOMString>>(globalObject, inputPropertiesIterableValue);
RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
Vector<String> inputArguments;
JSValue inputArgumentsIterableValue = paintConstructor->get(&globalObject, Identifier::fromString(vm, "inputArguments"));
RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
if (!inputArgumentsIterableValue.isUndefined())
inputArguments = convert<IDLSequence<IDLDOMString>>(globalObject, inputArgumentsIterableValue);
RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
JSValue contextOptionsValue = paintConstructor->get(&globalObject, Identifier::fromString(vm, "contextOptions"));
RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
UNUSED_PARAM(contextOptionsValue);
if (!paintConstructor->isConstructor(vm))
return Exception { TypeError, "The second argument must be a constructor" };
JSValue prototypeValue = paintConstructor->get(&globalObject, 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" };
JSValue paintValue = prototypeValue.get(&globalObject, Identifier::fromString(vm, "paint"));
RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
if (paintValue.isUndefined())
return Exception { TypeError, "The class must have a paint method" };
RefPtr<JSCSSPaintCallback> paint = convert<IDLCallbackFunction<JSCSSPaintCallback>>(globalObject, paintValue, *jsCast<JSDOMGlobalObject*>(&globalObject));
RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
auto paintDefinition = makeUnique<PaintDefinition>(name, paintConstructor.get(), paint.releaseNonNull(), WTFMove(inputProperties), WTFMove(inputArguments));
paintDefinitionMap().add(name, WTFMove(paintDefinition));
}
vm.heap.writeBarrier(&globalObject);
if (responsibleDocument() && responsibleDocument()->renderView())
responsibleDocument()->renderView()->repaintRootContents();
return { };
}
}
#endif