Skip to content

Commit

Permalink
Implement document.write (fixes #3704)
Browse files Browse the repository at this point in the history
This is a bit crude because of some missing utility methods on BufferQueue.
  • Loading branch information
nox committed Nov 28, 2016
1 parent 708ebdc commit 4d93ee1
Show file tree
Hide file tree
Showing 91 changed files with 235 additions and 585 deletions.
77 changes: 70 additions & 7 deletions components/script/dom/document.rs
Expand Up @@ -281,6 +281,8 @@ pub struct Document {
/// https://w3c.github.io/uievents/#event-type-dblclick
#[ignore_heap_size_of = "Defined in std"]
last_click_info: DOMRefCell<Option<(Instant, Point2D<f32>)>>,
/// https://html.spec.whatwg.org/multipage/#ignore-destructive-writes-counter
ignore_destructive_writes_counter: Cell<u32>,
}

#[derive(JSTraceable, HeapSizeOf)]
Expand Down Expand Up @@ -372,15 +374,16 @@ impl Document {
self.trigger_mozbrowser_event(MozBrowserEvent::SecurityChange(https_state));
}

// https://html.spec.whatwg.org/multipage/#active-document
pub fn is_active(&self) -> bool {
self.browsing_context().map_or(false, |context| {
self == &*context.active_document()
})
}

// https://html.spec.whatwg.org/multipage/#fully-active
pub fn is_fully_active(&self) -> bool {
let browsing_context = match self.browsing_context() {
Some(browsing_context) => browsing_context,
None => return false,
};
let active_document = browsing_context.active_document();

if self != &*active_document {
if !self.is_active() {
return false;
}
// FIXME: It should also check whether the browser context is top-level or not
Expand Down Expand Up @@ -1877,6 +1880,7 @@ impl Document {
referrer_policy: Cell::new(referrer_policy),
target_element: MutNullableHeap::new(None),
last_click_info: DOMRefCell::new(None),
ignore_destructive_writes_counter: Default::default(),
}
}

Expand Down Expand Up @@ -2053,6 +2057,16 @@ impl Document {
ReflowQueryType::NoQuery,
ReflowReason::ElementStateChanged);
}

pub fn incr_ignore_destructive_writes_counter(&self) {
self.ignore_destructive_writes_counter.set(
self.ignore_destructive_writes_counter.get() + 1);
}

pub fn decr_ignore_destructive_writes_counter(&self) {
self.ignore_destructive_writes_counter.set(
self.ignore_destructive_writes_counter.get() - 1);
}
}


Expand Down Expand Up @@ -3019,6 +3033,55 @@ impl DocumentMethods for Document {
elements
}

// https://html.spec.whatwg.org/multipage/#dom-document-write
fn Write(&self, text: Vec<DOMString>) -> ErrorResult {
if !self.is_html_document() {
// Step 1.
return Err(Error::InvalidState);
}

// Step 2.
// TODO: handle throw-on-dynamic-markup-insertion counter.

if !self.is_active() {
// Step 3.
return Ok(());
}

let parser = self.get_current_parser();
let parser = match parser.as_ref() {
Some(parser) if parser.script_nesting_level() > 0 => parser,
_ => {
// Either there is no parser, which means the parsing ended;
// or script nesting level is 0, which means the method was
// called from outside a parser-executed script.
if self.ignore_destructive_writes_counter.get() > 0 {
// Step 4.
// TODO: handle ignore-opens-during-unload counter.
return Ok(());
}
// Step 5.
// TODO: call document.open().
return Err(Error::InvalidState);
}
};

// Step 7.
// TODO: handle reload override buffer.

// Steps 6-8.
parser.write(text);

// Step 9.
Ok(())
}

// https://html.spec.whatwg.org/multipage/#dom-document-writeln
fn Writeln(&self, mut text: Vec<DOMString>) -> ErrorResult {
text.push("\n".into());
self.Write(text)
}

// https://html.spec.whatwg.org/multipage/#documentandelementeventhandlers
document_and_element_event_handlers!();
}
Expand Down
20 changes: 11 additions & 9 deletions components/script/dom/htmlscriptelement.rs
Expand Up @@ -469,19 +469,20 @@ impl HTMLScriptElement {
Ok(script) => script,
};

if script.external {
debug!("loading external script, url = {}", script.url);
}

// TODO(#12446): beforescriptexecute.
if self.dispatch_before_script_execute_event() == EventStatus::Canceled {
return;
}

// Step 3.
// TODO: If the script is from an external file, then increment the
// ignore-destructive-writes counter of the script element's node
// document. Let neutralised doc be that Document.
let neutralized_doc = if script.external {
debug!("loading external script, url = {}", script.url);
let doc = document_from_node(self);
doc.incr_ignore_destructive_writes_counter();
Some(doc)
} else {
None
};

// Step 4.
let document = document_from_node(self);
Expand All @@ -500,8 +501,9 @@ impl HTMLScriptElement {
document.set_current_script(old_script.r());

// Step 7.
// TODO: Decrement the ignore-destructive-writes counter of neutralised
// doc, if it was incremented in the earlier step.
if let Some(doc) = neutralized_doc {
doc.decr_ignore_destructive_writes_counter();
}

// TODO(#12446): afterscriptexecute.
self.dispatch_after_script_execute_event();
Expand Down

0 comments on commit 4d93ee1

Please sign in to comment.