Closed Bug 1368005 Opened 7 years ago Closed 5 years ago

Calling document.write in srcdoc when onload is called (which does document.open) will throw

Categories

(Core :: DOM: Core & HTML, defect, P2)

defect

Tracking

()

RESOLVED DUPLICATE of bug 1489308

People

(Reporter: allstars.chh, Unassigned)

References

Details

Attachments

(1 file, 1 obsolete file)

Attached file test_srcdoc.html (obsolete) —
The test is 
<iframe srcdoc="<script>window.onload=function(){document.write('hello');};</script>"></iframe>

See attachment for the test HTML
Open this HTML with Firefox, only the 1st iframe has 'hello', the 2nd iframe is empty.
See below for the stack.

However Chrome could show 'hello' in both iframes, as asked by smaug in https://bugzilla.mozilla.org/show_bug.cgi?id=1365857#c14, I filed this as a seperate bug.


document.write will return NS_ERR_MALFORMED_URI, the stack is 
GECKO(26064) | #01: mozilla::net::nsAboutProtocolHandler::NewChannel2(nsIURI*, nsILoadInfo*, nsIChannel**) (/home/allstars/src/gecko-dev/netwerk/protocol/about/nsAboutProtocolHandler.cpp:187)
GECKO(26064) | #02: mozilla::net::nsIOService::NewChannelFromURIWithProxyFlagsInternal(nsIURI*, nsIURI*, unsigned int, nsILoadInfo*, nsIChannel**) (/home/allstars/src/gecko-dev/netwerk/base/nsIOService.cpp:829)
GECKO(26064) | #03: mozilla::net::nsIOService::NewChannelFromURIWithProxyFlags2(nsIURI*, nsIURI*, unsigned int, nsIDOMNode*, nsIPrincipal*, nsIPrincipal*, unsigned int, unsigned int, nsIChannel**) (/home/allstars/src/gecko-dev/netwerk/base/nsIOService.cpp:932)
GECKO(26064) | #04: mozilla::net::nsIOService::NewChannelFromURI2(nsIURI*, nsIDOMNode*, nsIPrincipal*, nsIPrincipal*, unsigned int, unsigned int, nsIChannel**) (/home/allstars/src/gecko-dev/netwerk/base/nsIOService.cpp:727)
GECKO(26064) | #05: NS_NewChannelInternal(nsIChannel**, nsIURI*, nsINode*, nsIPrincipal*, nsIPrincipal*, unsigned int, unsigned int, nsILoadGroup*, nsIInterfaceRequestor*, unsigned int, nsIIOService*) (/home/allstars/src/gecko-dev/netwerk/base/nsNetUtil.cpp:255 (discriminator 4))
GECKO(26064) | #06: NS_NewChannel(nsIChannel**, nsIURI*, nsINode*, unsigned int, unsigned int, nsILoadGroup*, nsIInterfaceRequestor*, unsigned int, nsIIOService*) (/home/allstars/src/gecko-dev/netwerk/base/nsNetUtil.cpp:358)
GECKO(26064) | #07: nsHTMLDocument::Open(JSContext*, nsAString const&, nsAString const&, mozilla::ErrorResult&) (/home/allstars/src/gecko-dev/dom/html/nsHTMLDocument.cpp:1617)
GECKO(26064) | #08: nsHTMLDocument::Open(nsAString const&, nsAString const&, nsAString const&, JSContext*, unsigned char, nsISupports**) (/home/allstars/src/gecko-dev/dom/html/nsHTMLDocument.cpp:1436)
GECKO(26064) | #09: nsHTMLDocument::WriteCommon(JSContext*, nsAString const&, bool) (/home/allstars/src/gecko-dev/dom/html/nsHTMLDocument.cpp:1952)
GECKO(26064) | #10: nsHTMLDocument::WriteCommon(JSContext*, mozilla::dom::Sequence<nsString> const&, bool, mozilla::ErrorResult&) (/home/allstars/src/gecko-dev/dom/html/nsHTMLDocument.cpp:1879)
GECKO(26064) | #11: nsHTMLDocument::Write(JSContext*, mozilla::dom::Sequence<nsString> const&, mozilla::ErrorResult&) (/home/allstars/src/gecko-dev/dom/html/nsHTMLDocument.cpp:2011)
GECKO(26064) | #12: mozilla::dom::HTMLDocumentBinding::write(JSContext*, JS::Handle<JSObject*>, nsHTMLDocument*, JSJitMethodCallArgs const&) (/home/allstars/src/gecko-dev/obj-x86_64-pc-linux-gnu/dom/bindings/HTMLDocumentBinding.cpp:655)
GECKO(26064) | #13: mozilla::dom::GenericBindingMethod(JSContext*, unsigned int, JS::Value*) (/home/allstars/src/gecko-dev/dom/bindings/BindingUtils.cpp:2954)
GECKO(26064) | #14: js::CallJSNative(JSContext*, bool (*)(JSContext*, unsigned int, JS::Value*), JS::CallArgs const&) (/home/allstars/src/gecko-dev/js/src/jscntxtinlines.h:293)
GECKO(26064) | #15: js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct) (/home/allstars/src/gecko-dev/js/src/vm/Interpreter.cpp:470)
GECKO(26064) | #16: InternalCall(JSContext*, js::AnyInvokeArgs const&) (/home/allstars/src/gecko-dev/js/src/vm/Interpreter.cpp:516)
GECKO(26064) | #17: js::CallFromStack(JSContext*, JS::CallArgs const&) (/home/allstars/src/gecko-dev/js/src/vm/Interpreter.cpp:522)
GECKO(26064) | #18: Interpret(JSContext*, js::RunState&) (/home/allstars/src/gecko-dev/js/src/vm/Interpreter.cpp:3028)
GECKO(26064) | #19: js::RunScript(JSContext*, js::RunState&) (/home/allstars/src/gecko-dev/js/src/vm/Interpreter.cpp:410)
GECKO(26064) | #20: js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct) (/home/allstars/src/gecko-dev/js/src/vm/Interpreter.cpp:488)
GECKO(26064) | #21: InternalCall(JSContext*, js::AnyInvokeArgs const&) (/home/allstars/src/gecko-dev/js/src/vm/Interpreter.cpp:516)
GECKO(26064) | #22: js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>) (/home/allstars/src/gecko-dev/js/src/vm/Interpreter.cpp:534)
GECKO(26064) | #23: JS::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, JS::HandleValueArray const&, JS::MutableHandle<JS::Value>) (/home/allstars/src/gecko-dev/js/src/jsapi.cpp:2891)
GECKO(26064) | #24: mozilla::dom::EventHandlerNonNull::Call(JSContext*, JS::Handle<JS::Value>, mozilla::dom::Event&, JS::MutableHandle<JS::Value>, mozilla::ErrorResult&) (/home/allstars/src/gecko-dev/obj-x86_64-pc-linux-gnu/dom/bindings/EventHandlerBinding.cpp:260 (discriminator 1))
GECKO(26064) | #25: void mozilla::dom::EventHandlerNonNull::Call<nsISupports*>(nsISupports* const&, mozilla::dom::Event&, JS::MutableHandle<JS::Value>, mozilla::ErrorResult&, char const*, mozilla::dom::CallbackObject::ExceptionHandling, JSCompartment*) (/home/allstars/src/gecko-dev/obj-x86_64-pc-linux-gnu/dist/include/mozilla/dom/EventHandlerBinding.h:357)
GECKO(26064) | #26: mozilla::JSEventHandler::HandleEvent(nsIDOMEvent*) (/home/allstars/src/gecko-dev/dom/events/JSEventHandler.cpp:215)
GECKO(26064) | #27: mozilla::EventListenerManager::HandleEventSubType(mozilla::EventListenerManager::Listener*, nsIDOMEvent*, mozilla::dom::EventTarget*) (/home/allstars/src/gecko-dev/dom/events/EventListenerManager.cpp:1146)
GECKO(26064) | #28: mozilla::EventListenerManager::HandleEventInternal(nsPresContext*, mozilla::WidgetEvent*, nsIDOMEvent**, mozilla::dom::EventTarget*, nsEventStatus*) (/home/allstars/src/gecko-dev/dom/events/EventListenerManager.cpp:1320)
GECKO(26064) | #29: mozilla::EventListenerManager::HandleEvent(nsPresContext*, mozilla::WidgetEvent*, nsIDOMEvent**, mozilla::dom::EventTarget*, nsEventStatus*) (/home/allstars/src/gecko-dev/obj-x86_64-pc-linux-gnu/dist/include/mozilla/EventListenerManager.h:377)
GECKO(26064) | #30: mozilla::EventTargetChainItem::HandleEvent(mozilla::EventChainPostVisitor&, mozilla::ELMCreationDetector&) (/home/allstars/src/gecko-dev/dom/events/EventDispatcher.cpp:319)
GECKO(26064) | #31: mozilla::EventTargetChainItem::HandleEventTargetChain(nsTArray<mozilla::EventTargetChainItem>&, mozilla::EventChainPostVisitor&, mozilla::EventDispatchingCallback*, mozilla::ELMCreationDetector&) (/home/allstars/src/gecko-dev/dom/events/EventDispatcher.cpp:466)
GECKO(26064) | #32: mozilla::EventDispatcher::Dispatch(nsISupports*, nsPresContext*, mozilla::WidgetEvent*, nsIDOMEvent*, nsEventStatus*, mozilla::EventDispatchingCallback*, nsTArray<mozilla::dom::EventTarget*>*) (/home/allstars/src/gecko-dev/dom/events/EventDispatcher.cpp:828)
GECKO(26064) | #33: nsDocumentViewer::LoadComplete(nsresult) (/home/allstars/src/gecko-dev/layout/base/nsDocumentViewer.cpp:1073)
GECKO(26064) | #34: nsDocShell::EndPageLoad(nsIWebProgress*, nsIChannel*, nsresult) (/home/allstars/src/gecko-dev/docshell/base/nsDocShell.cpp:7680)
GECKO(26064) | #35: nsDocShell::OnStateChange(nsIWebProgress*, nsIRequest*, unsigned int, nsresult) (/home/allstars/src/gecko-dev/docshell/base/nsDocShell.cpp:7472)
GECKO(26064) | #36: nsDocLoader::DoFireOnStateChange(nsIWebProgress*, nsIRequest*, int&, nsresult) (/home/allstars/src/gecko-dev/uriloader/base/nsDocLoader.cpp:1276 (discriminator 6))
GECKO(26064) | #37: nsDocLoader::doStopDocumentLoad(nsIRequest*, nsresult) (/home/allstars/src/gecko-dev/uriloader/base/nsDocLoader.cpp:859 (discriminator 2))
GECKO(26064) | #38: nsDocLoader::DocLoaderIsEmpty(bool) (/home/allstars/src/gecko-dev/uriloader/base/nsDocLoader.cpp:751)
GECKO(26064) | #39: nsDocLoader::OnStopRequest(nsIRequest*, nsISupports*, nsresult) (/home/allstars/src/gecko-dev/uriloader/base/nsDocLoader.cpp:624)
GECKO(26064) | #40: mozilla::net::nsLoadGroup::RemoveRequest(nsIRequest*, nsISupports*, nsresult) (/home/allstars/src/gecko-dev/netwerk/base/nsLoadGroup.cpp:629)
GECKO(26064) | #41: nsDocument::DoUnblockOnload() (/home/allstars/src/gecko-dev/dom/base/nsDocument.cpp:8957 (discriminator 2))
GECKO(26064) | #42: nsDocument::UnblockOnload(bool) (/home/allstars/src/gecko-dev/dom/base/nsDocument.cpp:8885)
GECKO(26064) | #43: nsDocument::DispatchContentLoadedEvents() (/home/allstars/src/gecko-dev/dom/base/nsDocument.cpp:5307)

