Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
8252381: Cherry pick GTK WebKit 2.28.4 changes
Reviewed-by: kcr, bchoudhary
  • Loading branch information
arun-joseph committed Aug 28, 2020
1 parent c86bd35 commit 88c0f97
Show file tree
Hide file tree
Showing 21 changed files with 158 additions and 51 deletions.
Expand Up @@ -48,6 +48,13 @@ function initializeReadableStream(underlyingSource, strategy)
// Initialized with null value to enable distinction with undefined case.
@putByIdDirectPrivate(this, "readableStreamController", null);

// FIXME: We should introduce https://streams.spec.whatwg.org/#create-readable-stream.
// For now, we emulate this with underlyingSource with private properties.
if (@getByIdDirectPrivate(underlyingSource, "pull") !== @undefined) {
@setupReadableStreamDefaultController(this, underlyingSource, @undefined, 1, @getByIdDirectPrivate(underlyingSource, "start"), @getByIdDirectPrivate(underlyingSource, "pull"), @getByIdDirectPrivate(underlyingSource, "cancel"));
return this;
}

const type = underlyingSource.type;
const typeString = @toString(type);

Expand All @@ -65,7 +72,8 @@ function initializeReadableStream(underlyingSource, strategy)
} else if (type === @undefined) {
if (strategy.highWaterMark === @undefined)
strategy.highWaterMark = 1;
@putByIdDirectPrivate(this, "readableStreamController", new @ReadableStreamDefaultController(this, underlyingSource, strategy.size, strategy.highWaterMark, @isReadableStream));

@setupReadableStreamDefaultController(this, underlyingSource, strategy.size, strategy.highWaterMark, underlyingSource.start, underlyingSource.pull, underlyingSource.cancel);
} else
@throwRangeError("Invalid type for underlying source");

