Merge inbound to mozilla-central. a=merge
Merge inbound to mozilla-central. a=merge
--- a/dom/file/MemoryBlobImpl.h
+++ b/dom/file/MemoryBlobImpl.h
@@ -120,16 +120,17 @@ public:
uint32_t aLength,
nsIInputStream** _retval);
NS_DECL_THREADSAFE_ISUPPORTS
// These are mandatory.
NS_FORWARD_NSIINPUTSTREAM(mStream->)
NS_FORWARD_NSISEEKABLESTREAM(mSeekableStream->)
+ NS_FORWARD_NSITELLABLESTREAM(mSeekableStream->)
NS_FORWARD_NSICLONEABLEINPUTSTREAM(mCloneableInputStream->)
// This is optional. We use a conditional QI to keep it from being called
// if the underlying stream doesn't support it.
NS_FORWARD_NSIIPCSERIALIZABLEINPUTSTREAM(mSerializableInputStream->)
private:
~DataOwnerAdapter() {}
--- a/dom/media/MediaTimer.cpp
+++ b/dom/media/MediaTimer.cpp
@@ -16,29 +16,28 @@
namespace mozilla {
NS_IMPL_ADDREF(MediaTimer)
NS_IMPL_RELEASE_WITH_DESTROY(MediaTimer, DispatchDestroy())
MediaTimer::MediaTimer(bool aFuzzy)
: mMonitor("MediaTimer Monitor")
- , mTimer(NS_NewTimer())
, mCreationTimeStamp(TimeStamp::Now())
, mUpdateScheduled(false)
, mFuzzy(aFuzzy)
{
TIMER_LOG("MediaTimer::MediaTimer");
// Use the SharedThreadPool to create an nsIThreadPool with a maximum of one
// thread, which is equivalent to an nsIThread for our purposes.
RefPtr<SharedThreadPool> threadPool(
SharedThreadPool::Get(NS_LITERAL_CSTRING("MediaTimer"), 1));
mThread = threadPool.get();
- mTimer->SetTarget(mThread);
+ mTimer = NS_NewTimer(mThread);
}
void
MediaTimer::DispatchDestroy()
{
// Hold a strong reference to the thread so that it doesn't get deleted in
// Destroy(), which may run completely before the stack if Dispatch() begins
// to unwind.
--- a/dom/security/featurepolicy/FeaturePolicyUtils.cpp
+++ b/dom/security/featurepolicy/FeaturePolicyUtils.cpp
@@ -18,25 +18,25 @@ struct FeatureMap {
};
/*
* IMPORTANT: Do not change this list without review from a DOM peer _AND_ a
* DOM Security peer!
*/
static FeatureMap sSupportedFeatures[] = {
{ "autoplay", FeaturePolicyUtils::FeaturePolicyValue::eAll },
- { "camera", FeaturePolicyUtils::FeaturePolicyValue::eAll },
+ { "camera", FeaturePolicyUtils::FeaturePolicyValue::eSelf },
{ "encrypted-media", FeaturePolicyUtils::FeaturePolicyValue::eAll },
{ "fullscreen", FeaturePolicyUtils::FeaturePolicyValue::eAll },
{ "geolocation", FeaturePolicyUtils::FeaturePolicyValue::eAll },
- { "microphone", FeaturePolicyUtils::FeaturePolicyValue::eAll },
- { "midi", FeaturePolicyUtils::FeaturePolicyValue::eAll },
+ { "microphone", FeaturePolicyUtils::FeaturePolicyValue::eSelf },
+ { "midi", FeaturePolicyUtils::FeaturePolicyValue::eSelf },
{ "payment", FeaturePolicyUtils::FeaturePolicyValue::eAll },
// TODO: not supported yet!!!
- { "speaker", FeaturePolicyUtils::FeaturePolicyValue::eAll },
+ { "speaker", FeaturePolicyUtils::FeaturePolicyValue::eSelf },
{ "vr", FeaturePolicyUtils::FeaturePolicyValue::eAll },
};
/* static */ bool
FeaturePolicyUtils::IsSupportedFeature(const nsAString& aFeatureName)
{
uint32_t numFeatures = (sizeof(sSupportedFeatures) / sizeof(sSupportedFeatures[0]));
for (uint32_t i = 0; i < numFeatures; ++i) {
--- a/dom/security/featurepolicy/test/mochitest/test_parser.html
+++ b/dom/security/featurepolicy/test/mochitest/test_parser.html
@@ -13,34 +13,34 @@ SimpleTest.waitForExplicitFinish();
function test_document() {
info("Checking document.policy");
ok("policy" in document, "We have document.policy");
ok(!document.policy.allowsFeature("foobar"), "Random feature");
ok(!document.policy.allowsFeature("foobar", "http://www.something.net"), "Random feature");
- ok(document.policy.allowsFeature("camera"), "Camera is always enabled");
- ok(document.policy.allowsFeature("camera", "http://foo.bar"), "Camera is always enabled");
+ ok(document.policy.allowsFeature("camera"), "Camera is allowed for self");
+ ok(document.policy.allowsFeature("camera", "http://foo.bar"), "Camera is always allowed");
let allowed = document.policy.getAllowlistForFeature("camera");
is(allowed.length, 1, "Only 1 entry in allowlist for camera");
is(allowed[0], "*", "allowlist is *");
- ok(document.policy.allowsFeature("geolocation"), "Geolocation is enabled for self");
- ok(document.policy.allowsFeature("geolocation", location.origin), "Geolocation is enabled for self");
- ok(!document.policy.allowsFeature("geolocation", "http://foo.bar"), "Geolocation is not enabled for any random URL");
+ ok(document.policy.allowsFeature("geolocation"), "Geolocation is allowed for self");
+ ok(document.policy.allowsFeature("geolocation", location.origin), "Geolocation is allowed for self");
+ ok(!document.policy.allowsFeature("geolocation", "http://foo.bar"), "Geolocation is not allowed for any random URL");
allowed = document.policy.getAllowlistForFeature("geolocation");
is(allowed.length, 1, "Only 1 entry in allowlist for geolocation");
is(allowed[0], location.origin, "allowlist is self");
ok(!document.policy.allowsFeature("microphone"), "Microphone is disabled for self");
ok(!document.policy.allowsFeature("microphone", location.origin), "Microphone is disabled for self");
ok(!document.policy.allowsFeature("microphone", "http://foo.bar"), "Microphone is disabled for foo.bar");
- ok(document.policy.allowsFeature("microphone", "http://example.com"), "Microphone is enabled for example.com");
- ok(document.policy.allowsFeature("microphone", "http://example.org"), "Microphone is enabled for example.org");
+ ok(document.policy.allowsFeature("microphone", "http://example.com"), "Microphone is allowed for example.com");
+ ok(document.policy.allowsFeature("microphone", "http://example.org"), "Microphone is allowed for example.org");
allowed = document.policy.getAllowlistForFeature("microphone");
is(allowed.length, 0, "No allowlist for microphone");
ok(!document.policy.allowsFeature("vr"), "Vibrate is disabled for self");
ok(!document.policy.allowsFeature("vr", location.origin), "Vibrate is disabled for self");
ok(!document.policy.allowsFeature("vr", "http://foo.bar"), "Vibrate is disabled for foo.bar");
allowed = document.policy.getAllowlistForFeature("vr");
is(allowed.length, 0, "No allowlist for vr");
@@ -63,25 +63,25 @@ function test_document() {
function test_iframe_without_allow() {
info("Checking HTMLIFrameElement.policy");
let ifr = document.getElementById("ifr");
ok("policy" in ifr, "HTMLIFrameElement.policy exists");
ok(!ifr.policy.allowsFeature("foobar"), "Random feature");
ok(!ifr.policy.allowsFeature("foobar", "http://www.something.net"), "Random feature");
- ok(ifr.policy.allowsFeature("camera"), "Camera is always allowed");
- ok(ifr.policy.allowsFeature("camera", location.origin), "Camera is always allowed");
- ok(ifr.policy.allowsFeature("camera", "http://foo.bar"), "Camera is always allowed");
+ ok(ifr.policy.allowsFeature("camera"), "Camera is allowed for self");
+ ok(ifr.policy.allowsFeature("camera", location.origin), "Camera is allowed for self");
+ ok(!ifr.policy.allowsFeature("camera", "http://foo.bar"), "Camera is not allowed for a random URL");
let allowed = ifr.policy.getAllowlistForFeature("camera");
is(allowed.length, 1, "Only 1 entry in allowlist for camera");
- is(allowed[0], "*", "allowlist is '*'");
+ is(allowed[0], location.origin, "allowlist is 'self'");
- ok(ifr.policy.allowsFeature("geolocation"), "Geolocation is enabled for all");
- ok(ifr.policy.allowsFeature("geolocation", location.origin), "Geolocation is enabled for all");
+ ok(ifr.policy.allowsFeature("geolocation"), "Geolocation is allowed for all");
+ ok(ifr.policy.allowsFeature("geolocation", location.origin), "Geolocation is allowed for all");
ok(ifr.policy.allowsFeature("geolocation", "http://foo.bar"), "Geolocation is allowed for any random URL");
allowed = ifr.policy.getAllowlistForFeature("geolocation");
is(allowed.length, 1, "Only 1 entry in allowlist for geolocation");
is(allowed[0], "*", "allowlist is '*'");
ok(!ifr.policy.allowsFeature("microphone"), "Microphone is disabled for self");
ok(!ifr.policy.allowsFeature("microphone", location.origin), "Microphone is disabled for self");
ok(!ifr.policy.allowsFeature("microphone", "http://foo.bar"), "Microphone is disabled for foo.bar");
@@ -111,23 +111,23 @@ function test_iframe_with_allow() {
let ifr = document.getElementById("ifr");
ok("policy" in ifr, "HTMLIFrameElement.policy exists");
ifr.setAttribute("allow", "camera 'none'");
ok(!ifr.policy.allowsFeature("foobar"), "Random feature");
ok(!ifr.policy.allowsFeature("foobar", "http://www.something.net"), "Random feature");
- ok(!ifr.policy.allowsFeature("camera"), "Camera is not enabled");
+ ok(!ifr.policy.allowsFeature("camera"), "Camera is not allowed");
let allowed = ifr.policy.getAllowlistForFeature("camera");
is(allowed.length, 0, "Camera has an empty allowlist");
- ok(ifr.policy.allowsFeature("geolocation"), "Geolocation is enabled for all");
- ok(ifr.policy.allowsFeature("geolocation", location.origin), "Geolocation is enabled for all");
- ok(ifr.policy.allowsFeature("geolocation", "http://foo.bar"), "Geolocation is enabled for all");
+ ok(ifr.policy.allowsFeature("geolocation"), "Geolocation is allowed for all");
+ ok(ifr.policy.allowsFeature("geolocation", location.origin), "Geolocation is allowed for all");
+ ok(ifr.policy.allowsFeature("geolocation", "http://foo.bar"), "Geolocation is allowed for all");
allowed = ifr.policy.getAllowlistForFeature("geolocation");
is(allowed.length, 1, "Only 1 entry in allowlist for geolocation");
is(allowed[0], "*", "allowlist is '*'");
ok(!ifr.policy.allowsFeature("microphone"), "Microphone is disabled for self");
ok(!ifr.policy.allowsFeature("microphone", location.origin), "Microphone is disabled for self");
ok(!ifr.policy.allowsFeature("microphone", "http://foo.bar"), "Microphone is disabled for foo.bar");
ok(!ifr.policy.allowsFeature("microphone", "http://example.com"), "Microphone is disabled for example.com");
@@ -152,34 +152,35 @@ function test_iframe_contentDocument() {
let ifr = document.createElement("iframe");
ifr.setAttribute("src", "empty.html");
ifr.onload = function() {
ok("policy" in ifr.contentDocument, "We have ifr.contentDocument.policy");
ok(!ifr.contentDocument.policy.allowsFeature("foobar"), "Random feature");
ok(!ifr.contentDocument.policy.allowsFeature("foobar", "http://www.something.net"), "Random feature");
- ok(ifr.contentDocument.policy.allowsFeature("camera"), "Camera is always allowed");
- ok(ifr.contentDocument.policy.allowsFeature("camera", "http://foo.bar"), "Camera is always allowed");
+ ok(ifr.contentDocument.policy.allowsFeature("camera"), "Camera is allowed for self");
+ ok(ifr.contentDocument.policy.allowsFeature("camera", location.origin), "Camera is allowed for self");
+ ok(!ifr.contentDocument.policy.allowsFeature("camera", "http://foo.bar"), "Camera is allowed for self");
let allowed = ifr.contentDocument.policy.getAllowlistForFeature("camera");
is(allowed.length, 1, "Only 1 entry in allowlist for camera");
- is(allowed[0], "*", "allowlist is '*'");
+ is(allowed[0], location.origin, "allowlist is 'self'");
- ok(ifr.contentDocument.policy.allowsFeature("geolocation"), "Geolocation is enabled for all");
- ok(ifr.contentDocument.policy.allowsFeature("geolocation", location.origin), "Geolocation is enabled for all");
- ok(ifr.contentDocument.policy.allowsFeature("geolocation", "http://foo.bar"), "Geolocation is enabled for any random URL");
+ ok(ifr.contentDocument.policy.allowsFeature("geolocation"), "Geolocation is allowed for all");
+ ok(ifr.contentDocument.policy.allowsFeature("geolocation", location.origin), "Geolocation is allowed for all");
+ ok(ifr.contentDocument.policy.allowsFeature("geolocation", "http://foo.bar"), "Geolocation is allowed for any random URL");
allowed = ifr.contentDocument.policy.getAllowlistForFeature("geolocation");
is(allowed.length, 1, "Only 1 entry in allowlist for geolocation");
is(allowed[0], "*", "allowlist is '*'");
ok(!ifr.contentDocument.policy.allowsFeature("microphone"), "Microphone is disabled for self");
ok(!ifr.contentDocument.policy.allowsFeature("microphone", location.origin), "Microphone is disabled for self");
ok(!ifr.contentDocument.policy.allowsFeature("microphone", "http://foo.bar"), "Microphone is disabled for foo.bar");
- ok(!ifr.contentDocument.policy.allowsFeature("microphone", "http://example.com"), "Microphone is enabled for example.com");
- ok(!ifr.contentDocument.policy.allowsFeature("microphone", "http://example.org"), "Microphone is enabled for example.org");
+ ok(!ifr.contentDocument.policy.allowsFeature("microphone", "http://example.com"), "Microphone is allowed for example.com");
+ ok(!ifr.contentDocument.policy.allowsFeature("microphone", "http://example.org"), "Microphone is allowed for example.org");
allowed = ifr.contentDocument.policy.getAllowlistForFeature("microphone");
is(allowed.length, 0, "No allowlist for microphone");
ok(!ifr.contentDocument.policy.allowsFeature("vr"), "Vibrate is disabled for self");
ok(!ifr.contentDocument.policy.allowsFeature("vr", location.origin), "Vibrate is disabled for self");
ok(!ifr.contentDocument.policy.allowsFeature("vr", "http://foo.bar"), "Vibrate is disabled for foo.bar");
allowed = ifr.contentDocument.policy.getAllowlistForFeature("vr");
is(allowed.length, 0, "No allowlist for vr");
--- a/dom/xul/XULMenuElement.cpp
+++ b/dom/xul/XULMenuElement.cpp
@@ -20,45 +20,32 @@ namespace mozilla {
namespace dom {
JSObject*
XULMenuElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return XULMenuElement_Binding::Wrap(aCx, this, aGivenProto);
}
-nsIFrame*
-XULMenuElement::GetFrame()
-{
- nsCOMPtr<nsIContent> kungFuDeathGrip = this; // keep a reference
-
- nsCOMPtr<nsIDocument> doc = GetUncomposedDoc();
- if (doc) {
- doc->FlushPendingNotifications(FlushType::Frames);
- }
-
- return GetPrimaryFrame();
-}
-
already_AddRefed<Element>
XULMenuElement::GetActiveChild()
{
- nsMenuFrame* menu = do_QueryFrame(GetFrame());
+ nsMenuFrame* menu = do_QueryFrame(GetPrimaryFrame(FlushType::Frames));
if (menu) {
RefPtr<Element> el;
menu->GetActiveChild(getter_AddRefs(el));
return el.forget();
}
return nullptr;
}
void
XULMenuElement::SetActiveChild(Element* arg)
{
- nsMenuFrame* menu = do_QueryFrame(GetFrame());
+ nsMenuFrame* menu = do_QueryFrame(GetPrimaryFrame(FlushType::Frames));
if (menu) {
menu->SetActiveChild(arg);
}
}
bool
XULMenuElement::HandleKeyPress(KeyboardEvent& keyEvent)
{
@@ -70,17 +57,17 @@ XULMenuElement::HandleKeyPress(KeyboardE
// if event has already been handled, bail
if (keyEvent.DefaultPrevented()) {
return false;
}
if (nsMenuBarListener::IsAccessKeyPressed(&keyEvent))
return false;
- nsMenuFrame* menu = do_QueryFrame(GetFrame());
+ nsMenuFrame* menu = do_QueryFrame(GetPrimaryFrame(FlushType::Frames));
if (!menu) {
return false;
}
nsMenuPopupFrame* popupFrame = menu->GetPopup();
if (!popupFrame) {
return false;
}
@@ -99,17 +86,17 @@ XULMenuElement::HandleKeyPress(KeyboardE
default:
return pm->HandleShortcutNavigation(&keyEvent, popupFrame);
}
}
bool
XULMenuElement::OpenedWithKey()
{
- nsMenuFrame* menuframe = do_QueryFrame(GetFrame());
+ nsMenuFrame* menuframe = do_QueryFrame(GetPrimaryFrame(FlushType::Frames));
if (!menuframe) {
return false;
}
nsIFrame* frame = menuframe->GetParent();
while (frame) {
nsMenuBarFrame* menubar = do_QueryFrame(frame);
if (menubar) {
--- a/dom/xul/XULPopupElement.cpp
+++ b/dom/xul/XULPopupElement.cpp
@@ -28,29 +28,16 @@ NS_NewXULPopupElement(already_AddRefed<m
}
JSObject*
XULPopupElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
{
return XULPopupElement_Binding::Wrap(aCx, this, aGivenProto);
}
-nsIFrame*
-XULPopupElement::GetFrame(bool aFlushLayout)
-{
- nsCOMPtr<nsIContent> kungFuDeathGrip = this; // keep a reference
-
- nsCOMPtr<nsIDocument> doc = GetUncomposedDoc();
- if (doc) {
- doc->FlushPendingNotifications(aFlushLayout ? FlushType::Layout : FlushType::Frames);
- }
-
- return GetPrimaryFrame();
-}
-
void
XULPopupElement::OpenPopup(Element* aAnchorElement,
const StringOrOpenPopupOptions& aOptions,
int32_t aXPos, int32_t aYPos,
bool aIsContextMenu,
bool aAttributesOverride,
Event* aTriggerEvent)
{
@@ -238,17 +225,17 @@ XULPopupElement::GetAnchorNode() const
}
already_AddRefed<DOMRect>
XULPopupElement::GetOuterScreenRect()
{
RefPtr<DOMRect> rect = new DOMRect(ToSupports(this));
// Return an empty rectangle if the popup is not open.
- nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetFrame(false));
+ nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetPrimaryFrame(FlushType::Frames));
if (!menuPopupFrame || !menuPopupFrame->IsOpen()) {
return rect.forget();
}
nsView* view = menuPopupFrame->GetView();
if (view) {
nsIWidget* widget = view->GetWidget();
if (widget) {
@@ -262,17 +249,17 @@ XULPopupElement::GetOuterScreenRect()
}
void
XULPopupElement::GetAlignmentPosition(nsString& positionStr)
{
positionStr.Truncate();
// This needs to flush layout.
- nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetFrame(true));
+ nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetPrimaryFrame(FlushType::Layout));
if (!menuPopupFrame)
return;
int8_t position = menuPopupFrame->GetAlignmentPosition();
switch (position) {
case POPUPPOSITION_AFTERSTART:
positionStr.AssignLiteral("after_start");
break;
@@ -310,33 +297,33 @@ XULPopupElement::GetAlignmentPosition(ns
// Leave as an empty string.
break;
}
}
int32_t
XULPopupElement::AlignmentOffset()
{
- nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetFrame(false));
+ nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetPrimaryFrame(FlushType::Frames));
if (!menuPopupFrame)
return 0;
int32_t pp = mozilla::AppUnitsPerCSSPixel();
// Note that the offset might be along either the X or Y axis, but for the
// sake of simplicity we use a point with only the X axis set so we can
// use ToNearestPixels().
nsPoint appOffset(menuPopupFrame->GetAlignmentOffset(), 0);
nsIntPoint popupOffset = appOffset.ToNearestPixels(pp);
return popupOffset.x;
}
void
XULPopupElement::SetConstraintRect(dom::DOMRectReadOnly& aRect)
{
- nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetFrame(false));
+ nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetPrimaryFrame(FlushType::Frames));
if (menuPopupFrame) {
menuPopupFrame->SetOverrideConstraintRect(
LayoutDeviceIntRect::Truncate(aRect.Left(), aRect.Top(), aRect.Width(), aRect.Height()));
}
}
} // namespace dom
} // namespace mozilla
--- a/dom/xul/nsXULElement.cpp
+++ b/dom/xul/nsXULElement.cpp
@@ -523,34 +523,28 @@ nsXULElement::HasMenu()
{
nsMenuFrame* menu = do_QueryFrame(GetPrimaryFrame());
return menu != nullptr;
}
void
nsXULElement::OpenMenu(bool aOpenFlag)
{
- nsCOMPtr<nsIDocument> doc = GetUncomposedDoc();
- if (doc) {
- doc->FlushPendingNotifications(FlushType::Frames);
- }
+ nsMenuFrame* menu = do_QueryFrame(GetPrimaryFrame(FlushType::Frames));
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
if (pm) {
if (aOpenFlag) {
// Nothing will happen if this element isn't a menu.
pm->ShowMenu(this, false, false);
}
- else {
- nsMenuFrame* menu = do_QueryFrame(GetPrimaryFrame());
- if (menu) {
- nsMenuPopupFrame* popupFrame = menu->GetPopup();
- if (popupFrame) {
- pm->HidePopup(popupFrame->GetContent(), false, true, false, false);
- }
+ else if (menu) {
+ nsMenuPopupFrame* popupFrame = menu->GetPopup();
+ if (popupFrame) {
+ pm->HidePopup(popupFrame->GetContent(), false, true, false, false);
}
}
}
}
bool
nsXULElement::PerformAccesskey(bool aKeyCausesActivation,
bool aIsTrustedEvent)
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1498980.js
@@ -0,0 +1,24 @@
+dbgGlobal = newGlobal();
+dbg = new dbgGlobal.Debugger;
+dbg.addDebuggee(this);
+
+function f() {
+ dbg.getNewestFrame().older.eval("");
+}
+
+function execModule(source) {
+ m = parseModule(source);
+ m.declarationInstantiation();
+ m.evaluation();
+}
+
+execModule("f();");
+gc();
+
+let caught;
+try {
+ execModule("throw 'foo'");
+} catch (e) {
+ caught = e;
+}
+assertEq(caught, 'foo');
--- a/js/src/vm/EnvironmentObject.cpp
+++ b/js/src/vm/EnvironmentObject.cpp
@@ -2802,20 +2802,21 @@ DebugEnvironments::takeFrameSnapshot(JSC
* copy of the unaliased variables' values in an array for later debugger
* access via DebugEnvironmentProxy::handleUnaliasedAccess.
*
* Note: since it is simplest for this function to be infallible, failure
* in this code will be silently ignored. This does not break any
* invariants since DebugEnvironmentProxy::maybeSnapshot can already be nullptr.
*/
+ JSScript* script = frame.script();
+
// Act like no snapshot was taken if we run OOM while taking the snapshot.
Rooted<GCVector<Value>> vec(cx, GCVector<Value>(cx));
if (debugEnv->environment().is<CallObject>()) {
- JSScript* script = frame.script();
FunctionScope* scope = &script->bodyScope()->as<FunctionScope>();
uint32_t frameSlotCount = scope->nextFrameSlot();
MOZ_ASSERT(frameSlotCount <= script->nfixed());
// For simplicity, copy all frame slots from 0 to the frameSlotCount,
// even if we don't need all of them (like in the case of a defaults
// parameter scope having frame slots).
@@ -2843,32 +2844,38 @@ DebugEnvironments::takeFrameSnapshot(JSC
} else {
uint32_t frameSlotStart;
uint32_t frameSlotEnd;
if (debugEnv->environment().is<LexicalEnvironmentObject>()) {
LexicalScope* scope = &debugEnv->environment().as<LexicalEnvironmentObject>().scope();
frameSlotStart = scope->firstFrameSlot();
frameSlotEnd = scope->nextFrameSlot();
- } else {
+ } else if (debugEnv->environment().is<VarEnvironmentObject>()) {
VarEnvironmentObject* env = &debugEnv->environment().as<VarEnvironmentObject>();
if (frame.isFunctionFrame()) {
VarScope* scope = &env->scope().as<VarScope>();
frameSlotStart = scope->firstFrameSlot();
frameSlotEnd = scope->nextFrameSlot();
} else {
EvalScope* scope = &env->scope().as<EvalScope>();
- MOZ_ASSERT(scope == frame.script()->bodyScope());
+ MOZ_ASSERT(scope == script->bodyScope());
frameSlotStart = 0;
frameSlotEnd = scope->nextFrameSlot();
}
+ } else {
+ MOZ_ASSERT(&debugEnv->environment().as<ModuleEnvironmentObject>() ==
+ script->module()->environment());
+ ModuleScope* scope = &script->bodyScope()->as<ModuleScope>();
+ frameSlotStart = 0;
+ frameSlotEnd = scope->nextFrameSlot();
}
uint32_t frameSlotCount = frameSlotEnd - frameSlotStart;
- MOZ_ASSERT(frameSlotCount <= frame.script()->nfixed());
+ MOZ_ASSERT(frameSlotCount <= script->nfixed());
if (!vec.resize(frameSlotCount)) {
cx->recoverFromOutOfMemory();
return;
}
for (uint32_t slot = frameSlotStart; slot < frameSlotCount; slot++) {
vec[slot - frameSlotStart].set(frame.unaliasedLocal(slot));
}
@@ -3018,16 +3025,22 @@ DebugEnvironments::onPopWith(AbstractFra
{
Realm* realm = frame.realm();
if (DebugEnvironments* envs = realm->debugEnvs()) {
envs->liveEnvs.remove(&frame.environmentChain()->as<WithEnvironmentObject>());
}
}
void
+DebugEnvironments::onPopModule(JSContext* cx, const EnvironmentIter& ei)
+{
+ onPopGeneric<ModuleEnvironmentObject, ModuleScope>(cx, ei);
+}
+
+void
DebugEnvironments::onRealmUnsetIsDebuggee(Realm* realm)
{
if (DebugEnvironments* envs = realm->debugEnvs()) {
envs->proxiedEnvs.clear();
envs->missingEnvs.clear();
envs->liveEnvs.clear();
}
}
--- a/js/src/vm/EnvironmentObject.h
+++ b/js/src/vm/EnvironmentObject.h
@@ -1049,16 +1049,17 @@ class DebugEnvironments
// In debug-mode, these must be called whenever exiting a scope that might
// have stack-allocated locals.
static void onPopCall(JSContext* cx, AbstractFramePtr frame);
static void onPopVar(JSContext* cx, const EnvironmentIter& ei);
static void onPopVar(JSContext* cx, AbstractFramePtr frame, jsbytecode* pc);
static void onPopLexical(JSContext* cx, const EnvironmentIter& ei);
static void onPopLexical(JSContext* cx, AbstractFramePtr frame, jsbytecode* pc);
static void onPopWith(AbstractFramePtr frame);
+ static void onPopModule(JSContext* cx, const EnvironmentIter& ei);
static void onRealmUnsetIsDebuggee(Realm* realm);
};
} /* namespace js */
template <>
inline bool
JSObject::is<js::EnvironmentObject>() const
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -1238,20 +1238,24 @@ PopEnvironment(JSContext* cx, Environmen
case ScopeKind::StrictEval:
if (MOZ_UNLIKELY(cx->realm()->isDebuggee())) {
DebugEnvironments::onPopVar(cx, ei);
}
if (ei.scope().hasEnvironment()) {
ei.initialFrame().popOffEnvironmentChain<VarEnvironmentObject>();
}
break;
+ case ScopeKind::Module:
+ if (MOZ_UNLIKELY(cx->realm()->isDebuggee())) {
+ DebugEnvironments::onPopModule(cx, ei);
+ }
+ break;
case ScopeKind::Eval:
case ScopeKind::Global:
case ScopeKind::NonSyntactic:
- case ScopeKind::Module:
break;
case ScopeKind::WasmInstance:
case ScopeKind::WasmFunction:
MOZ_CRASH("wasm is not interpreted");
break;
}
}
--- a/netwerk/base/PartiallySeekableInputStream.cpp
+++ b/netwerk/base/PartiallySeekableInputStream.cpp
@@ -12,16 +12,17 @@ namespace mozilla {
namespace net {
NS_IMPL_ADDREF(PartiallySeekableInputStream);
NS_IMPL_RELEASE(PartiallySeekableInputStream);
NS_INTERFACE_MAP_BEGIN(PartiallySeekableInputStream)
NS_INTERFACE_MAP_ENTRY(nsIInputStream)
NS_INTERFACE_MAP_ENTRY(nsISeekableStream)
+ NS_INTERFACE_MAP_ENTRY(nsITellableStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsICloneableInputStream,
mWeakCloneableInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream,
mWeakIPCSerializableInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAsyncInputStream,
mWeakAsyncInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIInputStreamCallback,
mWeakAsyncInputStream)
--- a/netwerk/base/PartiallySeekableInputStream.h
+++ b/netwerk/base/PartiallySeekableInputStream.h
@@ -29,16 +29,17 @@ class PartiallySeekableInputStream final
, public nsIInputStreamLength
, public nsIAsyncInputStreamLength
, public nsIInputStreamLengthCallback
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIINPUTSTREAM
NS_DECL_NSISEEKABLESTREAM
+ NS_DECL_NSITELLABLESTREAM
NS_DECL_NSIASYNCINPUTSTREAM
NS_DECL_NSICLONEABLEINPUTSTREAM
NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
NS_DECL_NSIINPUTSTREAMCALLBACK
NS_DECL_NSIINPUTSTREAMLENGTH
NS_DECL_NSIASYNCINPUTSTREAMLENGTH
NS_DECL_NSIINPUTSTREAMLENGTHCALLBACK
--- a/netwerk/base/ThrottleQueue.cpp
+++ b/netwerk/base/ThrottleQueue.cpp
@@ -21,33 +21,35 @@ class ThrottleInputStream final
{
public:
ThrottleInputStream(nsIInputStream* aStream, ThrottleQueue* aQueue);
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIINPUTSTREAM
NS_DECL_NSISEEKABLESTREAM
+ NS_DECL_NSITELLABLESTREAM
NS_DECL_NSIASYNCINPUTSTREAM
void AllowInput();
private:
~ThrottleInputStream();
nsCOMPtr<nsIInputStream> mStream;
RefPtr<ThrottleQueue> mQueue;
nsresult mClosedStatus;
nsCOMPtr<nsIInputStreamCallback> mCallback;
nsCOMPtr<nsIEventTarget> mEventTarget;
};
-NS_IMPL_ISUPPORTS(ThrottleInputStream, nsIAsyncInputStream, nsIInputStream, nsISeekableStream)
+NS_IMPL_ISUPPORTS(ThrottleInputStream, nsIAsyncInputStream, nsIInputStream,
+ nsITellableStream, nsISeekableStream)
ThrottleInputStream::ThrottleInputStream(nsIInputStream *aStream, ThrottleQueue* aQueue)
: mStream(aStream)
, mQueue(aQueue)
, mClosedStatus(NS_OK)
{
MOZ_ASSERT(aQueue != nullptr);
}
@@ -155,17 +157,17 @@ ThrottleInputStream::Seek(int32_t aWhenc
NS_IMETHODIMP
ThrottleInputStream::Tell(int64_t* aResult)
{
if (NS_FAILED(mClosedStatus)) {
return mClosedStatus;
}
- nsCOMPtr<nsISeekableStream> sstream = do_QueryInterface(mStream);
+ nsCOMPtr<nsITellableStream> sstream = do_QueryInterface(mStream);
if (!sstream) {
return NS_ERROR_FAILURE;
}
return sstream->Tell(aResult);
}
NS_IMETHODIMP
--- a/netwerk/base/nsBufferedStreams.cpp
+++ b/netwerk/base/nsBufferedStreams.cpp
@@ -58,17 +58,17 @@ nsBufferedStream::nsBufferedStream()
{
}
nsBufferedStream::~nsBufferedStream()
{
Close();
}
-NS_IMPL_ISUPPORTS(nsBufferedStream, nsISeekableStream)
+NS_IMPL_ISUPPORTS(nsBufferedStream, nsITellableStream, nsISeekableStream)
nsresult
nsBufferedStream::Init(nsISupports* stream, uint32_t bufferSize)
{
NS_ASSERTION(stream, "need to supply a stream");
NS_ASSERTION(mStream == nullptr, "already inited");
mStream = stream;
NS_IF_ADDREF(mStream);
@@ -300,16 +300,17 @@ NS_INTERFACE_MAP_BEGIN(nsBufferedInputSt
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIInputStreamLengthCallback, mIsAsyncInputStreamLength)
NS_IMPL_QUERY_CLASSINFO(nsBufferedInputStream)
NS_INTERFACE_MAP_END_INHERITING(nsBufferedStream)
NS_IMPL_CI_INTERFACE_GETTER(nsBufferedInputStream,
nsIInputStream,
nsIBufferedInputStream,
nsISeekableStream,
+ nsITellableStream,
nsIStreamBufferAccess)
nsBufferedInputStream::nsBufferedInputStream()
: nsBufferedStream()
, mMutex("nsBufferedInputStream::mMutex")
, mIsIPCSerializable(true)
, mIsAsyncInputStream(false)
, mIsCloneableInputStream(false)
--- a/netwerk/base/nsBufferedStreams.h
+++ b/netwerk/base/nsBufferedStreams.h
@@ -21,16 +21,17 @@
////////////////////////////////////////////////////////////////////////////////
class nsBufferedStream : public nsISeekableStream
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSISEEKABLESTREAM
+ NS_DECL_NSITELLABLESTREAM
nsBufferedStream();
nsresult Close();
protected:
virtual ~nsBufferedStream();
--- a/netwerk/base/nsFileStreams.cpp
+++ b/netwerk/base/nsFileStreams.cpp
@@ -56,16 +56,17 @@ nsFileStreamBase::~nsFileStreamBase()
// We don't want to try to rewrind the stream when shutting down.
mBehaviorFlags &= ~nsIFileInputStream::REOPEN_ON_REWIND;
Close();
}
NS_IMPL_ISUPPORTS(nsFileStreamBase,
nsISeekableStream,
+ nsITellableStream,
nsIFileMetadata)
NS_IMETHODIMP
nsFileStreamBase::Seek(int32_t whence, int64_t offset)
{
nsresult rv = DoPendingOpen();
NS_ENSURE_SUCCESS(rv, rv);
@@ -437,16 +438,17 @@ NS_INTERFACE_MAP_BEGIN(nsFileInputStream
NS_IMPL_QUERY_CLASSINFO(nsFileInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsICloneableInputStream, IsCloneable())
NS_INTERFACE_MAP_END_INHERITING(nsFileStreamBase)
NS_IMPL_CI_INTERFACE_GETTER(nsFileInputStream,
nsIInputStream,
nsIFileInputStream,
nsISeekableStream,
+ nsITellableStream,
nsILineInputStream)
nsresult
nsFileInputStream::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
{
NS_ENSURE_NO_AGGREGATION(aOuter);
RefPtr<nsFileInputStream> stream = new nsFileInputStream();
--- a/netwerk/base/nsFileStreams.h
+++ b/netwerk/base/nsFileStreams.h
@@ -26,16 +26,17 @@
class nsFileStreamBase : public nsISeekableStream,
public nsIFileMetadata
{
public:
// Record refcount changes to ensure that streams are destroyed on
// consistent threads when recording/replaying.
NS_DECL_THREADSAFE_ISUPPORTS_WITH_RECORDING(mozilla::recordreplay::Behavior::Preserve)
NS_DECL_NSISEEKABLESTREAM
+ NS_DECL_NSITELLABLESTREAM
NS_DECL_NSIFILEMETADATA
nsFileStreamBase();
protected:
virtual ~nsFileStreamBase();
nsresult Close();
--- a/netwerk/base/nsInputStreamPump.cpp
+++ b/netwerk/base/nsInputStreamPump.cpp
@@ -569,20 +569,20 @@ nsInputStreamPump::OnStateTransfer()
// however, many do not... mailnews... stream converters...
// cough, cough. the input stream pump is fairly tolerant
// in this regard; however, if an ODA does not consume any
// data from the stream, then we could potentially end up in
// an infinite loop. we do our best here to try to catch
// such an error. (see bug 189672)
// in most cases this QI will succeed (mAsyncStream is almost always
- // a nsPipeInputStream, which implements nsISeekableStream::Tell).
+ // a nsPipeInputStream, which implements nsITellableStream::Tell).
int64_t offsetBefore;
- nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mAsyncStream);
- if (seekable && NS_FAILED(seekable->Tell(&offsetBefore))) {
+ nsCOMPtr<nsITellableStream> tellable = do_QueryInterface(mAsyncStream);
+ if (tellable && NS_FAILED(tellable->Tell(&offsetBefore))) {
MOZ_ASSERT_UNREACHABLE("Tell failed on readable stream");
offsetBefore = 0;
}
uint32_t odaAvail =
avail > UINT32_MAX ?
UINT32_MAX : uint32_t(avail);
@@ -597,21 +597,21 @@ nsInputStreamPump::OnStateTransfer()
rv = mListener->OnDataAvailable(this, mListenerContext,
mAsyncStream, mStreamOffset,
odaAvail);
}
// don't enter this code if ODA failed or called Cancel
if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(mStatus)) {
// test to see if this ODA failed to consume data
- if (seekable) {
+ if (tellable) {
// NOTE: if Tell fails, which can happen if the stream is
// now closed, then we assume that everything was read.
int64_t offsetAfter;
- if (NS_FAILED(seekable->Tell(&offsetAfter)))
+ if (NS_FAILED(tellable->Tell(&offsetAfter)))
offsetAfter = offsetBefore + odaAvail;
if (offsetAfter > offsetBefore)
mStreamOffset += (offsetAfter - offsetBefore);
else if (mSuspendCount == 0) {
//
// possible infinite loop if we continue pumping data!
//
// NOTE: although not allowed by nsIStreamListener, we
--- a/netwerk/base/nsMIMEInputStream.cpp
+++ b/netwerk/base/nsMIMEInputStream.cpp
@@ -42,16 +42,17 @@ class nsMIMEInputStream : public nsIMIME
public:
nsMIMEInputStream();
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIINPUTSTREAM
NS_DECL_NSIMIMEINPUTSTREAM
NS_DECL_NSISEEKABLESTREAM
+ NS_DECL_NSITELLABLESTREAM
NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
NS_DECL_NSIASYNCINPUTSTREAM
NS_DECL_NSIINPUTSTREAMCALLBACK
NS_DECL_NSIINPUTSTREAMLENGTH
NS_DECL_NSIASYNCINPUTSTREAMLENGTH
NS_DECL_NSIINPUTSTREAMLENGTHCALLBACK
NS_DECL_NSICLONEABLEINPUTSTREAM
@@ -93,16 +94,17 @@ NS_IMPL_RELEASE(nsMIMEInputStream)
NS_IMPL_CLASSINFO(nsMIMEInputStream, nullptr, nsIClassInfo::THREADSAFE,
NS_MIMEINPUTSTREAM_CID)
NS_INTERFACE_MAP_BEGIN(nsMIMEInputStream)
NS_INTERFACE_MAP_ENTRY(nsIMIMEInputStream)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIInputStream, nsIMIMEInputStream)
NS_INTERFACE_MAP_ENTRY(nsISeekableStream)
+ NS_INTERFACE_MAP_ENTRY(nsITellableStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream,
IsIPCSerializable())
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAsyncInputStream,
IsAsyncInputStream())
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIInputStreamCallback,
IsAsyncInputStream())
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIMIMEInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIInputStreamLength,
@@ -115,17 +117,18 @@ NS_INTERFACE_MAP_BEGIN(nsMIMEInputStream
IsCloneableInputStream())
NS_IMPL_QUERY_CLASSINFO(nsMIMEInputStream)
NS_INTERFACE_MAP_END
NS_IMPL_CI_INTERFACE_GETTER(nsMIMEInputStream,
nsIMIMEInputStream,
nsIAsyncInputStream,
nsIInputStream,
- nsISeekableStream)
+ nsISeekableStream,
+ nsITellableStream)
nsMIMEInputStream::nsMIMEInputStream()
: mStartedReading(false)
, mMutex("nsMIMEInputStream::mMutex")
{
}
NS_IMETHODIMP
@@ -307,23 +310,25 @@ nsMIMEInputStream::OnInputStreamReady(ns
callback.swap(mAsyncWaitCallback);
}
MOZ_ASSERT(callback);
return callback->OnInputStreamReady(this);
}
-// nsISeekableStream
+// nsITellableStream
NS_IMETHODIMP nsMIMEInputStream::Tell(int64_t *_retval)
{
INITSTREAMS;
- nsCOMPtr<nsISeekableStream> stream = do_QueryInterface(mStream);
+ nsCOMPtr<nsITellableStream> stream = do_QueryInterface(mStream);
return stream->Tell(_retval);
}
+
+// nsISeekableStream
NS_IMETHODIMP nsMIMEInputStream::SetEOF(void) {
INITSTREAMS;
nsCOMPtr<nsISeekableStream> stream = do_QueryInterface(mStream);
return stream->SetEOF();
}
/**
--- a/netwerk/cache2/CacheFileInputStream.cpp
+++ b/netwerk/cache2/CacheFileInputStream.cpp
@@ -33,16 +33,17 @@ CacheFileInputStream::Release()
return count;
}
NS_INTERFACE_MAP_BEGIN(CacheFileInputStream)
NS_INTERFACE_MAP_ENTRY(nsIInputStream)
NS_INTERFACE_MAP_ENTRY(nsIAsyncInputStream)
NS_INTERFACE_MAP_ENTRY(nsISeekableStream)
+ NS_INTERFACE_MAP_ENTRY(nsITellableStream)
NS_INTERFACE_MAP_ENTRY(mozilla::net::CacheFileChunkListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
NS_INTERFACE_MAP_END
CacheFileInputStream::CacheFileInputStream(CacheFile *aFile,
nsISupports *aEntry,
bool aAlternativeData)
: mFile(aFile)
@@ -384,16 +385,24 @@ CacheFileInputStream::Seek(int32_t whenc
mPos = newPos;
EnsureCorrectChunk(false);
LOG(("CacheFileInputStream::Seek() [this=%p, pos=%" PRId64 "]", this, mPos));
return NS_OK;
}
NS_IMETHODIMP
+CacheFileInputStream::SetEOF()
+{
+ MOZ_ASSERT(false, "Don't call SetEOF on cache input stream");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+// nsITellableStream
+NS_IMETHODIMP
CacheFileInputStream::Tell(int64_t *_retval)
{
CacheFileAutoLock lock(mFile);
if (mClosed) {
LOG(("CacheFileInputStream::Tell() - Stream is closed. [this=%p]", this));
return NS_BASE_STREAM_CLOSED;
}
@@ -403,23 +412,16 @@ CacheFileInputStream::Tell(int64_t *_ret
if (mAlternativeData) {
*_retval -= mFile->mAltDataOffset;
}
LOG(("CacheFileInputStream::Tell() [this=%p, retval=%" PRId64 "]", this, *_retval));
return NS_OK;
}
-NS_IMETHODIMP
-CacheFileInputStream::SetEOF()
-{
- MOZ_ASSERT(false, "Don't call SetEOF on cache input stream");
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
// CacheFileChunkListener
nsresult
CacheFileInputStream::OnChunkRead(nsresult aResult, CacheFileChunk *aChunk)
{
MOZ_CRASH("CacheFileInputStream::OnChunkRead should not be called!");
return NS_ERROR_UNEXPECTED;
}
--- a/netwerk/cache2/CacheFileInputStream.h
+++ b/netwerk/cache2/CacheFileInputStream.h
@@ -19,16 +19,17 @@ class CacheFile;
class CacheFileInputStream : public nsIAsyncInputStream
, public nsISeekableStream
, public CacheFileChunkListener
{
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIINPUTSTREAM
NS_DECL_NSIASYNCINPUTSTREAM
NS_DECL_NSISEEKABLESTREAM
+ NS_DECL_NSITELLABLESTREAM
public:
explicit CacheFileInputStream(CacheFile *aFile, nsISupports *aEntry,
bool aAlternativeData);
NS_IMETHOD OnChunkRead(nsresult aResult, CacheFileChunk *aChunk) override;
NS_IMETHOD OnChunkWritten(nsresult aResult, CacheFileChunk *aChunk) override;
NS_IMETHOD OnChunkAvailable(nsresult aResult, uint32_t aChunkIdx,
--- a/netwerk/cache2/CacheFileOutputStream.cpp
+++ b/netwerk/cache2/CacheFileOutputStream.cpp
@@ -35,16 +35,17 @@ CacheFileOutputStream::Release()
return count;
}
NS_INTERFACE_MAP_BEGIN(CacheFileOutputStream)
NS_INTERFACE_MAP_ENTRY(nsIOutputStream)
NS_INTERFACE_MAP_ENTRY(nsIAsyncOutputStream)
NS_INTERFACE_MAP_ENTRY(nsISeekableStream)
+ NS_INTERFACE_MAP_ENTRY(nsITellableStream)
NS_INTERFACE_MAP_ENTRY(mozilla::net::CacheFileChunkListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIOutputStream)
NS_INTERFACE_MAP_END
CacheFileOutputStream::CacheFileOutputStream(CacheFile *aFile,
CacheOutputCloseListener *aCloseListener,
bool aAlternativeData)
: mFile(aFile)
@@ -284,16 +285,27 @@ CacheFileOutputStream::Seek(int32_t when
mPos = newPos;
EnsureCorrectChunk(true);
LOG(("CacheFileOutputStream::Seek() [this=%p, pos=%" PRId64 "]", this, mPos));
return NS_OK;
}
NS_IMETHODIMP
+CacheFileOutputStream::SetEOF()
+{
+ MOZ_ASSERT(false, "CacheFileOutputStream::SetEOF() not implemented");
+ // Right now we don't use SetEOF(). If we ever need this method, we need
+ // to think about what to do with input streams that already points beyond
+ // new EOF.
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+// nsITellableStream
+NS_IMETHODIMP
CacheFileOutputStream::Tell(int64_t *_retval)
{
CacheFileAutoLock lock(mFile);
if (mClosed) {
LOG(("CacheFileOutputStream::Tell() - Stream is closed. [this=%p]", this));
return NS_BASE_STREAM_CLOSED;
}
@@ -303,26 +315,16 @@ CacheFileOutputStream::Tell(int64_t *_re
if (mAlternativeData) {
*_retval -= mFile->mAltDataOffset;
}
LOG(("CacheFileOutputStream::Tell() [this=%p, retval=%" PRId64 "]", this, *_retval));
return NS_OK;
}
-NS_IMETHODIMP
-CacheFileOutputStream::SetEOF()
-{
- MOZ_ASSERT(false, "CacheFileOutputStream::SetEOF() not implemented");
- // Right now we don't use SetEOF(). If we ever need this method, we need
- // to think about what to do with input streams that already points beyond
- // new EOF.
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
// CacheFileChunkListener
nsresult
CacheFileOutputStream::OnChunkRead(nsresult aResult, CacheFileChunk *aChunk)
{
MOZ_CRASH("CacheFileOutputStream::OnChunkRead should not be called!");
return NS_ERROR_UNEXPECTED;
}
--- a/netwerk/cache2/CacheFileOutputStream.h
+++ b/netwerk/cache2/CacheFileOutputStream.h
@@ -21,16 +21,17 @@ class CacheOutputCloseListener;
class CacheFileOutputStream : public nsIAsyncOutputStream
, public nsISeekableStream
, public CacheFileChunkListener
{
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIOUTPUTSTREAM
NS_DECL_NSIASYNCOUTPUTSTREAM
NS_DECL_NSISEEKABLESTREAM
+ NS_DECL_NSITELLABLESTREAM
public:
CacheFileOutputStream(CacheFile *aFile,
CacheOutputCloseListener *aCloseListener,
bool aAlternativeData);
NS_IMETHOD OnChunkRead(nsresult aResult, CacheFileChunk *aChunk) override;
NS_IMETHOD OnChunkWritten(nsresult aResult, CacheFileChunk *aChunk) override;
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -915,24 +915,20 @@ HttpBaseChannel::EnsureUploadStreamIsClo
NS_ENSURE_FALSE(mUploadCloneableCallback, NS_ERROR_UNEXPECTED);
// We can immediately exec the callback if we don't have an upload stream.
if (!mUploadStream) {
aCallback->Run();
return NS_OK;
}
- // Some nsSeekableStreams do not implement ::Seek() (see nsPipeInputStream).
- // In this case, we must clone the uploadStream into a memory stream in order
- // to have it seekable. If the CloneUploadStream() will succeed, then
- // synchronously invoke the callback to indicate we're already cloneable.
+ // Upload nsIInputStream must be cloneable and seekable in order to be
+ // processed by devtools network inspector.
nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mUploadStream);
- if (seekable &&
- NS_SUCCEEDED(seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0)) &&
- NS_InputStreamIsCloneable(mUploadStream)) {
+ if (seekable && NS_InputStreamIsCloneable(mUploadStream)) {
aCallback->Run();
return NS_OK;
}
nsCOMPtr<nsIStorageStream> storageStream;
nsresult rv = NS_NewStorageStream(4096, UINT32_MAX,
getter_AddRefs(storageStream));
NS_ENSURE_SUCCESS(rv, rv);
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/css/css-conditional/at-supports-040.html.ini
@@ -0,0 +1,3 @@
+[at-supports-040.html]
+ type: reftest
+ prefs: [layout.css.supports-selector.enabled:true]
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/css/css-conditional/at-supports-041.html.ini
@@ -0,0 +1,3 @@
+[at-supports-041.html]
+ type: reftest
+ prefs: [layout.css.supports-selector.enabled:true]
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/css/css-conditional/at-supports-042.html.ini
@@ -0,0 +1,3 @@
+[at-supports-042.html]
+ type: reftest
+ prefs: [layout.css.supports-selector.enabled:true]
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/css/cssom/CSS.html.ini
@@ -0,0 +1,2 @@
+[CSS.html]
+ prefs: [layout.css.supports-selector.enabled:true]
--- a/xpcom/io/InputStreamLengthWrapper.cpp
+++ b/xpcom/io/InputStreamLengthWrapper.cpp
@@ -19,16 +19,18 @@ NS_IMPL_RELEASE(InputStreamLengthWrapper
NS_INTERFACE_MAP_BEGIN(InputStreamLengthWrapper)
NS_INTERFACE_MAP_ENTRY(nsIInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsICloneableInputStream,
mWeakCloneableInputStream || !mInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream,
mWeakIPCSerializableInputStream || !mInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISeekableStream,
mWeakSeekableInputStream || !mInputStream)
+ NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsITellableStream,
+ mWeakTellableInputStream || !mInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAsyncInputStream,
mWeakAsyncInputStream || !mInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIInputStreamCallback,
mWeakAsyncInputStream || !mInputStream)
NS_INTERFACE_MAP_ENTRY(nsIInputStreamLength)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
NS_INTERFACE_MAP_END
@@ -58,31 +60,33 @@ InputStreamLengthWrapper::MaybeWrap(alre
return inputStream.forget();
}
InputStreamLengthWrapper::InputStreamLengthWrapper(already_AddRefed<nsIInputStream> aInputStream,
int64_t aLength)
: mWeakCloneableInputStream(nullptr)
, mWeakIPCSerializableInputStream(nullptr)
, mWeakSeekableInputStream(nullptr)
+ , mWeakTellableInputStream(nullptr)
, mWeakAsyncInputStream(nullptr)
, mLength(aLength)
, mConsumed(false)
, mMutex("InputStreamLengthWrapper::mMutex")
{
MOZ_ASSERT(mLength >= 0);
nsCOMPtr<nsIInputStream> inputStream = std::move(aInputStream);
SetSourceStream(inputStream.forget());
}
InputStreamLengthWrapper::InputStreamLengthWrapper()
: mWeakCloneableInputStream(nullptr)
, mWeakIPCSerializableInputStream(nullptr)
, mWeakSeekableInputStream(nullptr)
+ , mWeakTellableInputStream(nullptr)
, mWeakAsyncInputStream(nullptr)
, mLength(-1)
, mConsumed(false)
, mMutex("InputStreamLengthWrapper::mMutex")
{}
InputStreamLengthWrapper::~InputStreamLengthWrapper() = default;
@@ -107,16 +111,22 @@ InputStreamLengthWrapper::SetSourceStrea
}
nsCOMPtr<nsISeekableStream> seekableStream =
do_QueryInterface(mInputStream);
if (seekableStream && SameCOMIdentity(mInputStream, seekableStream)) {
mWeakSeekableInputStream = seekableStream;
}
+ nsCOMPtr<nsITellableStream> tellableStream =
+ do_QueryInterface(mInputStream);
+ if (tellableStream && SameCOMIdentity(mInputStream, tellableStream)) {
+ mWeakTellableInputStream = tellableStream;
+ }
+
nsCOMPtr<nsIAsyncInputStream> asyncInputStream =
do_QueryInterface(mInputStream);
if (asyncInputStream && SameCOMIdentity(mInputStream, asyncInputStream)) {
mWeakAsyncInputStream = asyncInputStream;
}
}
// nsIInputStream interface
@@ -326,34 +336,36 @@ InputStreamLengthWrapper::Seek(int32_t a
NS_ENSURE_STATE(mInputStream);
NS_ENSURE_STATE(mWeakSeekableInputStream);
mConsumed = true;
return mWeakSeekableInputStream->Seek(aWhence, aOffset);
}
NS_IMETHODIMP
-InputStreamLengthWrapper::Tell(int64_t *aResult)
-{
- NS_ENSURE_STATE(mInputStream);
- NS_ENSURE_STATE(mWeakSeekableInputStream);
-
- return mWeakSeekableInputStream->Tell(aResult);
-}
-
-NS_IMETHODIMP
InputStreamLengthWrapper::SetEOF()
{
NS_ENSURE_STATE(mInputStream);
NS_ENSURE_STATE(mWeakSeekableInputStream);
mConsumed = true;
return mWeakSeekableInputStream->SetEOF();
}
+// nsITellableStream
+
+NS_IMETHODIMP
+InputStreamLengthWrapper::Tell(int64_t *aResult)
+{
+ NS_ENSURE_STATE(mInputStream);
+ NS_ENSURE_STATE(mWeakTellableInputStream);
+
+ return mWeakTellableInputStream->Tell(aResult);
+}
+
// nsIInputStreamLength
NS_IMETHODIMP
InputStreamLengthWrapper::Length(int64_t* aLength)
{
NS_ENSURE_STATE(mInputStream);
*aLength = mLength;
return NS_OK;
--- a/xpcom/io/InputStreamLengthWrapper.h
+++ b/xpcom/io/InputStreamLengthWrapper.h
@@ -31,16 +31,17 @@ class InputStreamLengthWrapper final : p
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIINPUTSTREAM
NS_DECL_NSIASYNCINPUTSTREAM
NS_DECL_NSICLONEABLEINPUTSTREAM
NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
NS_DECL_NSISEEKABLESTREAM
+ NS_DECL_NSITELLABLESTREAM
NS_DECL_NSIINPUTSTREAMCALLBACK
NS_DECL_NSIINPUTSTREAMLENGTH
// This method creates a InputStreamLengthWrapper around aInputStream if
// this doesn't implement nsIInputStreamLength or
// nsIInputStreamAsyncLength interface, but it implements
// nsIAsyncInputStream. For this kind of streams,
// InputStreamLengthHelper is not able to retrieve the length. This
@@ -64,16 +65,17 @@ private:
SetSourceStream(already_AddRefed<nsIInputStream> aInputStream);
nsCOMPtr<nsIInputStream> mInputStream;
// Raw pointers because these are just QI of mInputStream.
nsICloneableInputStream* mWeakCloneableInputStream;
nsIIPCSerializableInputStream* mWeakIPCSerializableInputStream;
nsISeekableStream* mWeakSeekableInputStream;
+ nsITellableStream* mWeakTellableInputStream;
nsIAsyncInputStream* mWeakAsyncInputStream;
int64_t mLength;
bool mConsumed;
mozilla::Mutex mMutex;
// This is used for AsyncWait and it's protected by mutex.
--- a/xpcom/io/NonBlockingAsyncInputStream.cpp
+++ b/xpcom/io/NonBlockingAsyncInputStream.cpp
@@ -46,16 +46,18 @@ NS_INTERFACE_MAP_BEGIN(NonBlockingAsyncI
NS_INTERFACE_MAP_ENTRY(nsIInputStream)
NS_INTERFACE_MAP_ENTRY(nsIAsyncInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsICloneableInputStream,
mWeakCloneableInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream,
mWeakIPCSerializableInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISeekableStream,
mWeakSeekableInputStream)
+ NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsITellableStream,
+ mWeakTellableInputStream)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
NS_INTERFACE_MAP_END
/* static */ nsresult
NonBlockingAsyncInputStream::Create(already_AddRefed<nsIInputStream> aInputStream,
nsIAsyncInputStream** aResult)
{
MOZ_DIAGNOSTIC_ASSERT(aResult);
@@ -83,16 +85,17 @@ NonBlockingAsyncInputStream::Create(alre
return NS_OK;
}
NonBlockingAsyncInputStream::NonBlockingAsyncInputStream(already_AddRefed<nsIInputStream> aInputStream)
: mInputStream(std::move(aInputStream))
, mWeakCloneableInputStream(nullptr)
, mWeakIPCSerializableInputStream(nullptr)
, mWeakSeekableInputStream(nullptr)
+ , mWeakTellableInputStream(nullptr)
, mLock("NonBlockingAsyncInputStream::mLock")
, mClosed(false)
{
MOZ_ASSERT(mInputStream);
nsCOMPtr<nsICloneableInputStream> cloneableStream =
do_QueryInterface(mInputStream);
if (cloneableStream && SameCOMIdentity(mInputStream, cloneableStream)) {
@@ -106,16 +109,22 @@ NonBlockingAsyncInputStream::NonBlocking
mWeakIPCSerializableInputStream = serializableStream;
}
nsCOMPtr<nsISeekableStream> seekableStream =
do_QueryInterface(mInputStream);
if (seekableStream && SameCOMIdentity(mInputStream, seekableStream)) {
mWeakSeekableInputStream = seekableStream;
}
+
+ nsCOMPtr<nsITellableStream> tellableStream =
+ do_QueryInterface(mInputStream);
+ if (tellableStream && SameCOMIdentity(mInputStream, tellableStream)) {
+ mWeakTellableInputStream = tellableStream;
+ }
}
NonBlockingAsyncInputStream::~NonBlockingAsyncInputStream()
{}
NS_IMETHODIMP
NonBlockingAsyncInputStream::Close()
{
@@ -346,29 +355,31 @@ NonBlockingAsyncInputStream::ExpectedSer
NS_IMETHODIMP
NonBlockingAsyncInputStream::Seek(int32_t aWhence, int64_t aOffset)
{
NS_ENSURE_STATE(mWeakSeekableInputStream);
return mWeakSeekableInputStream->Seek(aWhence, aOffset);
}
NS_IMETHODIMP
-NonBlockingAsyncInputStream::Tell(int64_t* aResult)
-{
- NS_ENSURE_STATE(mWeakSeekableInputStream);
- return mWeakSeekableInputStream->Tell(aResult);
-}
-
-NS_IMETHODIMP
NonBlockingAsyncInputStream::SetEOF()
{
NS_ENSURE_STATE(mWeakSeekableInputStream);
return NS_ERROR_NOT_IMPLEMENTED;
}
+// nsITellableStream
+
+NS_IMETHODIMP
+NonBlockingAsyncInputStream::Tell(int64_t* aResult)
+{
+ NS_ENSURE_STATE(mWeakTellableInputStream);
+ return mWeakTellableInputStream->Tell(aResult);
+}
+
void
NonBlockingAsyncInputStream::RunAsyncWaitCallback(NonBlockingAsyncInputStream::AsyncWaitRunnable* aRunnable,
already_AddRefed<nsIInputStreamCallback> aCallback)
{
nsCOMPtr<nsIInputStreamCallback> callback = std::move(aCallback);
{
MutexAutoLock lock(mLock);
--- a/xpcom/io/NonBlockingAsyncInputStream.h
+++ b/xpcom/io/NonBlockingAsyncInputStream.h
@@ -29,16 +29,17 @@ class NonBlockingAsyncInputStream final
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIINPUTSTREAM
NS_DECL_NSIASYNCINPUTSTREAM
NS_DECL_NSICLONEABLEINPUTSTREAM
NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
NS_DECL_NSISEEKABLESTREAM
+ NS_DECL_NSITELLABLESTREAM
// |aInputStream| must be a non-blocking, non-async inputSteam.
static nsresult
Create(already_AddRefed<nsIInputStream> aInputStream,
nsIAsyncInputStream** aAsyncInputStream);
private:
explicit NonBlockingAsyncInputStream(already_AddRefed<nsIInputStream> aInputStream);
@@ -51,16 +52,17 @@ private:
already_AddRefed<nsIInputStreamCallback> aCallback);
nsCOMPtr<nsIInputStream> mInputStream;
// Raw pointers because these are just QI of mInputStream.
nsICloneableInputStream* MOZ_NON_OWNING_REF mWeakCloneableInputStream;
nsIIPCSerializableInputStream* MOZ_NON_OWNING_REF mWeakIPCSerializableInputStream;
nsISeekableStream* MOZ_NON_OWNING_REF mWeakSeekableInputStream;
+ nsITellableStream* MOZ_NON_OWNING_REF mWeakTellableInputStream;
Mutex mLock;
struct WaitClosureOnly
{
WaitClosureOnly(AsyncWaitRunnable* aRunnable, nsIEventTarget* aEventTarget);
RefPtr<AsyncWaitRunnable> mRunnable;
--- a/xpcom/io/SlicedInputStream.cpp
+++ b/xpcom/io/SlicedInputStream.cpp
@@ -21,16 +21,18 @@ NS_IMPL_RELEASE(SlicedInputStream);
NS_INTERFACE_MAP_BEGIN(SlicedInputStream)
NS_INTERFACE_MAP_ENTRY(nsIInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsICloneableInputStream,
mWeakCloneableInputStream || !mInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream,
mWeakIPCSerializableInputStream || !mInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISeekableStream,
mWeakSeekableInputStream || !mInputStream)
+ NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsITellableStream,
+ mWeakTellableInputStream || !mInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAsyncInputStream,
mWeakAsyncInputStream || !mInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIInputStreamCallback,
mWeakAsyncInputStream || !mInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIInputStreamLength,
mWeakInputStreamLength || !mInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAsyncInputStreamLength,
mWeakAsyncInputStreamLength || !mInputStream)
@@ -39,16 +41,17 @@ NS_INTERFACE_MAP_BEGIN(SlicedInputStream
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
NS_INTERFACE_MAP_END
SlicedInputStream::SlicedInputStream(already_AddRefed<nsIInputStream> aInputStream,
uint64_t aStart, uint64_t aLength)
: mWeakCloneableInputStream(nullptr)
, mWeakIPCSerializableInputStream(nullptr)
, mWeakSeekableInputStream(nullptr)
+ , mWeakTellableInputStream(nullptr)
, mWeakAsyncInputStream(nullptr)
, mWeakInputStreamLength(nullptr)
, mWeakAsyncInputStreamLength(nullptr)
, mStart(aStart)
, mLength(aLength)
, mCurPos(0)
, mClosed(false)
, mAsyncWaitFlags(0)
@@ -58,16 +61,17 @@ SlicedInputStream::SlicedInputStream(alr
nsCOMPtr<nsIInputStream> inputStream = std::move(aInputStream);
SetSourceStream(inputStream.forget());
}
SlicedInputStream::SlicedInputStream()
: mWeakCloneableInputStream(nullptr)
, mWeakIPCSerializableInputStream(nullptr)
, mWeakSeekableInputStream(nullptr)
+ , mWeakTellableInputStream(nullptr)
, mWeakAsyncInputStream(nullptr)
, mStart(0)
, mLength(0)
, mCurPos(0)
, mClosed(false)
, mAsyncWaitFlags(0)
, mAsyncWaitRequestedCount(0)
, mMutex("SlicedInputStream::mMutex")
@@ -97,16 +101,22 @@ SlicedInputStream::SetSourceStream(alrea
}
nsCOMPtr<nsISeekableStream> seekableStream =
do_QueryInterface(mInputStream);
if (seekableStream && SameCOMIdentity(mInputStream, seekableStream)) {
mWeakSeekableInputStream = seekableStream;
}
+ nsCOMPtr<nsITellableStream> tellableStream =
+ do_QueryInterface(mInputStream);
+ if (tellableStream && SameCOMIdentity(mInputStream, tellableStream)) {
+ mWeakTellableInputStream = tellableStream;
+ }
+
nsCOMPtr<nsIAsyncInputStream> asyncInputStream =
do_QueryInterface(mInputStream);
if (asyncInputStream && SameCOMIdentity(mInputStream, asyncInputStream)) {
mWeakAsyncInputStream = asyncInputStream;
}
nsCOMPtr<nsIInputStreamLength> streamLength = do_QueryInterface(mInputStream);
if (streamLength &&
@@ -539,24 +549,36 @@ SlicedInputStream::Seek(int32_t aWhence,
return rv;
}
mCurPos = offset;
return NS_OK;
}
NS_IMETHODIMP
-SlicedInputStream::Tell(int64_t *aResult)
+SlicedInputStream::SetEOF()
{
NS_ENSURE_STATE(mInputStream);
NS_ENSURE_STATE(mWeakSeekableInputStream);
+ mClosed = true;
+ return mWeakSeekableInputStream->SetEOF();
+}
+
+// nsITellableStream
+
+NS_IMETHODIMP
+SlicedInputStream::Tell(int64_t *aResult)
+{
+ NS_ENSURE_STATE(mInputStream);
+ NS_ENSURE_STATE(mWeakTellableInputStream);
+
int64_t tell = 0;
- nsresult rv = mWeakSeekableInputStream->Tell(&tell);
+ nsresult rv = mWeakTellableInputStream->Tell(&tell);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (tell < (int64_t)mStart) {
*aResult = 0;
return NS_OK;
}
@@ -564,26 +586,16 @@ SlicedInputStream::Tell(int64_t *aResult
*aResult = tell - mStart;
if (*aResult > (int64_t)mLength) {
*aResult = mLength;
}
return NS_OK;
}
-NS_IMETHODIMP
-SlicedInputStream::SetEOF()
-{
- NS_ENSURE_STATE(mInputStream);
- NS_ENSURE_STATE(mWeakSeekableInputStream);
-
- mClosed = true;
- return mWeakSeekableInputStream->SetEOF();
-}
-
// nsIInputStreamLength
NS_IMETHODIMP
SlicedInputStream::Length(int64_t* aLength)
{
NS_ENSURE_STATE(mInputStream);
NS_ENSURE_STATE(mWeakInputStreamLength);
--- a/xpcom/io/SlicedInputStream.h
+++ b/xpcom/io/SlicedInputStream.h
@@ -31,16 +31,17 @@ class SlicedInputStream final : public n
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIINPUTSTREAM
NS_DECL_NSIASYNCINPUTSTREAM
NS_DECL_NSICLONEABLEINPUTSTREAM
NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
NS_DECL_NSISEEKABLESTREAM
+ NS_DECL_NSITELLABLESTREAM
NS_DECL_NSIINPUTSTREAMCALLBACK
NS_DECL_NSIINPUTSTREAMLENGTH
NS_DECL_NSIASYNCINPUTSTREAMLENGTH
NS_DECL_NSIINPUTSTREAMLENGTHCALLBACK
// Create an input stream whose data comes from a slice of aInputStream. The
// slice begins at aStart bytes beyond aInputStream's current position, and
// extends for a maximum of aLength bytes. If aInputStream contains fewer
@@ -68,16 +69,17 @@ private:
AdjustRange(uint64_t aRange);
nsCOMPtr<nsIInputStream> mInputStream;
// Raw pointers because these are just QI of mInputStream.
nsICloneableInputStream* mWeakCloneableInputStream;
nsIIPCSerializableInputStream* mWeakIPCSerializableInputStream;
nsISeekableStream* mWeakSeekableInputStream;
+ nsITellableStream* mWeakTellableInputStream;
nsIAsyncInputStream* mWeakAsyncInputStream;
nsIInputStreamLength* mWeakInputStreamLength;
nsIAsyncInputStreamLength* mWeakAsyncInputStreamLength;
uint64_t mStart;
uint64_t mLength;
uint64_t mCurPos;
--- a/xpcom/io/moz.build
+++ b/xpcom/io/moz.build
@@ -28,16 +28,17 @@ XPIDL_SOURCES += [
'nsIPipe.idl',
'nsISafeOutputStream.idl',
'nsIScriptableBase64Encoder.idl',
'nsIScriptableInputStream.idl',
'nsISeekableStream.idl',
'nsIStorageStream.idl',
'nsIStreamBufferAccess.idl',
'nsIStringStream.idl',
+ 'nsITellableStream.idl',
'nsIUnicharInputStream.idl',
'nsIUnicharLineInputStream.idl',
'nsIUnicharOutputStream.idl',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
XPIDL_SOURCES += [
'nsILocalFileMac.idl',
--- a/xpcom/io/nsISeekableStream.idl
+++ b/xpcom/io/nsISeekableStream.idl
@@ -1,25 +1,27 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "nsITellableStream.idl"
+
/*
* nsISeekableStream
*
* Note that a stream might not implement all methods (e.g., a readonly stream
* won't implement setEOF)
*/
#include "nsISupports.idl"
[scriptable, uuid(8429d350-1040-4661-8b71-f2a6ba455980)]
-interface nsISeekableStream : nsISupports
+interface nsISeekableStream : nsITellableStream
{
/*
* Sets the stream pointer to the value of the 'offset' parameter
*/
const int32_t NS_SEEK_SET = 0;
/*
* Sets the stream pointer to its current location plus the value
@@ -48,27 +50,16 @@ interface nsISeekableStream : nsISupport
* implementing stream. A negative value causes seeking in
* the reverse direction.
*
* @throws NS_BASE_STREAM_CLOSED if called on a closed stream.
*/
void seek(in long whence, in long long offset);
/**
- * tell
- *
- * This method reports the current offset, in bytes, from the start of the
- * stream.
- *
- * @throws NS_BASE_STREAM_CLOSED if called on a closed stream.
- */
- long long tell();
-
-
- /**
* setEOF
*
* This method truncates the stream at the current offset.
*
* @throws NS_BASE_STREAM_CLOSED if called on a closed stream.
*/
void setEOF();
};
new file mode 100644
--- /dev/null
+++ b/xpcom/io/nsITellableStream.idl
@@ -0,0 +1,34 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+
+/*
+ * nsITellableStream
+ *
+ * This class is separate from nsISeekableStream in order to let streams to
+ * implement ::Tell() without implementing the whole nsISeekableStream
+ * interface. Callers can QI the stream to know what is implemented. This is
+ * mainly done for nsPipeInputStream.
+ *
+ *
+ * Implementing this interface, streams are able to expose the current offset
+ * via ::tell().
+ */
+
+#include "nsISupports.idl"
+
+[scriptable, uuid(ee942946-4538-45d2-bf05-ffdbf5932621)]
+interface nsITellableStream : nsISupports
+{
+ /**
+ * tell
+ *
+ * This method reports the current offset, in bytes, from the start of the
+ * stream.
+ *
+ * @throws NS_BASE_STREAM_CLOSED if called on a closed stream.
+ */
+ long long tell();
+};
--- a/xpcom/io/nsMultiplexInputStream.cpp
+++ b/xpcom/io/nsMultiplexInputStream.cpp
@@ -51,16 +51,17 @@ class nsMultiplexInputStream final
{
public:
nsMultiplexInputStream();
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIINPUTSTREAM
NS_DECL_NSIMULTIPLEXINPUTSTREAM
NS_DECL_NSISEEKABLESTREAM
+ NS_DECL_NSITELLABLESTREAM
NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
NS_DECL_NSICLONEABLEINPUTSTREAM
NS_DECL_NSIASYNCINPUTSTREAM
NS_DECL_NSIINPUTSTREAMCALLBACK
NS_DECL_NSIINPUTSTREAMLENGTH
NS_DECL_NSIASYNCINPUTSTREAMLENGTH
// This is used for nsIAsyncInputStream::AsyncWait
@@ -72,25 +73,28 @@ public:
struct StreamData
{
void Initialize(nsIInputStream* aStream, bool aBuffered)
{
mStream = aStream;
mAsyncStream = do_QueryInterface(aStream);
mSeekableStream = do_QueryInterface(aStream);
+ mTellableStream = do_QueryInterface(aStream);
mBuffered = aBuffered;
}
nsCOMPtr<nsIInputStream> mStream;
// This can be null.
nsCOMPtr<nsIAsyncInputStream> mAsyncStream;
// This can be null.
nsCOMPtr<nsISeekableStream> mSeekableStream;
+ // This can be null.
+ nsCOMPtr<nsITellableStream> mTellableStream;
// True if the stream is wrapped with nsIBufferedInputStream.
bool mBuffered;
};
Mutex& GetLock()
{
return mLock;
@@ -99,34 +103,35 @@ public:
private:
~nsMultiplexInputStream()
{
}
nsresult
AsyncWaitInternal();
- // This method updates mSeekableStreams, mIPCSerializableStreams,
- // mCloneableStreams and mAsyncInputStreams values.
+ // This method updates mSeekableStreams, mTellableStreams,
+ // mIPCSerializableStreams, mCloneableStreams and mAsyncInputStreams values.
void UpdateQIMap(StreamData& aStream, int32_t aCount);
struct MOZ_STACK_CLASS ReadSegmentsState
{
nsCOMPtr<nsIInputStream> mThisStream;
uint32_t mOffset;
nsWriteSegmentFun mWriter;
void* mClosure;
bool mDone;
};
static nsresult ReadSegCb(nsIInputStream* aIn, void* aClosure,
const char* aFromRawSegment, uint32_t aToOffset,
uint32_t aCount, uint32_t* aWriteCount);
bool IsSeekable() const;
+ bool IsTellable() const;
bool IsIPCSerializable() const;
bool IsCloneable() const;
bool IsAsyncInputStream() const;
bool IsInputStreamLength() const;
bool IsAsyncInputStreamLength() const;
Mutex mLock; // Protects access to all data members.
@@ -140,16 +145,17 @@ private:
uint32_t mAsyncWaitRequestedCount;
nsCOMPtr<nsIEventTarget> mAsyncWaitEventTarget;
nsCOMPtr<nsIInputStreamLengthCallback> mAsyncWaitLengthCallback;
class AsyncWaitLengthHelper;
RefPtr<AsyncWaitLengthHelper> mAsyncWaitLengthHelper;
uint32_t mSeekableStreams;
+ uint32_t mTellableStreams;
uint32_t mIPCSerializableStreams;
uint32_t mCloneableStreams;
uint32_t mAsyncInputStreams;
uint32_t mInputStreamLengths;
uint32_t mAsyncInputStreamLengths;
};
NS_IMPL_ADDREF(nsMultiplexInputStream)
@@ -157,16 +163,17 @@ NS_IMPL_RELEASE(nsMultiplexInputStream)
NS_IMPL_CLASSINFO(nsMultiplexInputStream, nullptr, nsIClassInfo::THREADSAFE,
NS_MULTIPLEXINPUTSTREAM_CID)
NS_INTERFACE_MAP_BEGIN(nsMultiplexInputStream)
NS_INTERFACE_MAP_ENTRY(nsIMultiplexInputStream)
NS_INTERFACE_MAP_ENTRY(nsIInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISeekableStream, IsSeekable())
+ NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsITellableStream, IsTellable())
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream,
IsIPCSerializable())
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsICloneableInputStream,
IsCloneable())
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAsyncInputStream,
IsAsyncInputStream())
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIInputStreamCallback,
IsAsyncInputStream())
@@ -176,17 +183,18 @@ NS_INTERFACE_MAP_BEGIN(nsMultiplexInputS
IsAsyncInputStreamLength())
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIMultiplexInputStream)
NS_IMPL_QUERY_CLASSINFO(nsMultiplexInputStream)
NS_INTERFACE_MAP_END
NS_IMPL_CI_INTERFACE_GETTER(nsMultiplexInputStream,
nsIMultiplexInputStream,
nsIInputStream,
- nsISeekableStream)
+ nsISeekableStream,
+ nsITellableStream)
static nsresult
AvailableMaybeSeek(nsMultiplexInputStream::StreamData& aStream,
uint64_t* aResult)
{
nsresult rv = aStream.mStream->Available(aResult);
if (rv == NS_BASE_STREAM_CLOSED) {
// Blindly seek to the current position if Available() returns
@@ -200,40 +208,42 @@ AvailableMaybeSeek(nsMultiplexInputStrea
rv = aStream.mStream->Available(aResult);
}
}
}
return rv;
}
static nsresult
-TellMaybeSeek(nsISeekableStream* aSeekable, int64_t* aResult)
+TellMaybeSeek(nsITellableStream* aTellable, nsISeekableStream* aSeekable,
+ int64_t* aResult)
{
- nsresult rv = aSeekable->Tell(aResult);
- if (rv == NS_BASE_STREAM_CLOSED) {
+ nsresult rv = aTellable->Tell(aResult);
+ if (rv == NS_BASE_STREAM_CLOSED && aSeekable) {
// Blindly seek to the current position if Tell() returns
// NS_BASE_STREAM_CLOSED.
// If nsIFileInputStream is closed in Read() due to CLOSE_ON_EOF flag,
// Seek() could reopen the file if REOPEN_ON_REWIND flag is set.
nsresult rvSeek = aSeekable->Seek(nsISeekableStream::NS_SEEK_CUR, 0);
if (NS_SUCCEEDED(rvSeek)) {
- rv = aSeekable->Tell(aResult);
+ rv = aTellable->Tell(aResult);
}
}
return rv;
}
nsMultiplexInputStream::nsMultiplexInputStream()
: mLock("nsMultiplexInputStream lock")
, mCurrentStream(0)
, mStartedReadingCurrent(false)
, mStatus(NS_OK)
, mAsyncWaitFlags(0)
, mAsyncWaitRequestedCount(0)
, mSeekableStreams(0)
+ , mTellableStreams(0)
, mIPCSerializableStreams(0)
, mCloneableStreams(0)
, mAsyncInputStreams(0)
, mInputStreamLengths(0)
, mAsyncInputStreamLengths(0)
{}
NS_IMETHODIMP
@@ -574,16 +584,18 @@ nsMultiplexInputStream::Seek(int32_t aWh
mCurrentStream = 0;
}
for (uint32_t i = 0; i < mStreams.Length(); ++i) {
nsCOMPtr<nsISeekableStream> stream = mStreams[i].mSeekableStream;
if (!stream) {
return NS_ERROR_FAILURE;
}
+ MOZ_ASSERT(mStreams[i].mTellableStream);
+
// See if all remaining streams should be rewound
if (remaining == 0) {
if (i < oldCurrentStream ||
(i == oldCurrentStream && oldStartedReadingCurrent)) {
rv = stream->Seek(NS_SEEK_SET, 0);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@@ -594,17 +606,17 @@ nsMultiplexInputStream::Seek(int32_t aWh
}
// Get position in current stream
int64_t streamPos;
if (i > oldCurrentStream ||
(i == oldCurrentStream && !oldStartedReadingCurrent)) {
streamPos = 0;
} else {
- rv = TellMaybeSeek(stream, &streamPos);
+ rv = TellMaybeSeek(mStreams[i].mTellableStream, stream, &streamPos);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
// See if we need to seek current stream forward or backward
if (remaining < streamPos) {
rv = stream->Seek(NS_SEEK_SET, remaining);
@@ -677,17 +689,18 @@ nsMultiplexInputStream::Seek(int32_t aWh
return NS_OK;
}
if (aWhence == NS_SEEK_CUR && aOffset < 0) {
int64_t remaining = -aOffset;
for (uint32_t i = mCurrentStream; remaining && i != (uint32_t)-1; --i) {
int64_t pos;
- rv = TellMaybeSeek(mStreams[i].mSeekableStream, &pos);
+ rv = TellMaybeSeek(mStreams[i].mTellableStream,
+ mStreams[i].mSeekableStream, &pos);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
int64_t seek = XPCOM_MIN(pos, remaining);
rv = mStreams[i].mSeekableStream->Seek(NS_SEEK_CUR, -seek);
if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -756,17 +769,17 @@ nsMultiplexInputStream::Seek(int32_t aWh
remaining = 0;
} else if (DeprecatedAbs(remaining) > streamPos) {
if (i > oldCurrentStream ||
(i == oldCurrentStream && !oldStartedReadingCurrent)) {
// We're already at start so no need to seek this stream
remaining += streamPos;
} else {
int64_t avail;
- rv = TellMaybeSeek(stream, &avail);
+ rv = TellMaybeSeek(mStreams[i].mTellableStream, stream, &avail);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
int64_t newPos = streamPos + XPCOM_MIN(avail, DeprecatedAbs(remaining));
rv = stream->Seek(NS_SEEK_END, -newPos);
if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -800,22 +813,23 @@ nsMultiplexInputStream::Tell(int64_t* aR
return mStatus;
}
nsresult rv;
int64_t ret64 = 0;
uint32_t i, last;
last = mStartedReadingCurrent ? mCurrentStream + 1 : mCurrentStream;
for (i = 0; i < last; ++i) {
- if (NS_WARN_IF(!mStreams[i].mSeekableStream)) {
+ if (NS_WARN_IF(!mStreams[i].mTellableStream)) {
return NS_ERROR_NO_INTERFACE;
}
int64_t pos;
- rv = TellMaybeSeek(mStreams[i].mSeekableStream, &pos);
+ rv = TellMaybeSeek(mStreams[i].mTellableStream, mStreams[i].mSeekableStream,
+ &pos);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
ret64 += pos;
}
*aResult = ret64;
return NS_OK;
@@ -1510,32 +1524,39 @@ nsMultiplexInputStream::AsyncWaitComplet
}
void
nsMultiplexInputStream::UpdateQIMap(StreamData& aStream, int32_t aCount)
{
MOZ_ASSERT(aCount == -1 || aCount == 1);
MAYBE_UPDATE_VALUE_REAL(mSeekableStreams, aStream.mSeekableStream)
+ MAYBE_UPDATE_VALUE_REAL(mTellableStreams, aStream.mTellableStream)
MAYBE_UPDATE_VALUE(mIPCSerializableStreams, nsIIPCSerializableInputStream)
MAYBE_UPDATE_VALUE(mCloneableStreams, nsICloneableInputStream)
MAYBE_UPDATE_VALUE_REAL(mAsyncInputStreams, aStream.mAsyncStream)
MAYBE_UPDATE_VALUE(mInputStreamLengths, nsIInputStreamLength)
MAYBE_UPDATE_VALUE(mAsyncInputStreamLengths, nsIAsyncInputStreamLength)
}
#undef MAYBE_UPDATE_VALUE
bool
nsMultiplexInputStream::IsSeekable() const
{
return mStreams.Length() == mSeekableStreams;
}
bool
+nsMultiplexInputStream::IsTellable() const
+{
+ return mStreams.Length() == mTellableStreams;
+}
+
+bool
nsMultiplexInputStream::IsIPCSerializable() const
{
return mStreams.Length() == mIPCSerializableStreams;
}
bool
nsMultiplexInputStream::IsCloneable() const
{
--- a/xpcom/io/nsPipe3.cpp
+++ b/xpcom/io/nsPipe3.cpp
@@ -7,17 +7,17 @@
#include <algorithm>
#include "mozilla/Attributes.h"
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/ReentrantMonitor.h"
#include "nsIBufferedStreams.h"
#include "nsICloneableInputStream.h"
#include "nsIPipe.h"
#include "nsIEventTarget.h"
-#include "nsISeekableStream.h"
+#include "nsITellableStream.h"
#include "mozilla/RefPtr.h"
#include "nsSegmentedBuffer.h"
#include "nsStreamUtils.h"
#include "nsCOMPtr.h"
#include "nsCRT.h"
#include "mozilla/Logging.h"
#include "nsIClassInfoImpl.h"
#include "nsAlgorithm.h"
@@ -137,30 +137,30 @@ struct nsPipeReadState
bool mNeedDrain;
};
//-----------------------------------------------------------------------------
// an input end of a pipe (maintained as a list of refs within the pipe)
class nsPipeInputStream final
: public nsIAsyncInputStream
- , public nsISeekableStream
+ , public nsITellableStream
, public nsISearchableInputStream
, public nsICloneableInputStream
, public nsIClassInfo
, public nsIBufferedInputStream
{
public:
// Pipe input streams preserve their refcount changes when record/replaying,
// as otherwise the thread which destroys the stream may vary between
// recording and replaying.
NS_DECL_THREADSAFE_ISUPPORTS_WITH_RECORDING(recordreplay::Behavior::Preserve)
NS_DECL_NSIINPUTSTREAM
NS_DECL_NSIASYNCINPUTSTREAM
- NS_DECL_NSISEEKABLESTREAM
+ NS_DECL_NSITELLABLESTREAM
NS_DECL_NSISEARCHABLEINPUTSTREAM
NS_DECL_NSICLONEABLEINPUTSTREAM
NS_DECL_NSICLASSINFO
NS_DECL_NSIBUFFEREDINPUTSTREAM
explicit nsPipeInputStream(nsPipe* aPipe)
: mPipe(aPipe)
, mLogicalOffset(0)
@@ -1245,32 +1245,32 @@ nsPipeEvents::~nsPipeEvents()
//-----------------------------------------------------------------------------
NS_IMPL_ADDREF(nsPipeInputStream);
NS_IMPL_RELEASE(nsPipeInputStream);
NS_INTERFACE_TABLE_HEAD(nsPipeInputStream)
NS_INTERFACE_TABLE_BEGIN
NS_INTERFACE_TABLE_ENTRY(nsPipeInputStream, nsIAsyncInputStream)
- NS_INTERFACE_TABLE_ENTRY(nsPipeInputStream, nsISeekableStream)
+ NS_INTERFACE_TABLE_ENTRY(nsPipeInputStream, nsITellableStream)
NS_INTERFACE_TABLE_ENTRY(nsPipeInputStream, nsISearchableInputStream)
NS_INTERFACE_TABLE_ENTRY(nsPipeInputStream, nsICloneableInputStream)
NS_INTERFACE_TABLE_ENTRY(nsPipeInputStream, nsIBufferedInputStream)
NS_INTERFACE_TABLE_ENTRY(nsPipeInputStream, nsIClassInfo)
NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(nsPipeInputStream, nsIInputStream,
nsIAsyncInputStream)
NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(nsPipeInputStream, nsISupports,
nsIAsyncInputStream)
NS_INTERFACE_TABLE_END
NS_INTERFACE_TABLE_TAIL
NS_IMPL_CI_INTERFACE_GETTER(nsPipeInputStream,
nsIInputStream,
nsIAsyncInputStream,
- nsISeekableStream,
+ nsITellableStream,
nsISearchableInputStream,
nsICloneableInputStream,
nsIBufferedInputStream)
NS_IMPL_THREADSAFE_CI(nsPipeInputStream)
NS_IMETHODIMP
nsPipeInputStream::Init(nsIInputStream*, uint32_t)
@@ -1521,42 +1521,29 @@ nsPipeInputStream::AsyncWait(nsIInputStr
mCallback = aCallback;
mCallbackFlags = aFlags;
}
}
return NS_OK;
}
NS_IMETHODIMP
-nsPipeInputStream::Seek(int32_t aWhence, int64_t aOffset)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
nsPipeInputStream::Tell(int64_t* aOffset)
{
ReentrantMonitorAutoEnter mon(mPipe->mReentrantMonitor);
// return error if closed
if (!mReadState.mAvailable && NS_FAILED(Status(mon))) {
return Status(mon);
}
*aOffset = mLogicalOffset;
return NS_OK;
}
-NS_IMETHODIMP
-nsPipeInputStream::SetEOF()
-{
- MOZ_ASSERT_UNREACHABLE("nsPipeInputStream::SetEOF");
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
static bool strings_equal(bool aIgnoreCase,
const char* aS1, const char* aS2, uint32_t aLen)
{
return aIgnoreCase
? !nsCRT::strncasecmp(aS1, aS2, aLen) : !strncmp(aS1, aS2, aLen);
}
NS_IMETHODIMP
--- a/xpcom/io/nsStorageStream.cpp
+++ b/xpcom/io/nsStorageStream.cpp
@@ -344,16 +344,17 @@ public:
mSegmentSize(aSegmentSize), mLogicalCursor(0),
mStatus(NS_OK)
{
}
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIINPUTSTREAM
NS_DECL_NSISEEKABLESTREAM
+ NS_DECL_NSITELLABLESTREAM
NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
NS_DECL_NSICLONEABLEINPUTSTREAM
private:
~nsStorageInputStream()
{
}
@@ -379,16 +380,17 @@ private:
{
return aPosition & (mSegmentSize - 1);
}
};
NS_IMPL_ISUPPORTS(nsStorageInputStream,
nsIInputStream,
nsISeekableStream,
+ nsITellableStream,
nsIIPCSerializableInputStream,
nsICloneableInputStream)
NS_IMETHODIMP
nsStorageStream::NewInputStream(int32_t aStartingOffset,
nsIInputStream** aInputStream)
{
if (NS_WARN_IF(!mSegmentedBuffer)) {
--- a/xpcom/io/nsStringStream.cpp
+++ b/xpcom/io/nsStringStream.cpp
@@ -39,16 +39,17 @@ class nsStringInputStream final
, public nsIIPCSerializableInputStream
, public nsICloneableInputStream
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIINPUTSTREAM
NS_DECL_NSISTRINGINPUTSTREAM
NS_DECL_NSISEEKABLESTREAM
+ NS_DECL_NSITELLABLESTREAM
NS_DECL_NSISUPPORTSPRIMITIVE
NS_DECL_NSISUPPORTSCSTRING
NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
NS_DECL_NSICLONEABLEINPUTSTREAM
nsStringInputStream()
: mOffset(0)
{
@@ -104,23 +105,25 @@ NS_IMPL_RELEASE(nsStringInputStream)
NS_IMPL_CLASSINFO(nsStringInputStream, nullptr, nsIClassInfo::THREADSAFE,
NS_STRINGINPUTSTREAM_CID)
NS_IMPL_QUERY_INTERFACE_CI(nsStringInputStream,
nsIStringInputStream,
nsIInputStream,
nsISupportsCString,
nsISeekableStream,
+ nsITellableStream,
nsIIPCSerializableInputStream,
nsICloneableInputStream)
NS_IMPL_CI_INTERFACE_GETTER(nsStringInputStream,
nsIStringInputStream,
nsIInputStream,
nsISupportsCString,
nsISeekableStream,
+ nsITellableStream,
nsICloneableInputStream)
/////////
// nsISupportsCString implementation
/////////
NS_IMETHODIMP
nsStringInputStream::GetType(uint16_t* aType)
@@ -318,37 +321,41 @@ nsStringInputStream::Seek(int32_t aWhenc
return NS_ERROR_INVALID_ARG;
}
mOffset = (uint32_t)newPos;
return NS_OK;
}
NS_IMETHODIMP
+nsStringInputStream::SetEOF()
+{
+ if (Closed()) {
+ return NS_BASE_STREAM_CLOSED;
+ }
+
+ mOffset = Length();
+ return NS_OK;
+}
+
+/////////
+// nsITellableStream implementation
+/////////
+
+NS_IMETHODIMP
nsStringInputStream::Tell(int64_t* aOutWhere)
{
if (Closed()) {
return NS_BASE_STREAM_CLOSED;
}
*aOutWhere = mOffset;
return NS_OK;
}
-NS_IMETHODIMP
-nsStringInputStream::SetEOF()
-{
- if (Closed()) {
- return NS_BASE_STREAM_CLOSED;
- }
-
- mOffset = Length();
- return NS_OK;
-}
-
/////////
// nsIIPCSerializableInputStream implementation
/////////
void
nsStringInputStream::Serialize(InputStreamParams& aParams,
FileDescriptorArray& /* aFDs */)
{
--- a/xpcom/io/nsStringStream.h
+++ b/xpcom/io/nsStringStream.h
@@ -11,30 +11,31 @@
#include "nsString.h"
#include "nsMemory.h"
/**
* Implements:
* nsIStringInputStream
* nsIInputStream
* nsISeekableStream
+ * nsITellableStream
* nsISupportsCString
*/
#define NS_STRINGINPUTSTREAM_CONTRACTID "@mozilla.org/io/string-input-stream;1"
#define NS_STRINGINPUTSTREAM_CID \
{ /* 0abb0835-5000-4790-af28-61b3ba17c295 */ \
0x0abb0835, \
0x5000, \
0x4790, \
{0xaf, 0x28, 0x61, 0xb3, 0xba, 0x17, 0xc2, 0x95} \
}
/**
* Factory method to get an nsInputStream from a byte buffer. Result will
- * implement nsIStringInputStream and nsISeekableStream.
+ * implement nsIStringInputStream, nsITellableStream and nsISeekableStream.
*
* If aAssignment is NS_ASSIGNMENT_COPY, then the resulting stream holds a copy
* of the given buffer (aStringToRead), and the caller is free to discard
* aStringToRead after this function returns.
*
* If aAssignment is NS_ASSIGNMENT_DEPEND, then the resulting stream refers
* directly to the given buffer (aStringToRead), so the caller must ensure that
* the buffer remains valid for the lifetime of the stream object. Use with
@@ -49,17 +50,17 @@
*/
extern nsresult
NS_NewByteInputStream(nsIInputStream** aStreamResult,
const char* aStringToRead, int32_t aLength = -1,
nsAssignmentType aAssignment = NS_ASSIGNMENT_DEPEND);
/**
* Factory method to get an nsInputStream from an nsACString. Result will
- * implement nsIStringInputStream and nsISeekableStream.
+ * implement nsIStringInputStream, nsTellableStream and nsISeekableStream.
*/
extern nsresult
NS_NewCStringInputStream(nsIInputStream** aStreamResult,
const nsACString& aStringToRead);
extern nsresult
NS_NewCStringInputStream(nsIInputStream** aStreamResult,
nsCString&& aStringToRead);
--- a/xpcom/tests/gtest/TestPipes.cpp
+++ b/xpcom/tests/gtest/TestPipes.cpp
@@ -14,17 +14,17 @@
#include "nsIAsyncInputStream.h"
#include "nsIAsyncOutputStream.h"
#include "nsIBufferedStreams.h"
#include "nsIClassInfo.h"
#include "nsICloneableInputStream.h"
#include "nsIInputStream.h"
#include "nsIOutputStream.h"
#include "nsIPipe.h"
-#include "nsISeekableStream.h"
+#include "nsITellableStream.h"
#include "nsIThread.h"
#include "nsIRunnable.h"
#include "nsStreamUtils.h"
#include "nsString.h"
#include "nsThreadUtils.h"
#include "prinrval.h"
using namespace mozilla;
@@ -1073,17 +1073,17 @@ TEST(Pipes, Interfaces)
nsCOMPtr<nsIOutputStream> writer;
nsresult rv = NS_NewPipe(getter_AddRefs(reader), getter_AddRefs(writer));
ASSERT_TRUE(NS_SUCCEEDED(rv));
nsCOMPtr<nsIAsyncInputStream> readerType1 = do_QueryInterface(reader);
ASSERT_TRUE(readerType1);
- nsCOMPtr<nsISeekableStream> readerType2 = do_QueryInterface(reader);
+ nsCOMPtr<nsITellableStream> readerType2 = do_QueryInterface(reader);
ASSERT_TRUE(readerType2);
nsCOMPtr<nsISearchableInputStream> readerType3 = do_QueryInterface(reader);
ASSERT_TRUE(readerType3);
nsCOMPtr<nsICloneableInputStream> readerType4 = do_QueryInterface(reader);
ASSERT_TRUE(readerType4);