So far I noticed the difference is, in pframe2 nsHTMLDocument::Open will be called,
and this is because the mParser is null in nsHTMLDocument.cpp.
http://searchfox.org/mozilla-central/source/dom/html/nsHTMLDocument.cpp#1928
Right, the key part is doing document.open from a srcdoc document.

And the reason this fails is that document.open tries to give the new thing the URI of the "responsible document", which we do via creating a channel for it, etc.  But "about:srcdoc" is a special URI that can't have a channel created for it, hence the stack above.

What does Chrome do if an about:srcdoc document does a document.open() on some other document?  Does that other document get "about:srcdoc" as a URI?  Does it then consider it to be an "iframe srcdoc document" or no?
Flags: needinfo?(allstars.chh)
Summary: Calling document.write in srcdoc when onload is called will throw → Calling document.write in srcdoc when onload is called (which does document.open) will throw
(In reply to Boris Zbarsky [:bz] (if a patch has no decent message, automatic r-) from comment #1)
> Right, the key part is doing document.open from a srcdoc document.
> 
> And the reason this fails is that document.open tries to give the new thing
> the URI of the "responsible document", which we do via creating a channel
> for it, etc.  But "about:srcdoc" is a special URI that can't have a channel
> created for it, hence the stack above.
>
Yeah, per spec https://html.spec.whatwg.org/multipage/infrastructure.html#urls about:srcdoc is unresolvable.
However the problem happens only in onload, if not calling document.open in onload handler it looks fine. That's also one of the reason I filed this bug.

> What does Chrome do if an about:srcdoc document does a document.open() on
> some other document?  Does that other document get "about:srcdoc" as a URI?

upload the test to https://allstarschh.github.io/test_srcdoc.html
See pframe4, 
Firefox, pframe 4: https://allstarschh.github.io/test.html
Chrome, pframe 4: about:srcdoc
 
> Does it then consider it to be an "iframe srcdoc document" or no?

I don't understand your question clearly, in Chrome the uri of pframe4 is about:srcdoc, it's considered as an 'iframe srcdoc doc', right? 

Thanks
Flags: needinfo?(allstars.chh)
Attached file test_srcdoc.html
Attachment #8871653 - Attachment is obsolete: true
> However the problem happens only in onload

I would expect it happens any time you call open() or write() on a document that is not in the middle of being parsed.

> upload the test to https://allstarschh.github.io/test_srcdoc.html

That test doesn't quite test the situation I was asking about.  The situation I was asking about is an about:srcdoc document executing script that does an open() on another document which is not being parsed.

In the test, pframe4 is the thing that is trying to test that, but it's racy: it runs at some random time, likely before pframe3 is done loading.  It might be simpler to have a manual test where the user waits for the page to load, then clicks something in pframe4 that triggers the script.

That said, it does look like Chrome is treating that open() call as something that does the no-op steps in the spec.

> in Chrome the uri of pframe4 is about:srcdoc

Yes.

> it's considered as an 'iframe srcdoc doc', right? 

That's not obvious.  You'd need to test one of the spec requirements that are special for "iframe srcdoc documents" in the spec to tell whether it is or not.  (Per spec as written it shouldn't be, but that also means that per spec you can have about:srcdoc documents that are not "iframe scrdoc documents", and it's not clear to me that this was a desired behavior in the spec.)
Flags: needinfo?(annevk)
I don't have a good idea for how to handle this at the moment.
Flags: needinfo?(annevk)
Priority: -- → P2

Is this still an issue after bug 1489308? It seems to be working fine for me...

Depends on: 1489308
Flags: needinfo?(allstars.chh)

yes, it doesn't throw now.

Status: NEW → RESOLVED
Closed: 5 years ago
Flags: needinfo?(allstars.chh)
Resolution: --- → DUPLICATE
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: