Diff
Modified: trunk/LayoutTests/ChangeLog (215321 => 215322)
--- trunk/LayoutTests/ChangeLog 2017-04-13 16:38:58 UTC (rev 215321)
+++ trunk/LayoutTests/ChangeLog 2017-04-13 16:40:25 UTC (rev 215322)
@@ -1,3 +1,15 @@
+2017-04-13 Romain Bellessort <romain.belless...@crf.canon.fr>
+
+ [Readable Streams API] Implement cloneArrayBuffer in WebCore
+ https://bugs.webkit.org/show_bug.cgi?id=170008
+
+ Reviewed by Youenn Fablet.
+
+ Added test to check cloneArrayBuffer behaviour.
+
+ * streams/clone-array-buffer-expected.txt: Added.
+ * streams/clone-array-buffer.html: Added.
+
2017-04-13 Youenn Fablet <you...@apple.com>
onnegotiationneeded should only be called once
Added: trunk/LayoutTests/streams/clone-array-buffer-expected.txt (0 => 215322)
--- trunk/LayoutTests/streams/clone-array-buffer-expected.txt (rev 0)
+++ trunk/LayoutTests/streams/clone-array-buffer-expected.txt 2017-04-13 16:40:25 UTC (rev 215322)
@@ -0,0 +1,3 @@
+
+PASS Test cloneArrayBuffer implementation
+
Added: trunk/LayoutTests/streams/clone-array-buffer.html (0 => 215322)
--- trunk/LayoutTests/streams/clone-array-buffer.html (rev 0)
+++ trunk/LayoutTests/streams/clone-array-buffer.html 2017-04-13 16:40:25 UTC (rev 215322)
@@ -0,0 +1,22 @@
+
+<!DOCTYPE html>
+<script src=''></script>
+<script src=''></script>
+<script>
+'use strict';
+
+const CloneArrayBuffer = internals.cloneArrayBuffer.bind(internals);
+
+test(function() {
+ const typedArray = new Uint8Array([3, 5, 7]);
+ const clonedBuffer = CloneArrayBuffer(typedArray.buffer, 1, 1);
+ const otherArray = new Uint8Array(clonedBuffer);
+ assert_equals(otherArray.byteLength, 1);
+ assert_equals(otherArray.byteOffset, 0);
+ assert_equals(otherArray.buffer.byteLength, 1);
+ assert_equals(otherArray[0], 5);
+ // Check that when typedArray is modified, otherArray is not modified.
+ typedArray[1] = 0;
+ assert_equals(otherArray[0], 5);
+}, "Test cloneArrayBuffer implementation");
+</script>
Modified: trunk/Source/WebCore/ChangeLog (215321 => 215322)
--- trunk/Source/WebCore/ChangeLog 2017-04-13 16:38:58 UTC (rev 215321)
+++ trunk/Source/WebCore/ChangeLog 2017-04-13 16:40:25 UTC (rev 215322)
@@ -1,3 +1,31 @@
+2017-04-13 Romain Bellessort <romain.belless...@crf.canon.fr>
+
+ [Readable Streams API] Implement cloneArrayBuffer in WebCore
+ https://bugs.webkit.org/show_bug.cgi?id=170008
+
+ Reviewed by Youenn Fablet.
+
+ Implemented cloneArrayBuffer based on existing structuredCloneArrayBuffer
+ implementation. The code has been factorized so that both cloneArrayBuffer
+ and structuredCloneArrayBuffer rely on the same code (which is basically
+ the previous implementation of structuredCloneArrayBuffer + the ability
+ to clone only a part of considered buffer).
+
+ Test: streams/clone-array-buffer.html
+
+ * Modules/streams/ReadableByteStreamInternals.js: Deleted cloneArrayBuffer JS implementation.
+ * bindings/js/JSDOMGlobalObject.cpp:
+ (WebCore::JSDOMGlobalObject::addBuiltinGlobals): Add cloneArrayBuffer private declaration.
+ * bindings/js/StructuredClone.cpp:
+ (WebCore::cloneArrayBufferImpl): Added (mostly based on previous structuredCloneArrayBuffer).
+ (WebCore::cloneArrayBuffer): Added.
+ (WebCore::structuredCloneArrayBuffer): Updated.
+ * bindings/js/StructuredClone.h: Added cloneArrayBuffer declaration.
+ * bindings/js/WebCoreBuiltinNames.h: Added cloneArrayBuffer declaration.
+ * testing/Internals.cpp: Added support for testing cloneArrayBuffer.
+ * testing/Internals.h: Added support for testing cloneArrayBuffer.
+ * testing/Internals.idl: Added support for testing cloneArrayBuffer.
+
2017-04-13 Youenn Fablet <you...@apple.com>
onnegotiationneeded should only be called once
Modified: trunk/Source/WebCore/Modules/streams/ReadableByteStreamInternals.js (215321 => 215322)
--- trunk/Source/WebCore/Modules/streams/ReadableByteStreamInternals.js 2017-04-13 16:38:58 UTC (rev 215321)
+++ trunk/Source/WebCore/Modules/streams/ReadableByteStreamInternals.js 2017-04-13 16:40:25 UTC (rev 215322)
@@ -396,17 +396,6 @@
}
}
-function cloneArrayBuffer(srcBuffer, srcByteOffset, srcLength)
-{
- "use strict";
-
- // FIXME: Below implementation returns the appropriate data but does not perform
- // exactly what is described by ECMAScript CloneArrayBuffer operation. This should
- // be fixed in a follow up patch implementing cloneArrayBuffer in JSC (similarly to
- // structuredCloneArrayBuffer implementation).
- return srcBuffer.slice(srcByteOffset, srcByteOffset + srcLength);
-}
-
function readableByteStreamControllerRespondInReadableState(controller, bytesWritten, pullIntoDescriptor)
{
"use strict";
Modified: trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp (215321 => 215322)
--- trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp 2017-04-13 16:38:58 UTC (rev 215321)
+++ trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp 2017-04-13 16:40:25 UTC (rev 215322)
@@ -142,6 +142,8 @@
JSFunction::create(vm, this, 2, String(), makeThisTypeErrorForBuiltins), DontDelete | ReadOnly),
JSDOMGlobalObject::GlobalPropertyInfo(clientData.builtinNames().makeGetterTypeErrorPrivateName(),
JSFunction::create(vm, this, 2, String(), makeGetterTypeErrorForBuiltins), DontDelete | ReadOnly),
+ JSDOMGlobalObject::GlobalPropertyInfo(clientData.builtinNames().cloneArrayBufferPrivateName(),
+ JSFunction::create(vm, this, 3, String(), cloneArrayBuffer), DontDelete | ReadOnly),
JSDOMGlobalObject::GlobalPropertyInfo(clientData.builtinNames().structuredCloneArrayBufferPrivateName(),
JSFunction::create(vm, this, 1, String(), structuredCloneArrayBuffer), DontDelete | ReadOnly),
JSDOMGlobalObject::GlobalPropertyInfo(clientData.builtinNames().structuredCloneArrayBufferViewPrivateName(),
Modified: trunk/Source/WebCore/bindings/js/StructuredClone.cpp (215321 => 215322)
--- trunk/Source/WebCore/bindings/js/StructuredClone.cpp 2017-04-13 16:38:58 UTC (rev 215321)
+++ trunk/Source/WebCore/bindings/js/StructuredClone.cpp 2017-04-13 16:40:25 UTC (rev 215322)
@@ -35,7 +35,14 @@
namespace WebCore {
-EncodedJSValue JSC_HOST_CALL structuredCloneArrayBuffer(ExecState* state)
+enum class CloneMode {
+ Full,
+ Partial,
+};
+
+EncodedJSValue JSC_HOST_CALL cloneArrayBufferImpl(ExecState*, CloneMode);
+
+EncodedJSValue JSC_HOST_CALL cloneArrayBufferImpl(ExecState* state, CloneMode mode)
{
ASSERT(state);
ASSERT(state->argumentCount());
@@ -48,9 +55,25 @@
throwDataCloneError(*state, scope);
return { };
}
+ if (mode == CloneMode::Partial) {
+ ASSERT(state->argumentCount() == 3);
+ int srcByteOffset = static_cast<int>(state->uncheckedArgument(1).toNumber(state));
+ int srcLength = static_cast<int>(state->uncheckedArgument(2).toNumber(state));
+ return JSValue::encode(JSArrayBuffer::create(state->vm(), state->lexicalGlobalObject()->arrayBufferStructure(ArrayBufferSharingMode::Default), buffer->slice(srcByteOffset, srcByteOffset + srcLength)));
+ }
return JSValue::encode(JSArrayBuffer::create(state->vm(), state->lexicalGlobalObject()->arrayBufferStructure(ArrayBufferSharingMode::Default), ArrayBuffer::tryCreate(buffer->data(), buffer->byteLength())));
}
+EncodedJSValue JSC_HOST_CALL cloneArrayBuffer(ExecState* state)
+{
+ return cloneArrayBufferImpl(state, CloneMode::Partial);
+}
+
+EncodedJSValue JSC_HOST_CALL structuredCloneArrayBuffer(ExecState* state)
+{
+ return cloneArrayBufferImpl(state, CloneMode::Full);
+}
+
EncodedJSValue JSC_HOST_CALL structuredCloneArrayBufferView(ExecState* state)
{
ASSERT(state);
Modified: trunk/Source/WebCore/bindings/js/StructuredClone.h (215321 => 215322)
--- trunk/Source/WebCore/bindings/js/StructuredClone.h 2017-04-13 16:38:58 UTC (rev 215321)
+++ trunk/Source/WebCore/bindings/js/StructuredClone.h 2017-04-13 16:40:25 UTC (rev 215322)
@@ -31,6 +31,7 @@
namespace WebCore {
+JSC::EncodedJSValue JSC_HOST_CALL cloneArrayBuffer(JSC::ExecState*);
JSC::EncodedJSValue JSC_HOST_CALL structuredCloneArrayBuffer(JSC::ExecState*);
JSC::EncodedJSValue JSC_HOST_CALL structuredCloneArrayBufferView(JSC::ExecState*);
Modified: trunk/Source/WebCore/bindings/js/WebCoreBuiltinNames.h (215321 => 215322)
--- trunk/Source/WebCore/bindings/js/WebCoreBuiltinNames.h 2017-04-13 16:38:58 UTC (rev 215321)
+++ trunk/Source/WebCore/bindings/js/WebCoreBuiltinNames.h 2017-04-13 16:40:25 UTC (rev 215322)
@@ -39,6 +39,7 @@
macro(body) \
macro(byobRequest) \
macro(cancel) \
+ macro(cloneArrayBuffer) \
macro(cloneForJS) \
macro(closeRequested) \
macro(closedPromiseCapability) \
Modified: trunk/Source/WebCore/testing/Internals.cpp (215321 => 215322)
--- trunk/Source/WebCore/testing/Internals.cpp 2017-04-13 16:38:58 UTC (rev 215321)
+++ trunk/Source/WebCore/testing/Internals.cpp 2017-04-13 16:40:25 UTC (rev 215322)
@@ -354,7 +354,7 @@
#endif
else
return false;
-
+
return true;
}
@@ -394,9 +394,9 @@
page.setPaginationLineGridEnabled(false);
page.setDefersLoading(false);
-
+
page.mainFrame().setTextZoomFactor(1.0f);
-
+
FrameView* mainFrameView = page.mainFrame().view();
if (mainFrameView) {
mainFrameView->setHeaderHeight(0);
@@ -598,7 +598,7 @@
ResourceRequest request(contextDocument()->completeURL(url));
request.setDomainForCachePartition(contextDocument()->topOrigin().domainForCachePartition());
-
+
CachedResource* resource = MemoryCache::singleton().resourceForRequest(request, contextDocument()->page()->sessionID());
return resource && resource->status() == CachedResource::Cached;
}
@@ -755,11 +755,11 @@
auto* cachedImage = element.cachedImage();
if (!cachedImage)
return;
-
+
auto* image = cachedImage->image();
if (!is<BitmapImage>(image))
return;
-
+
downcast<BitmapImage>(*image).setFrameDecodingDurationForTesting(Seconds { duration });
}
@@ -1030,7 +1030,7 @@
count++;
continue;
}
-
+
StyleRuleGroup* groupRule = nullptr;
if (is<StyleRuleMedia>(rule.get()))
groupRule = downcast<StyleRuleMedia>(rule.get());
@@ -1038,11 +1038,11 @@
groupRule = downcast<StyleRuleSupports>(rule.get());
if (!groupRule)
continue;
-
+
auto* groupChildRules = groupRule->childRulesWithoutDeferredParsing();
if (!groupChildRules)
continue;
-
+
count += deferredStyleRulesCountForList(*groupChildRules);
}
@@ -1065,7 +1065,7 @@
groupRule = downcast<StyleRuleSupports>(rule.get());
if (!groupRule)
continue;
-
+
auto* groupChildRules = groupRule->childRulesWithoutDeferredParsing();
if (!groupChildRules)
count++;
@@ -1090,7 +1090,7 @@
count++;
continue;
}
-
+
StyleRuleGroup* groupRule = nullptr;
if (is<StyleRuleMedia>(rule.get()))
groupRule = downcast<StyleRuleMedia>(rule.get());
@@ -1098,14 +1098,14 @@
groupRule = downcast<StyleRuleSupports>(rule.get());
if (!groupRule)
continue;
-
+
auto* groupChildRules = groupRule->childRulesWithoutDeferredParsing();
if (!groupChildRules)
continue;
-
+
count += deferredKeyframesRulesCountForList(*groupChildRules);
}
-
+
return count;
}
@@ -1178,7 +1178,7 @@
auto behavior = document->page()->eventThrottlingBehaviorOverride();
if (!behavior)
return std::nullopt;
-
+
switch (behavior.value()) {
case WebCore::EventThrottlingBehavior::Responsive:
return Internals::EventThrottlingBehavior::Responsive;
@@ -1243,7 +1243,7 @@
SpeechSynthesis* synthesis = DOMWindowSpeechSynthesis::speechSynthesis(*document->domWindow());
if (!synthesis)
return;
-
+
synthesis->setPlatformSynthesizer(std::make_unique<PlatformSpeechSynthesizerMock>(synthesis));
}
@@ -1692,7 +1692,7 @@
return Exception { INVALID_ACCESS_ERR };
document->updateLayoutIgnorePendingStylesheets();
-
+
HitTestResult result = document->frame()->mainFrame().eventHandler().hitTestResultAtPoint(IntPoint(x, y));
NSDictionary *options = nullptr;
return DictionaryLookup::rangeAtHitTestResult(result, &options);
@@ -1848,7 +1848,7 @@
} else {
HitTestResult result(point, topPadding, rightPadding, bottomPadding, leftPadding);
renderView->hitTest(request, result);
-
+
const HitTestResult::NodeSet& nodeSet = result.rectBasedTestResult();
matches.reserveInitialCapacity(nodeSet.size());
for (auto& node : nodeSet)
@@ -1969,7 +1969,7 @@
return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Spelling, from, length);
}
-
+
bool Internals::hasAutocorrectedMarker(int from, int length)
{
Document* document = contextDocument();
@@ -2222,7 +2222,7 @@
return count;
}
-
+
ExceptionOr<bool> Internals::isPageBoxVisible(int pageNumber)
{
Document* document = contextDocument();
@@ -2275,7 +2275,7 @@
auto& layerModelObject = downcast<RenderLayerModelObject>(*element.renderer());
if (!layerModelObject.layer()->isComposited())
return Exception { NOT_FOUND_ERR };
-
+
auto* backing = layerModelObject.layer()->backing();
return backing->graphicsLayer()->primaryLayerID();
}
@@ -2344,11 +2344,11 @@
if (!element.renderer()->hasLayer())
return Exception { INVALID_ACCESS_ERR };
-
+
RenderLayer* layer = downcast<RenderLayerModelObject>(element.renderer())->layer();
if (!layer->isComposited())
return Exception { INVALID_ACCESS_ERR };
-
+
layer->backing()->setUsesDisplayListDrawing(usesDisplayListDrawing);
return { };
}
@@ -2373,7 +2373,7 @@
RenderLayer* layer = downcast<RenderLayerModelObject>(element.renderer())->layer();
if (!layer->isComposited())
return Exception { INVALID_ACCESS_ERR };
-
+
layer->backing()->setIsTrackingDisplayListReplay(isTrackingReplay);
return { };
}
@@ -2613,7 +2613,7 @@
document->view()->setFooterHeight(height);
}
-
+
void Internals::setTopContentInset(float contentInset)
{
Document* document = contextDocument();
@@ -2757,7 +2757,7 @@
Document* document = contextDocument();
if (!document)
return Exception { INVALID_ACCESS_ERR };
-
+
return document->styleRecalcCount();
}
@@ -2784,7 +2784,7 @@
Document* document = contextDocument();
if (!document || !document->renderView())
return Exception { INVALID_ACCESS_ERR };
-
+
return document->renderView()->compositor().compositingUpdateCount();
}
@@ -3076,10 +3076,10 @@
Document* document = contextDocument();
if (!document || !document->page())
return Exception { INVALID_ACCESS_ERR };
-
+
#if ENABLE(VIDEO_TRACK)
auto& captionPreferences = document->page()->group().captionPreferences();
-
+
if (equalLettersIgnoringASCIICase(mode, "automatic"))
captionPreferences.setCaptionDisplayMode(CaptionUserPreferences::Automatic);
else if (equalLettersIgnoringASCIICase(mode, "forcedonly"))
@@ -3144,12 +3144,12 @@
return downcast<RenderEmbeddedObject>(*renderer).isReplacementObscured();
}
-
+
bool Internals::isPluginSnapshotted(Element& element)
{
return is<HTMLPlugInElement>(element) && downcast<HTMLPlugInElement>(element).displayState() <= HTMLPlugInElement::DisplayingSnapshot;
}
-
+
#if ENABLE(MEDIA_SOURCE)
void Internals::initializeMockMediaSource()
@@ -3167,7 +3167,7 @@
{
return buffer.bufferedSamplesForTrackID(trackID);
}
-
+
Vector<String> Internals::enqueuedSamplesForTrackID(SourceBuffer& buffer, const AtomicString& trackID)
{
return buffer.enqueuedSamplesForTrackID(trackID);
@@ -3207,7 +3207,7 @@
if (equalLettersIgnoringASCIICase(flagsString, "mayresumeplaying"))
flags = PlatformMediaSession::MayResumePlaying;
-
+
PlatformMediaSessionManager::sharedManager().endInterruption(flags);
}
@@ -3362,7 +3362,7 @@
command = PlatformMediaSession::SeekToPlaybackPositionCommand;
else
return Exception { INVALID_ACCESS_ERR };
-
+
PlatformMediaSessionManager::sharedManager().didReceiveRemoteControlCommand(command, ¶meter);
return { };
}
@@ -3637,12 +3637,12 @@
builder.appendLiteral(", ");
else
justStarting = false;
-
+
builder.append(String::number(coordinate.toUnsigned()));
}
builder.appendLiteral(" }");
}
-
+
void Internals::setPlatformMomentumScrollingPredictionEnabled(bool enabled)
{
ScrollingMomentumCalculator::setPlatformMomentumScrollingPredictionEnabled(enabled);
@@ -3657,13 +3657,13 @@
RenderBox& box = *element.renderBox();
ScrollableArea* scrollableArea;
-
+
if (box.isBody()) {
FrameView* frameView = box.frame().mainFrame().view();
if (!frameView || !frameView->isScrollable())
return Exception { INVALID_ACCESS_ERR };
scrollableArea = frameView;
-
+
} else {
if (!box.canBeScrolledAndHasScrollableArea())
return Exception { INVALID_ACCESS_ERR };
@@ -3672,7 +3672,7 @@
if (!scrollableArea)
return String();
-
+
StringBuilder result;
if (auto* offsets = scrollableArea->horizontalSnapOffsets()) {
@@ -3761,7 +3761,7 @@
Document* document = contextDocument();
if (!document)
return;
-
+
Page* page = document->page();
if (!page)
return;
@@ -3794,7 +3794,33 @@
return returnedValue.asBoolean();
}
+#if ENABLE(READABLE_BYTE_STREAM_API)
+
+JSValue Internals::cloneArrayBuffer(JSC::ExecState& state, JSValue buffer, JSValue srcByteOffset, JSValue srcLength)
+{
+ JSGlobalObject* globalObject = state.vmEntryGlobalObject();
+ JSVMClientData* clientData = static_cast<JSVMClientData*>(state.vm().clientData);
+ const Identifier& privateName = clientData->builtinNames().cloneArrayBufferPrivateName();
+ JSValue value;
+ PropertySlot propertySlot(value, PropertySlot::InternalMethodType::Get);
+ globalObject->methodTable()->getOwnPropertySlot(globalObject, &state, privateName, propertySlot);
+ value = propertySlot.getValue(&state, privateName);
+ ASSERT(value.isFunction());
+
+ JSObject* function = value.getObject();
+ CallData callData;
+ CallType callType = JSC::getCallData(function, callData);
+ ASSERT(callType != JSC::CallType::None);
+ MarkedArgumentBuffer arguments;
+ arguments.append(buffer);
+ arguments.append(srcByteOffset);
+ arguments.append(srcLength);
+
+ return JSC::call(&state, function, callType, callData, JSC::jsUndefined(), arguments);
+}
+
#endif
+#endif
String Internals::resourceLoadStatisticsForOrigin(const String& origin)
{
Modified: trunk/Source/WebCore/testing/Internals.h (215321 => 215322)
--- trunk/Source/WebCore/testing/Internals.h 2017-04-13 16:38:58 UTC (rev 215321)
+++ trunk/Source/WebCore/testing/Internals.h 2017-04-13 16:40:25 UTC (rev 215322)
@@ -195,14 +195,14 @@
void invalidateFontCache();
void setFontSmoothingEnabled(bool);
-
+
ExceptionOr<void> setLowPowerModeEnabled(bool);
ExceptionOr<void> setScrollViewPosition(int x, int y);
-
+
ExceptionOr<Ref<ClientRect>> layoutViewportRect();
ExceptionOr<Ref<ClientRect>> visualViewportRect();
-
+
ExceptionOr<void> setViewBaseBackgroundColor(const String& colorValue);
ExceptionOr<void> setPagination(const String& mode, int gap, int pageLength);
@@ -375,7 +375,7 @@
ExceptionOr<void> startTrackingLayerFlushes();
ExceptionOr<unsigned> layerFlushCount();
-
+
ExceptionOr<void> startTrackingStyleRecalcs();
ExceptionOr<unsigned> styleRecalcCount();
unsigned lastStyleUpdateSize() const;
@@ -531,10 +531,13 @@
#if ENABLE(READABLE_STREAM_API)
bool isReadableStreamDisturbed(JSC::ExecState&, JSC::JSValue);
+#if ENABLE(READABLE_BYTE_STREAM_API)
+ JSC::JSValue cloneArrayBuffer(JSC::ExecState&, JSC::JSValue, JSC::JSValue, JSC::JSValue);
#endif
+#endif
String composedTreeAsText(Node&);
-
+
bool isProcessingUserGesture();
double lastHandledUserGestureTimestamp();
@@ -544,7 +547,7 @@
void setUserInterfaceLayoutDirection(UserInterfaceLayoutDirection);
bool userPrefersReducedMotion() const;
-
+
void reportBacktrace();
enum class BaseWritingDirection { Natural, Ltr, Rtl };
Modified: trunk/Source/WebCore/testing/Internals.idl (215321 => 215322)
--- trunk/Source/WebCore/testing/Internals.idl 2017-04-13 16:38:58 UTC (rev 215321)
+++ trunk/Source/WebCore/testing/Internals.idl 2017-04-13 16:40:25 UTC (rev 215322)
@@ -493,6 +493,7 @@
void setShowAllPlugins(boolean showAll);
+ [Conditional=READABLE_STREAM_API&READABLE_BYTE_STREAM_API, CallWith=ScriptState] any cloneArrayBuffer(any buffer, any srcByteOffset, any byteLength);
[Conditional=READABLE_STREAM_API, CallWith=ScriptState] boolean isReadableStreamDisturbed(any stream);
DOMString resourceLoadStatisticsForOrigin(DOMString domain);