Diff
Modified: trunk/LayoutTests/imported/w3c/ChangeLog (288591 => 288592)
--- trunk/LayoutTests/imported/w3c/ChangeLog 2022-01-26 01:01:25 UTC (rev 288591)
+++ trunk/LayoutTests/imported/w3c/ChangeLog 2022-01-26 01:10:59 UTC (rev 288592)
@@ -1,5 +1,18 @@
2022-01-25 Alexey Shvayka <ashva...@apple.com>
+ [WebIDL] Blob-related methods should use _relevant_ context instead of _current_
+ https://bugs.webkit.org/show_bug.cgi?id=235279
+
+ Reviewed by Darin Adler.
+
+ Import WPT tests from TBA.
+
+ * web-platform-tests/FileAPI/blob/Blob-methods-from-detached-frame-expected.txt: Added.
+ * web-platform-tests/FileAPI/blob/Blob-methods-from-detached-frame.html: Added.
+ * web-platform-tests/FileAPI/support/empty-document.html: Added.
+
+2022-01-25 Alexey Shvayka <ashva...@apple.com>
+
XPath::Step::nodesInAxis(): add null checks after Attr::ownerElement() calls
https://bugs.webkit.org/show_bug.cgi?id=235500
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/FileAPI/blob/Blob-methods-from-detached-frame-expected.txt (0 => 288592)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/FileAPI/blob/Blob-methods-from-detached-frame-expected.txt (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/FileAPI/blob/Blob-methods-from-detached-frame-expected.txt 2022-01-26 01:10:59 UTC (rev 288592)
@@ -0,0 +1,6 @@
+
+PASS slice()
+PASS text()
+PASS arrayBuffer()
+PASS stream()
+
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/FileAPI/blob/Blob-methods-from-detached-frame.html (0 => 288592)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/FileAPI/blob/Blob-methods-from-detached-frame.html (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/FileAPI/blob/Blob-methods-from-detached-frame.html 2022-01-26 01:10:59 UTC (rev 288592)
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Blob methods from detached frame work as expected</title>
+<script src=""
+<script src=""
+
+<iframe id="emptyDocumentIframe" src=""
+
+<script>
+const BlobPrototypeFromDetachedFramePromise = new Promise(resolve => {
+ emptyDocumentIframe._onload_ = () => {
+ const BlobPrototype = emptyDocumentIframe.contentWindow.Blob.prototype;
+ emptyDocumentIframe.remove();
+ resolve(BlobPrototype);
+ };
+});
+
+const charCodeArrayToString = charCodeArray => Array.from(charCodeArray, c => String.fromCharCode(c)).join("");
+const charCodeBufferToString = charCodeBuffer => charCodeArrayToString(new Uint8Array(charCodeBuffer));
+
+promise_test(async () => {
+ const { slice } = await BlobPrototypeFromDetachedFramePromise;
+ const blob = new Blob(["foobar"]);
+
+ const slicedBlob = slice.call(blob, 1, 3);
+ assert_true(slicedBlob instanceof Blob);
+
+ assert_equals(await slicedBlob.text(), "oo");
+ assert_equals(charCodeBufferToString(await slicedBlob.arrayBuffer()), "oo");
+
+ const reader = slicedBlob.stream().getReader();
+ const { value } = await reader.read();
+ assert_equals(charCodeArrayToString(value), "oo");
+}, "slice()");
+
+promise_test(async () => {
+ const { text } = await BlobPrototypeFromDetachedFramePromise;
+ const blob = new Blob(["foo"]);
+
+ assert_equals(await text.call(blob), "foo");
+}, "text()");
+
+promise_test(async () => {
+ const { arrayBuffer } = await BlobPrototypeFromDetachedFramePromise;
+ const blob = new Blob(["bar"]);
+
+ const charCodeBuffer = await arrayBuffer.call(blob);
+ assert_equals(charCodeBufferToString(charCodeBuffer), "bar");
+}, "arrayBuffer()");
+
+promise_test(async () => {
+ const { stream } = await BlobPrototypeFromDetachedFramePromise;
+ const blob = new Blob(["baz"]);
+
+ const reader = stream.call(blob).getReader();
+ const { value } = await reader.read();
+ assert_equals(charCodeArrayToString(value), "baz");
+}, "stream()");
+</script>
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/FileAPI/support/empty-document.html (0 => 288592)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/FileAPI/support/empty-document.html (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/FileAPI/support/empty-document.html 2022-01-26 01:10:59 UTC (rev 288592)
@@ -0,0 +1,3 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<body>
Modified: trunk/Source/WebCore/ChangeLog (288591 => 288592)
--- trunk/Source/WebCore/ChangeLog 2022-01-26 01:01:25 UTC (rev 288591)
+++ trunk/Source/WebCore/ChangeLog 2022-01-26 01:10:59 UTC (rev 288592)
@@ -1,3 +1,47 @@
+2022-01-25 Alexey Shvayka <ashva...@apple.com>
+
+ [WebIDL] Blob-related methods should use _relevant_ context instead of _current_
+ https://bugs.webkit.org/show_bug.cgi?id=235279
+
+ Reviewed by Darin Adler.
+
+ This patch fixes the following methods to rely on _relevant_ global object instead of _current_:
+
+ 1. Blob's slice() / stream() / arrayBuffer() / text() as explicitly required by the File API spec [1].
+ Before this change, methods from detached <iframe> were throwing when called on a main frame's Blob.
+ Aligns WebKit with Blink and Gecko.
+
+ 2. HTMLCanvasElement's toBlob() as per HTML spec [2]: a task should be queued on _relevant_ document's
+ event loop.
+
+ 3. HTMLCanvasElement's transferControlToOffscreen() / captureStream() per recommendatation for spec
+ authors [4], and to align with toBlob(). transferControlToOffscreen() should certainly pass _relevant_
+ context, which would be used later for Blob creation.
+
+ [1] https://w3c.github.io/FileAPI/#blob-get-stream
+ [2] https://html.spec.whatwg.org/#canvas-blob-serialisation-task-source
+ [3] https://html.spec.whatwg.org/multipage/webappapis.html#realms-settings-objects-global-objects:concept-relevant-everything-2
+
+ Test: imported/w3c/web-platform-tests/FileAPI/blob/Blob-methods-from-detached-frame.html
+
+ Not sure if changes to HTMLCanvasElement methods are even testable.
+
+ * fileapi/Blob.cpp:
+ (WebCore::Blob::slice const):
+ (WebCore::Blob::loadBlob):
+ (WebCore::Blob::text):
+ (WebCore::Blob::arrayBuffer):
+ (WebCore::Blob::stream):
+ * fileapi/Blob.h:
+ * fileapi/Blob.idl:
+ * html/HTMLCanvasElement.cpp:
+ (WebCore::HTMLCanvasElement::toBlob):
+ (WebCore::HTMLCanvasElement::transferControlToOffscreen):
+ (WebCore::HTMLCanvasElement::captureStream):
+ * html/HTMLCanvasElement.h:
+ * html/HTMLCanvasElement.idl:
+ Mark transferControlToOffscreen() as [NewObject].
+
2022-01-25 Aditya Keerthi <akeer...@apple.com>
Disable input-security CSS property
Modified: trunk/Source/WebCore/fileapi/Blob.cpp (288591 => 288592)
--- trunk/Source/WebCore/fileapi/Blob.cpp 2022-01-26 01:01:25 UTC (rev 288591)
+++ trunk/Source/WebCore/fileapi/Blob.cpp 2022-01-26 01:10:59 UTC (rev 288592)
@@ -159,9 +159,9 @@
(*m_blobLoaders.begin())->cancel();
}
-Ref<Blob> Blob::slice(ScriptExecutionContext& context, long long start, long long end, const String& contentType) const
+Ref<Blob> Blob::slice(long long start, long long end, const String& contentType) const
{
- auto blob = adoptRef(*new Blob(&context, m_internalURL, start, end, contentType));
+ auto blob = adoptRef(*new Blob(scriptExecutionContext(), m_internalURL, start, end, contentType));
blob->suspendIfNeeded();
return blob;
}
@@ -196,7 +196,7 @@
return contentType.convertToASCIILowercase();
}
-void Blob::loadBlob(ScriptExecutionContext& context, FileReaderLoader::ReadType readType, CompletionHandler<void(BlobLoader&)>&& completionHandler)
+void Blob::loadBlob(FileReaderLoader::ReadType readType, CompletionHandler<void(BlobLoader&)>&& completionHandler)
{
auto blobLoader = makeUnique<BlobLoader>([this, pendingActivity = makePendingActivity(*this), completionHandler = WTFMove(completionHandler)](BlobLoader& blobLoader) mutable {
completionHandler(blobLoader);
@@ -203,15 +203,15 @@
m_blobLoaders.take(&blobLoader);
});
- blobLoader->start(*this, &context, readType);
+ blobLoader->start(*this, scriptExecutionContext(), readType);
if (blobLoader->isLoading())
m_blobLoaders.add(WTFMove(blobLoader));
}
-void Blob::text(ScriptExecutionContext& context, Ref<DeferredPromise>&& promise)
+void Blob::text(Ref<DeferredPromise>&& promise)
{
- loadBlob(context, FileReaderLoader::ReadAsText, [promise = WTFMove(promise)](BlobLoader& blobLoader) mutable {
+ loadBlob(FileReaderLoader::ReadAsText, [promise = WTFMove(promise)](BlobLoader& blobLoader) mutable {
if (auto optionalErrorCode = blobLoader.errorCode()) {
promise->reject(Exception { *optionalErrorCode });
return;
@@ -220,9 +220,9 @@
});
}
-void Blob::arrayBuffer(ScriptExecutionContext& context, Ref<DeferredPromise>&& promise)
+void Blob::arrayBuffer(Ref<DeferredPromise>&& promise)
{
- loadBlob(context, FileReaderLoader::ReadAsArrayBuffer, [promise = WTFMove(promise)](BlobLoader& blobLoader) mutable {
+ loadBlob(FileReaderLoader::ReadAsArrayBuffer, [promise = WTFMove(promise)](BlobLoader& blobLoader) mutable {
if (auto optionalErrorCode = blobLoader.errorCode()) {
promise->reject(Exception { *optionalErrorCode });
return;
@@ -236,7 +236,7 @@
});
}
-ExceptionOr<Ref<ReadableStream>> Blob::stream(ScriptExecutionContext& scriptExecutionContext)
+ExceptionOr<Ref<ReadableStream>> Blob::stream()
{
class BlobStreamSource : public FileReaderLoaderClient, public ReadableStreamSource {
public:
@@ -290,10 +290,11 @@
std::optional<Exception> m_exception;
};
- auto* globalObject = scriptExecutionContext.globalObject();
+ auto* context = scriptExecutionContext();
+ auto* globalObject = context ? context->globalObject() : nullptr;
if (!globalObject)
return Exception { InvalidStateError };
- return ReadableStream::create(*globalObject, adoptRef(*new BlobStreamSource(scriptExecutionContext, *this)));
+ return ReadableStream::create(*globalObject, adoptRef(*new BlobStreamSource(*context, *this)));
}
#if ASSERT_ENABLED
Modified: trunk/Source/WebCore/fileapi/Blob.h (288591 => 288592)
--- trunk/Source/WebCore/fileapi/Blob.h 2022-01-26 01:01:25 UTC (rev 288591)
+++ trunk/Source/WebCore/fileapi/Blob.h 2022-01-26 01:10:59 UTC (rev 288592)
@@ -111,11 +111,11 @@
// URLRegistrable
URLRegistry& registry() const override;
- Ref<Blob> slice(ScriptExecutionContext&, long long start, long long end, const String& contentType) const;
+ Ref<Blob> slice(long long start, long long end, const String& contentType) const;
- void text(ScriptExecutionContext&, Ref<DeferredPromise>&&);
- void arrayBuffer(ScriptExecutionContext&, Ref<DeferredPromise>&&);
- ExceptionOr<Ref<ReadableStream>> stream(ScriptExecutionContext&);
+ void text(Ref<DeferredPromise>&&);
+ void arrayBuffer(Ref<DeferredPromise>&&);
+ ExceptionOr<Ref<ReadableStream>> stream();
// Keeping the handle alive will keep the Blob data alive (but not the Blob object).
BlobURLHandle handle() const;
@@ -138,7 +138,7 @@
Blob(ScriptExecutionContext*, const URL& srcURL, long long start, long long end, const String& contentType);
private:
- void loadBlob(ScriptExecutionContext&, FileReaderLoader::ReadType, CompletionHandler<void(BlobLoader&)>&&);
+ void loadBlob(FileReaderLoader::ReadType, CompletionHandler<void(BlobLoader&)>&&);
// ActiveDOMObject.
const char* activeDOMObjectName() const override;
Modified: trunk/Source/WebCore/fileapi/Blob.idl (288591 => 288592)
--- trunk/Source/WebCore/fileapi/Blob.idl 2022-01-26 01:01:25 UTC (rev 288591)
+++ trunk/Source/WebCore/fileapi/Blob.idl 2022-01-26 01:10:59 UTC (rev 288592)
@@ -42,9 +42,9 @@
readonly attribute unsigned long long size;
readonly attribute DOMString type;
- [CallWith=ScriptExecutionContext] Blob slice(optional long long start = 0, optional long long end = 0x7FFFFFFFFFFFFFFF, optional DOMString contentType = "");
+ [NewObject] Blob slice(optional long long start = 0, optional long long end = 0x7FFFFFFFFFFFFFFF, optional DOMString contentType = "");
- [NewObject, CallWith=ScriptExecutionContext] ReadableStream stream();
- [NewObject, CallWith=ScriptExecutionContext] Promise<USVString> text();
- [NewObject, CallWith=ScriptExecutionContext] Promise<ArrayBuffer> arrayBuffer();
+ [NewObject] ReadableStream stream();
+ [NewObject] Promise<USVString> text();
+ [NewObject] Promise<ArrayBuffer> arrayBuffer();
};
Modified: trunk/Source/WebCore/html/HTMLCanvasElement.cpp (288591 => 288592)
--- trunk/Source/WebCore/html/HTMLCanvasElement.cpp 2022-01-26 01:01:25 UTC (rev 288591)
+++ trunk/Source/WebCore/html/HTMLCanvasElement.cpp 2022-01-26 01:10:59 UTC (rev 288592)
@@ -708,13 +708,13 @@
return toDataURL(mimeType, { });
}
-ExceptionOr<void> HTMLCanvasElement::toBlob(ScriptExecutionContext& context, Ref<BlobCallback>&& callback, const String& mimeType, JSC::JSValue qualityValue)
+ExceptionOr<void> HTMLCanvasElement::toBlob(Ref<BlobCallback>&& callback, const String& mimeType, JSC::JSValue qualityValue)
{
if (!originClean())
return Exception { SecurityError };
if (size().isEmpty() || !buffer()) {
- callback->scheduleCallback(context, nullptr);
+ callback->scheduleCallback(document(), nullptr);
return { };
}
if (RuntimeEnabledFeatures::sharedFeatures().webAPIStatisticsEnabled())
@@ -729,7 +729,7 @@
Vector<uint8_t> blobData = data(imageData->pixelBuffer(), encodingMIMEType, quality);
if (!blobData.isEmpty())
blob = Blob::create(&document(), WTFMove(blobData), encodingMIMEType);
- callback->scheduleCallback(context, WTFMove(blob));
+ callback->scheduleCallback(document(), WTFMove(blob));
return { };
}
#endif
@@ -740,12 +740,12 @@
Vector<uint8_t> blobData = buffer()->toData(encodingMIMEType, quality);
if (!blobData.isEmpty())
blob = Blob::create(&document(), WTFMove(blobData), encodingMIMEType);
- callback->scheduleCallback(context, WTFMove(blob));
+ callback->scheduleCallback(document(), WTFMove(blob));
return { };
}
#if ENABLE(OFFSCREEN_CANVAS)
-ExceptionOr<Ref<OffscreenCanvas>> HTMLCanvasElement::transferControlToOffscreen(ScriptExecutionContext& context)
+ExceptionOr<Ref<OffscreenCanvas>> HTMLCanvasElement::transferControlToOffscreen()
{
if (m_context)
return Exception { InvalidStateError };
@@ -754,7 +754,7 @@
if (m_context->isAccelerated())
invalidateStyleAndLayerComposition();
- return OffscreenCanvas::create(context, *this);
+ return OffscreenCanvas::create(document(), *this);
}
#endif
@@ -807,7 +807,7 @@
#endif
}
-ExceptionOr<Ref<MediaStream>> HTMLCanvasElement::captureStream(Document& document, std::optional<double>&& frameRequestRate)
+ExceptionOr<Ref<MediaStream>> HTMLCanvasElement::captureStream(std::optional<double>&& frameRequestRate)
{
if (!originClean())
return Exception(SecurityError, "Canvas is tainted"_s);
@@ -817,8 +817,8 @@
if (frameRequestRate && frameRequestRate.value() < 0)
return Exception(NotSupportedError, "frameRequestRate is negative"_s);
- auto track = CanvasCaptureMediaStreamTrack::create(document, *this, WTFMove(frameRequestRate));
- auto stream = MediaStream::create(document);
+ auto track = CanvasCaptureMediaStreamTrack::create(document(), *this, WTFMove(frameRequestRate));
+ auto stream = MediaStream::create(document());
stream->addTrack(track);
return stream;
}
Modified: trunk/Source/WebCore/html/HTMLCanvasElement.h (288591 => 288592)
--- trunk/Source/WebCore/html/HTMLCanvasElement.h 2022-01-26 01:01:25 UTC (rev 288591)
+++ trunk/Source/WebCore/html/HTMLCanvasElement.h 2022-01-26 01:10:59 UTC (rev 288592)
@@ -96,9 +96,9 @@
WEBCORE_EXPORT ExceptionOr<UncachedString> toDataURL(const String& mimeType, JSC::JSValue quality);
WEBCORE_EXPORT ExceptionOr<UncachedString> toDataURL(const String& mimeType);
- ExceptionOr<void> toBlob(ScriptExecutionContext&, Ref<BlobCallback>&&, const String& mimeType, JSC::JSValue quality);
+ ExceptionOr<void> toBlob(Ref<BlobCallback>&&, const String& mimeType, JSC::JSValue quality);
#if ENABLE(OFFSCREEN_CANVAS)
- ExceptionOr<Ref<OffscreenCanvas>> transferControlToOffscreen(ScriptExecutionContext&);
+ ExceptionOr<Ref<OffscreenCanvas>> transferControlToOffscreen();
#endif
// Used for rendering
@@ -108,7 +108,7 @@
#if ENABLE(MEDIA_STREAM)
RefPtr<MediaSample> toMediaSample();
- ExceptionOr<Ref<MediaStream>> captureStream(Document&, std::optional<double>&& frameRequestRate);
+ ExceptionOr<Ref<MediaStream>> captureStream(std::optional<double>&& frameRequestRate);
#endif
Image* copiedImage() const final;
Modified: trunk/Source/WebCore/html/HTMLCanvasElement.idl (288591 => 288592)
--- trunk/Source/WebCore/html/HTMLCanvasElement.idl 2022-01-26 01:01:25 UTC (rev 288591)
+++ trunk/Source/WebCore/html/HTMLCanvasElement.idl 2022-01-26 01:10:59 UTC (rev 288592)
@@ -48,8 +48,8 @@
[CallWith=GlobalObject] RenderingContext? getContext(DOMString contextId, any... arguments);
DOMString toDataURL(optional DOMString type, optional any quality);
- [CallWith=ScriptExecutionContext] undefined toBlob(BlobCallback callback, optional DOMString type, optional any quality);
- [Conditional=OFFSCREEN_CANVAS, EnabledAtRuntime=OffscreenCanvasEnabled, CallWith=ScriptExecutionContext] OffscreenCanvas transferControlToOffscreen();
+ undefined toBlob(BlobCallback callback, optional DOMString type, optional any quality);
+ [Conditional=OFFSCREEN_CANVAS, EnabledAtRuntime=OffscreenCanvasEnabled, NewObject] OffscreenCanvas transferControlToOffscreen();
- [Conditional=MEDIA_STREAM, CallWith=Document, NewObject] MediaStream captureStream(optional double frameRequestRate);
+ [Conditional=MEDIA_STREAM, NewObject] MediaStream captureStream(optional double frameRequestRate);
};