Expand Down
Expand Up @@ -63,21 +63,33 @@ function privateInitializeReadableStreamDefaultController(stream, underlyingSour
@putByIdDirectPrivate(this, "pulling", false);
@putByIdDirectPrivate(this, "strategy", @validateAndNormalizeQueuingStrategy(size, highWaterMark));

const controller = this;
@promiseInvokeOrNoopNoCatch(underlyingSource, "start", [this]).@then(() => {
return this;
}

// https://streams.spec.whatwg.org/#set-up-readable-stream-default-controller, starting from step 6.
// The other part is implemented in privateInitializeReadableStreamDefaultController.
function setupReadableStreamDefaultController(stream, underlyingSource, size, highWaterMark, startMethod, pullMethod, cancelMethod)
{
"use strict";
const controller = new @ReadableStreamDefaultController(stream, underlyingSource, size, highWaterMark, @isReadableStream);
const startAlgorithm = () => @promiseInvokeOrNoopMethodNoCatch(underlyingSource, startMethod, [controller]);
const pullAlgorithm = () => @promiseInvokeOrNoopMethod(underlyingSource, pullMethod, [controller]);
const cancelAlgorithm = (reason) => @promiseInvokeOrNoopMethod(underlyingSource, cancelMethod, [reason]);

@putByIdDirectPrivate(controller, "pullAlgorithm", pullAlgorithm);
@putByIdDirectPrivate(controller, "cancelAlgorithm", cancelAlgorithm);
@putByIdDirectPrivate(controller, "pull", @readableStreamDefaultControllerPull);
@putByIdDirectPrivate(controller, "cancel", @readableStreamDefaultControllerCancel);
@putByIdDirectPrivate(stream, "readableStreamController", controller);

startAlgorithm().@then(() => {
@putByIdDirectPrivate(controller, "started", true);
@assert(!@getByIdDirectPrivate(controller, "pulling"));
@assert(!@getByIdDirectPrivate(controller, "pullAgain"));
@readableStreamDefaultControllerCallPullIfNeeded(controller);
}, (error) => {
@readableStreamDefaultControllerError(controller, error);
});

@putByIdDirectPrivate(this, "cancel", @readableStreamDefaultControllerCancel);

@putByIdDirectPrivate(this, "pull", @readableStreamDefaultControllerPull);

return this;
}

function readableStreamDefaultControllerError(controller, error)
Expand Down Expand Up @@ -137,18 +149,20 @@ function readableStreamTee(stream, shouldClone)
reason2: @undefined,
};

teeState.cancelPromiseCapability = @newPromiseCapability(@InternalPromise);
teeState.cancelPromiseCapability = @newPromiseCapability(@Promise);

const pullFunction = @readableStreamTeePullFunction(teeState, reader, shouldClone);

const branch1 = new @ReadableStream({
"pull": pullFunction,
"cancel": @readableStreamTeeBranch1CancelFunction(teeState, stream)
});
const branch2 = new @ReadableStream({
"pull": pullFunction,
"cancel": @readableStreamTeeBranch2CancelFunction(teeState, stream)
});
const branch1Source = { };
@putByIdDirectPrivate(branch1Source, "pull", pullFunction);
@putByIdDirectPrivate(branch1Source, "cancel", @readableStreamTeeBranch1CancelFunction(teeState, stream));

const branch2Source = { };
@putByIdDirectPrivate(branch2Source, "pull", pullFunction);
@putByIdDirectPrivate(branch2Source, "cancel", @readableStreamTeeBranch2CancelFunction(teeState, stream));

const branch1 = new @ReadableStream(branch1Source);
const branch2 = new @ReadableStream(branch2Source);

@getByIdDirectPrivate(reader, "closedPromiseCapability").@promise.@then(@undefined, function(e) {
if (teeState.closedOrErrored)
Expand Down Expand Up @@ -322,7 +336,7 @@ function readableStreamDefaultControllerCallPullIfNeeded(controller)
@assert(!@getByIdDirectPrivate(controller, "pullAgain"));
@putByIdDirectPrivate(controller, "pulling", true);

@promiseInvokeOrNoop(@getByIdDirectPrivate(controller, "underlyingSource"), "pull", [controller]).@then(function() {
@getByIdDirectPrivate(controller, "pullAlgorithm").@call(@undefined).@then(function() {
@putByIdDirectPrivate(controller, "pulling", false);
if (@getByIdDirectPrivate(controller, "pullAgain")) {
@putByIdDirectPrivate(controller, "pullAgain", false);
Expand Down Expand Up @@ -385,7 +399,7 @@ function readableStreamDefaultControllerCancel(controller, reason)
"use strict";

@putByIdDirectPrivate(controller, "queue", @newQueue());
return @promiseInvokeOrNoop(@getByIdDirectPrivate(controller, "underlyingSource"), "cancel", [reason]);
return @getByIdDirectPrivate(controller, "cancelAlgorithm").@call(@undefined, reason);
}

function readableStreamDefaultControllerPull(controller)
Expand Down
Expand Up @@ -36,16 +36,34 @@ function shieldingPromiseResolve(result)
return promise;
}

function promiseInvokeOrNoopNoCatch(object, key, args)
function promiseInvokeOrNoopMethodNoCatch(object, method, args)
{
"use strict";

const method = object[key];
if (method === @undefined)
return @Promise.@resolve();
return @shieldingPromiseResolve(method.@apply(object, args));
}

function promiseInvokeOrNoopNoCatch(object, key, args)
{
"use strict";

return @promiseInvokeOrNoopMethodNoCatch(object, object[key], args);
}

function promiseInvokeOrNoopMethod(object, method, args)
{
"use strict";

try {
return @promiseInvokeOrNoopMethodNoCatch(object, method, args);
}
catch(error) {
return @Promise.@reject(error);
}
}

function promiseInvokeOrNoop(object, key, args)
{
"use strict";
Expand All @@ -56,7 +74,6 @@ function promiseInvokeOrNoop(object, key, args)
catch(error) {
return @Promise.@reject(error);
}

}

function promiseInvokeOrFallbackOrNoop(object, key1, args1, key2, args2)
Expand Down
Expand Up @@ -142,7 +142,7 @@ Vector<RefPtr<WebAnimation>> DocumentTimeline::getAnimations() const
Vector<RefPtr<WebAnimation>> webAnimations;

// First, let's get all qualifying animations in their right group.
for (const auto& animation : m_allAnimations) {
for (const auto& animation : m_animations) {
if (!animation || !animation->isRelevant() || animation->timeline() != this || !is<KeyframeEffect>(animation->effect()))
continue;

Expand All @@ -151,15 +151,15 @@ Vector<RefPtr<WebAnimation>> DocumentTimeline::getAnimations() const
continue;

if (is<CSSTransition>(animation.get()) && downcast<CSSTransition>(animation.get())->owningElement())
cssTransitions.append(animation.get());
cssTransitions.append(animation);
else if (is<CSSAnimation>(animation.get()) && downcast<CSSAnimation>(animation.get())->owningElement())
cssAnimations.append(animation.get());
cssAnimations.append(animation);
else
webAnimations.append(animation.get());
webAnimations.append(animation);
}

// Now sort CSS Transitions by their composite order.
std::sort(cssTransitions.begin(), cssTransitions.end(), [](auto& lhs, auto& rhs) {
std::stable_sort(cssTransitions.begin(), cssTransitions.end(), [](auto& lhs, auto& rhs) {
// https://drafts.csswg.org/css-transitions-2/#animation-composite-order
auto* lhsTransition = downcast<CSSTransition>(lhs.get());
auto* rhsTransition = downcast<CSSTransition>(rhs.get());
Expand All @@ -181,7 +181,7 @@ Vector<RefPtr<WebAnimation>> DocumentTimeline::getAnimations() const
});

// Now sort CSS Animations by their composite order.
std::sort(cssAnimations.begin(), cssAnimations.end(), [](auto& lhs, auto& rhs) {
std::stable_sort(cssAnimations.begin(), cssAnimations.end(), [](auto& lhs, auto& rhs) {
// https://drafts.csswg.org/css-animations-2/#animation-composite-order
auto* lhsOwningElement = downcast<CSSAnimation>(lhs.get())->owningElement();
auto* rhsOwningElement = downcast<CSSAnimation>(rhs.get())->owningElement();
Expand All @@ -194,7 +194,7 @@ Vector<RefPtr<WebAnimation>> DocumentTimeline::getAnimations() const
return compareAnimationsByCompositeOrder(*lhs, *rhs, lhsOwningElement->ensureKeyframeEffectStack().cssAnimationList());
});

std::sort(webAnimations.begin(), webAnimations.end(), [](auto& lhs, auto& rhs) {
std::stable_sort(webAnimations.begin(), webAnimations.end(), [](auto& lhs, auto& rhs) {
return lhs->globalPosition() < rhs->globalPosition();
});

Expand Down
Expand Up @@ -80,7 +80,7 @@ void KeyframeEffectStack::ensureEffectsAreSorted()
if (m_isSorted || m_effects.size() < 2)
return;

std::sort(m_effects.begin(), m_effects.end(), [&](auto& lhs, auto& rhs) {
std::stable_sort(m_effects.begin(), m_effects.end(), [&](auto& lhs, auto& rhs) {
auto* lhsAnimation = lhs->animation();
auto* rhsAnimation = rhs->animation();

Expand Down
Expand Up @@ -37,6 +37,11 @@ namespace WebCore {

bool compareAnimationsByCompositeOrder(WebAnimation& lhsAnimation, WebAnimation& rhsAnimation, const AnimationList* cssAnimationList)
{
// We should not ever be calling this function with two WebAnimation objects that are the same. If that were the case,
// then comparing objects of this kind would yield inconsistent results when comparing A == B and B == A. As such,
// this function should be called with std::stable_sort().
RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(&lhsAnimation != &rhsAnimation);

bool lhsHasOwningElement = is<DeclarativeAnimation>(lhsAnimation) && downcast<DeclarativeAnimation>(lhsAnimation).owningElement();
bool rhsHasOwningElement = is<DeclarativeAnimation>(rhsAnimation) && downcast<DeclarativeAnimation>(rhsAnimation).owningElement();

Expand Down
Expand Up @@ -245,6 +245,7 @@ namespace WebCore {
macro(byobRequest) \
macro(caches) \
macro(cancel) \
macro(cancelAlgorithm) \
macro(cancelIdleCallback) \
macro(cloneArrayBuffer) \
macro(close) \
Expand Down Expand Up @@ -307,6 +308,7 @@ namespace WebCore {
macro(privateGetStats) \
macro(pull) \
macro(pullAgain) \
macro(pullAlgorithm) \
macro(pulling) \
macro(queue) \
macro(queuedAddIceCandidate) \
Expand All @@ -329,6 +331,7 @@ namespace WebCore {
macro(setBodyFromInputRequest) \
macro(setStatus) \
macro(showModalDialog) \
macro(start) \
macro(startConsumingStream) \
macro(started) \
macro(startedPromise) \
Expand Down
Expand Up @@ -751,6 +751,10 @@ String StyleProperties::pageBreakPropertyValue(const StylePropertyShorthand& sho
// FIXME: Remove this isGlobalKeyword check after we do this consistently for all shorthands in getPropertyValue.
if (value->isGlobalKeyword())
return value->cssText();

if (!is<CSSPrimitiveValue>(*value))
return String();

CSSValueID valueId = downcast<CSSPrimitiveValue>(*value).valueID();
switch (valueId) {
case CSSValuePage:
Expand Down
13 changes: 13 additions & 0 deletions modules/javafx.web/src/main/native/Source/WebCore/dom/Document.cpp
Expand Up @@ -4660,6 +4660,19 @@ void Document::nodeWillBeRemoved(Node& node)
m_markers->removeMarkers(node);
}

void Document::parentlessNodeMovedToNewDocument(Node& node)
{
Vector<Range*, 5> rangesAffected;

for (auto* range : m_ranges) {
if (range->parentlessNodeMovedToNewDocumentAffectsRange(node))
rangesAffected.append(range);
}

for (auto* range : rangesAffected)
range->updateRangeForParentlessNodeMovedToNewDocument(node);
}

static Node* fallbackFocusNavigationStartingNodeAfterRemoval(Node& node)
{
return node.previousSibling() ? node.previousSibling() : node.parentNode();
Expand Down
Expand Up @@ -815,6 +815,7 @@ class Document
void nodeChildrenWillBeRemoved(ContainerNode&);
// nodeWillBeRemoved is only safe when removing one node at a time.
void nodeWillBeRemoved(Node&);
void parentlessNodeMovedToNewDocument(Node&);

enum class AcceptChildOperation { Replace, InsertOrAdd };
bool canAcceptChild(const Node& newChild, const Node* refChild, AcceptChildOperation) const;
Expand Down
Expand Up @@ -2050,6 +2050,9 @@ void Node::moveNodeToNewDocument(Document& oldDocument, Document& newDocument)

oldDocument.moveNodeIteratorsToNewDocument(*this, newDocument);

if (!parentNode())
oldDocument.parentlessNodeMovedToNewDocument(*this);

if (AXObjectCache::accessibilityEnabled()) {
if (auto* cache = oldDocument.existingAXObjectCache())
cache->remove(*this);
Expand Down
12 changes: 12 additions & 0 deletions modules/javafx.web/src/main/native/Source/WebCore/dom/Range.cpp
Expand Up @@ -1659,6 +1659,18 @@ void Range::nodeWillBeRemoved(Node& node)
boundaryNodeWillBeRemoved(m_end, node);
}

bool Range::parentlessNodeMovedToNewDocumentAffectsRange(Node& node)
{
return node.containsIncludingShadowDOM(m_start.container());
}

void Range::updateRangeForParentlessNodeMovedToNewDocument(Node& node)
{
m_ownerDocument->detachRange(*this);
m_ownerDocument = node.document();
m_ownerDocument->attachRange(*this);
}

static inline void boundaryTextInserted(RangeBoundaryPoint& boundary, Node& text, unsigned offset, unsigned length)
{
if (boundary.container() != &text)
Expand Down
2 changes: 2 additions & 0 deletions modules/javafx.web/src/main/native/Source/WebCore/dom/Range.h
Expand Up @@ -138,6 +138,8 @@ class Range : public RefCounted<Range> {
void nodeChildrenChanged(ContainerNode&);
void nodeChildrenWillBeRemoved(ContainerNode&);
void nodeWillBeRemoved(Node&);
bool parentlessNodeMovedToNewDocumentAffectsRange(Node&);
void updateRangeForParentlessNodeMovedToNewDocument(Node&);

void textInserted(Node&, unsigned offset, unsigned length);
void textRemoved(Node&, unsigned offset, unsigned length);
Expand Down
Expand Up @@ -124,13 +124,6 @@ void HTMLAppletElement::updateWidget(CreatePlugins createPlugins)

setNeedsWidgetUpdate(false);

RenderEmbeddedObject* renderer = renderEmbeddedObject();

LayoutUnit contentWidth = renderer->style().width().isFixed() ? LayoutUnit(renderer->style().width().value()) :
renderer->width() - renderer->horizontalBorderAndPaddingExtent();
LayoutUnit contentHeight = renderer->style().height().isFixed() ? LayoutUnit(renderer->style().height().value()) :
renderer->height() - renderer->verticalBorderAndPaddingExtent();

Vector<String> paramNames;
Vector<String> paramValues;

Expand Down Expand Up @@ -175,7 +168,20 @@ void HTMLAppletElement::updateWidget(CreatePlugins createPlugins)
RefPtr<Frame> frame = document().frame();
ASSERT(frame);

renderer->setWidget(frame->loader().subframeLoader().createJavaAppletWidget(roundedIntSize(LayoutSize(contentWidth, contentHeight)), *this, paramNames, paramValues));
auto contentSize = LayoutSize { };
{
auto* renderer = renderEmbeddedObject();
auto& style = renderer->style();

contentSize = LayoutSize { style.width().isFixed() ? LayoutUnit(style.width().value()) : renderer->width() - renderer->horizontalBorderAndPaddingExtent(),
style.height().isFixed() ? LayoutUnit(style.height().value()) : renderer->height() - renderer->verticalBorderAndPaddingExtent() };
}

auto widget = frame->loader().subframeLoader().createJavaAppletWidget(roundedIntSize(contentSize), *this, paramNames, paramValues);
// createJavaAppletWidget needs to check if the plugin(replacement) is obscured. Since the overlapping test requires up-to-date geometry, it initiates a top level style recalc/layout.
// Let's see if this element still has a renderer after the style recalc.
if (auto* renderer = renderEmbeddedObject())
renderer->setWidget(WTFMove(widget));
#endif // !PLATFORM(IOS_FAMILY)
}

Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2006-2018 Apple Inc. All rights reserved.
* Copyright (C) 2006-2020 Apple Inc. All rights reserved.
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
* Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
* Copyright (C) 2008 Alp Toker <alp@atoker.com>
Expand Down Expand Up @@ -461,9 +461,11 @@ void FrameLoader::submitForm(Ref<FormSubmission>&& submission)
return;
}

if (WTF::protocolIsJavaScript(submission->action())) {
if (!m_frame.document()->contentSecurityPolicy()->allowFormAction(URL(submission->action())))
return;
URL formAction = submission->action();
if (!m_frame.document()->contentSecurityPolicy()->allowFormAction(formAction))
return;

if (WTF::protocolIsJavaScript(formAction)) {
m_isExecutingJavaScriptFormAction = true;
Ref<Frame> protect(m_frame);
m_frame.script().executeIfJavaScriptURL(submission->action(), nullptr, DoNotReplaceDocumentIfJavaScriptURL);
Expand Down

0 comments on commit 88c0f97

Please sign in to comment.