From 6eb6e386c18663424c9b94125622bc9dd722c966 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Thu, 9 Apr 2015 00:53:28 +0200 Subject: [PATCH 1/6] Add links to CharacterData's spec --- components/script/dom/characterdata.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/components/script/dom/characterdata.rs b/components/script/dom/characterdata.rs index 2b730469582..df173ff1787 100644 --- a/components/script/dom/characterdata.rs +++ b/components/script/dom/characterdata.rs @@ -70,42 +70,50 @@ impl CharacterData { } impl<'a> CharacterDataMethods for JSRef<'a, CharacterData> { + // https://dom.spec.whatwg.org/#dom-characterdata-data fn Data(self) -> DOMString { // FIXME(https://github.com/rust-lang/rust/issues/23338) let data = self.data.borrow(); data.clone() } + // https://dom.spec.whatwg.org/#dom-characterdata-data fn SetData(self, arg: DOMString) -> ErrorResult { *self.data.borrow_mut() = arg; Ok(()) } + // https://dom.spec.whatwg.org/#dom-characterdata-length fn Length(self) -> u32 { // FIXME(https://github.com/rust-lang/rust/issues/23338) let data = self.data.borrow(); data.chars().count() as u32 } + // https://dom.spec.whatwg.org/#dom-characterdata-substringdata fn SubstringData(self, offset: u32, count: u32) -> Fallible { // FIXME(https://github.com/rust-lang/rust/issues/23338) let data = self.data.borrow(); Ok(data.slice_chars(offset as usize, (offset + count) as usize).to_owned()) } + // https://dom.spec.whatwg.org/#dom-characterdata-appenddata fn AppendData(self, arg: DOMString) -> ErrorResult { self.data.borrow_mut().push_str(arg.as_slice()); Ok(()) } + // https://dom.spec.whatwg.org/#dom-characterdata-insertdata fn InsertData(self, offset: u32, arg: DOMString) -> ErrorResult { self.ReplaceData(offset, 0, arg) } + // https://dom.spec.whatwg.org/#dom-characterdata-deletedata fn DeleteData(self, offset: u32, count: u32) -> ErrorResult { self.ReplaceData(offset, count, "".to_owned()) } + // https://dom.spec.whatwg.org/#dom-characterdata-replacedata fn ReplaceData(self, offset: u32, count: u32, arg: DOMString) -> ErrorResult { let length = self.data.borrow().chars().count() as u32; if offset > length { From 14cd68221026a4e3a8c26200d36be982d9f72623 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Thu, 9 Apr 2015 01:02:32 +0200 Subject: [PATCH 2/6] Fix CharacterData annotations --- components/script/dom/characterdata.rs | 10 ++++------ components/script/dom/webidls/CharacterData.webidl | 3 +-- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/components/script/dom/characterdata.rs b/components/script/dom/characterdata.rs index df173ff1787..f10516c5278 100644 --- a/components/script/dom/characterdata.rs +++ b/components/script/dom/characterdata.rs @@ -78,9 +78,8 @@ impl<'a> CharacterDataMethods for JSRef<'a, CharacterData> { } // https://dom.spec.whatwg.org/#dom-characterdata-data - fn SetData(self, arg: DOMString) -> ErrorResult { - *self.data.borrow_mut() = arg; - Ok(()) + fn SetData(self, data: DOMString) { + *self.data.borrow_mut() = data; } // https://dom.spec.whatwg.org/#dom-characterdata-length @@ -98,9 +97,8 @@ impl<'a> CharacterDataMethods for JSRef<'a, CharacterData> { } // https://dom.spec.whatwg.org/#dom-characterdata-appenddata - fn AppendData(self, arg: DOMString) -> ErrorResult { - self.data.borrow_mut().push_str(arg.as_slice()); - Ok(()) + fn AppendData(self, data: DOMString) { + self.data.borrow_mut().push_str(&data); } // https://dom.spec.whatwg.org/#dom-characterdata-insertdata diff --git a/components/script/dom/webidls/CharacterData.webidl b/components/script/dom/webidls/CharacterData.webidl index 39f304e0e39..e758adb4d30 100644 --- a/components/script/dom/webidls/CharacterData.webidl +++ b/components/script/dom/webidls/CharacterData.webidl @@ -11,11 +11,10 @@ */ interface CharacterData : Node { - [TreatNullAs=EmptyString,SetterThrows] attribute DOMString data; + [TreatNullAs=EmptyString] attribute DOMString data; readonly attribute unsigned long length; [Throws] DOMString substringData(unsigned long offset, unsigned long count); - [Throws] void appendData(DOMString data); [Throws] void insertData(unsigned long offset, DOMString data); From c8f41b473cbe69be8bfd17fc02318b1b6520e76a Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Thu, 9 Apr 2015 01:47:51 +0200 Subject: [PATCH 3/6] Remove CharacterData::set_data() --- components/script/dom/characterdata.rs | 5 ----- components/script/dom/node.rs | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/components/script/dom/characterdata.rs b/components/script/dom/characterdata.rs index f10516c5278..1796663acf0 100644 --- a/components/script/dom/characterdata.rs +++ b/components/script/dom/characterdata.rs @@ -56,11 +56,6 @@ impl CharacterData { self.data.borrow() } - #[inline] - pub fn set_data(&self, data: DOMString) { - *self.data.borrow_mut() = data; - } - #[inline] #[allow(unsafe_code)] pub unsafe fn data_for_layout<'a>(&'a self) -> &'a str { diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index 5368a012846..f6c7adc2668 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -1880,7 +1880,7 @@ impl<'a> NodeMethods for JSRef<'a, Node> { NodeTypeId::Text | NodeTypeId::ProcessingInstruction => { let characterdata: JSRef = CharacterDataCast::to_ref(self).unwrap(); - characterdata.set_data(value); + characterdata.SetData(value); // Notify the document that the content of this node is different let document = self.owner_doc().root(); From 45b490c977749618d200dbed77e7a098967d6864 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Thu, 9 Apr 2015 02:06:48 +0200 Subject: [PATCH 4/6] Generate from_layout_js() conversion methods --- components/script/dom/bindings/codegen/CodegenRust.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index 650d1507b77..dd788146acd 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -5427,6 +5427,12 @@ impl ${name}Cast { unsafe { derived.transmute_borrowed() } } + #[inline(always)] + #[allow(unrooted_must_root)] + pub fn from_layout_js(derived: &LayoutJS) -> LayoutJS<${name}> { + unsafe { derived.transmute_copy() } + } + #[inline(always)] pub fn from_temporary(derived: Temporary) -> Temporary<${name}> { unsafe { derived.transmute() } From 8f73b452fb36cceed9d7a3aa253d937c338983b3 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Thu, 9 Apr 2015 02:07:15 +0200 Subject: [PATCH 5/6] Cleanup access to CharacterData nodes --- components/layout/wrapper.rs | 16 +++---- components/script/dom/characterdata.rs | 42 +++++++++++-------- components/script/dom/comment.rs | 5 --- components/script/dom/document.rs | 5 ++- components/script/dom/htmltitleelement.rs | 5 ++- components/script/dom/node.rs | 25 ++++++----- .../script/dom/processinginstruction.rs | 4 -- components/script/dom/text.rs | 5 --- components/script/parse/html.rs | 22 +++++----- 9 files changed, 60 insertions(+), 69 deletions(-) diff --git a/components/layout/wrapper.rs b/components/layout/wrapper.rs index b599e75d745..137a2e469b6 100644 --- a/components/layout/wrapper.rs +++ b/components/layout/wrapper.rs @@ -41,11 +41,12 @@ use opaque_node::OpaqueNodeMethods; use cssparser::RGBA; use gfx::display_list::OpaqueNode; -use script::dom::bindings::codegen::InheritTypes::{ElementCast, HTMLIFrameElementCast}; -use script::dom::bindings::codegen::InheritTypes::{HTMLCanvasElementCast, HTMLImageElementCast}; -use script::dom::bindings::codegen::InheritTypes::{HTMLInputElementCast, HTMLTextAreaElementCast}; -use script::dom::bindings::codegen::InheritTypes::{NodeCast, TextCast}; +use script::dom::bindings::codegen::InheritTypes::{CharacterDataCast, ElementCast}; +use script::dom::bindings::codegen::InheritTypes::{HTMLIFrameElementCast, HTMLCanvasElementCast}; +use script::dom::bindings::codegen::InheritTypes::{HTMLImageElementCast, HTMLInputElementCast}; +use script::dom::bindings::codegen::InheritTypes::{HTMLTextAreaElementCast, NodeCast, TextCast}; use script::dom::bindings::js::LayoutJS; +use script::dom::characterdata::LayoutCharacterDataHelpers; use script::dom::element::{Element, ElementTypeId}; use script::dom::element::{LayoutElementHelpers, RawLayoutElementHelpers}; use script::dom::htmlelement::HTMLElementTypeId; @@ -222,9 +223,8 @@ impl<'ln> TLayoutNode for LayoutNode<'ln> { let text: Option> = TextCast::to_layout_js(self.get_jsmanaged()); if let Some(text) = text { return vec![ - ContentItem::String((*text.unsafe_get()).characterdata() - .data_for_layout() - .to_owned()) + ContentItem::String( + CharacterDataCast::from_layout_js(&text).data_for_layout().to_owned()) ]; } let input: Option> = @@ -961,7 +961,7 @@ impl<'ln> ThreadSafeLayoutNode<'ln> { None => return false }; - if !is_whitespace((*text.unsafe_get()).characterdata().data_for_layout()) { + if !is_whitespace(CharacterDataCast::from_layout_js(&text).data_for_layout()) { return false } diff --git a/components/script/dom/characterdata.rs b/components/script/dom/characterdata.rs index 1796663acf0..82fcc459fec 100644 --- a/components/script/dom/characterdata.rs +++ b/components/script/dom/characterdata.rs @@ -10,7 +10,7 @@ use dom::bindings::codegen::InheritTypes::{CharacterDataDerived, ElementCast}; use dom::bindings::codegen::InheritTypes::NodeCast; use dom::bindings::error::{Fallible, ErrorResult}; use dom::bindings::error::Error::IndexSize; -use dom::bindings::js::{JSRef, Temporary}; +use dom::bindings::js::{JSRef, LayoutJS, Temporary}; use dom::document::Document; use dom::element::Element; use dom::eventtarget::{EventTarget, EventTargetTypeId}; @@ -45,23 +45,6 @@ impl CharacterData { data: DOMRefCell::new(data), } } - - #[inline] - pub fn node<'a>(&'a self) -> &'a Node { - &self.node - } - - #[inline] - pub fn data(&self) -> Ref { - self.data.borrow() - } - - #[inline] - #[allow(unsafe_code)] - pub unsafe fn data_for_layout<'a>(&'a self) -> &'a str { - self.data.borrow_for_layout().as_slice() - } - } impl<'a> CharacterDataMethods for JSRef<'a, CharacterData> { @@ -144,3 +127,26 @@ impl<'a> CharacterDataMethods for JSRef<'a, CharacterData> { } } +pub trait CharacterDataHelpers<'a> { + fn data(self) -> Ref<'a, DOMString>; +} + +impl<'a> CharacterDataHelpers<'a> for JSRef<'a, CharacterData> { + #[inline] + fn data(self) -> Ref<'a, DOMString> { + self.extended_deref().data.borrow() + } +} + +#[allow(unsafe_code)] +pub trait LayoutCharacterDataHelpers { + unsafe fn data_for_layout<'a>(&'a self) -> &'a str; +} + +#[allow(unsafe_code)] +impl LayoutCharacterDataHelpers for LayoutJS { + #[inline] + unsafe fn data_for_layout<'a>(&'a self) -> &'a str { + &(*self.unsafe_get()).data.borrow_for_layout() + } +} diff --git a/components/script/dom/comment.rs b/components/script/dom/comment.rs index 85cca18b2b2..743e935db01 100644 --- a/components/script/dom/comment.rs +++ b/components/script/dom/comment.rs @@ -42,10 +42,5 @@ impl Comment { let document = global.as_window().Document().root(); Ok(Comment::new(data, document.r())) } - - #[inline] - pub fn characterdata<'a>(&'a self) -> &'a CharacterData { - &self.characterdata - } } diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 9812cf13f0b..ca4182164d8 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -18,7 +18,7 @@ use dom::bindings::codegen::InheritTypes::{EventTargetCast, HTMLAnchorElementCas use dom::bindings::codegen::InheritTypes::{HTMLAnchorElementDerived, HTMLAppletElementDerived}; use dom::bindings::codegen::InheritTypes::{HTMLAreaElementDerived, HTMLEmbedElementDerived}; use dom::bindings::codegen::InheritTypes::{HTMLFormElementDerived, HTMLImageElementDerived}; -use dom::bindings::codegen::InheritTypes::{HTMLScriptElementDerived}; +use dom::bindings::codegen::InheritTypes::{HTMLScriptElementDerived, CharacterDataCast}; use dom::bindings::error::{ErrorResult, Fallible}; use dom::bindings::error::Error::{NotSupported, InvalidCharacter, Security}; use dom::bindings::error::Error::HierarchyRequest; @@ -29,6 +29,7 @@ use dom::bindings::refcounted::Trusted; use dom::bindings::utils::reflect_dom_object; use dom::bindings::utils::{xml_name_type, validate_and_extract}; use dom::bindings::utils::XMLName::InvalidXMLName; +use dom::characterdata::CharacterDataHelpers; use dom::comment::Comment; use dom::customevent::CustomEvent; use dom::documentfragment::DocumentFragment; @@ -1125,7 +1126,7 @@ impl<'a> DocumentMethods for JSRef<'a, Document> { for child in title_element.children() { let child = child.root(); if let Some(text) = TextCast::to_ref(child.r()) { - title.push_str(&text.characterdata().data()); + title.push_str(&CharacterDataCast::from_ref(text).data()); } } } diff --git a/components/script/dom/htmltitleelement.rs b/components/script/dom/htmltitleelement.rs index df2592acef9..5fb9cd3b25f 100644 --- a/components/script/dom/htmltitleelement.rs +++ b/components/script/dom/htmltitleelement.rs @@ -6,8 +6,9 @@ use dom::bindings::codegen::Bindings::HTMLTitleElementBinding; use dom::bindings::codegen::Bindings::HTMLTitleElementBinding::HTMLTitleElementMethods; use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLTitleElementDerived, NodeCast}; -use dom::bindings::codegen::InheritTypes::{TextCast}; +use dom::bindings::codegen::InheritTypes::{CharacterDataCast, TextCast}; use dom::bindings::js::{JSRef, Temporary}; +use dom::characterdata::CharacterDataHelpers; use dom::document::{Document, DocumentHelpers}; use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::element::ElementTypeId; @@ -51,7 +52,7 @@ impl<'a> HTMLTitleElementMethods for JSRef<'a, HTMLTitleElement> { let child = child.root(); let text: Option> = TextCast::to_ref(child.r()); match text { - Some(text) => content.push_str(text.characterdata().data().as_slice()), + Some(text) => content.push_str(&CharacterDataCast::from_ref(text).data()), None => (), } } diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index f6c7adc2668..89ec44718eb 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -13,12 +13,11 @@ use dom::bindings::codegen::Bindings::NamedNodeMapBinding::NamedNodeMapMethods; use dom::bindings::codegen::Bindings::NodeBinding::{NodeConstants, NodeMethods}; use dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods; use dom::bindings::codegen::Bindings::ProcessingInstructionBinding::ProcessingInstructionMethods; -use dom::bindings::codegen::InheritTypes::{CommentCast, DocumentCast, DocumentTypeCast}; -use dom::bindings::codegen::InheritTypes::{ElementCast, TextCast, NodeCast, ElementDerived}; -use dom::bindings::codegen::InheritTypes::{CharacterDataCast, NodeBase, NodeDerived}; -use dom::bindings::codegen::InheritTypes::{ProcessingInstructionCast, EventTargetCast}; +use dom::bindings::codegen::InheritTypes::{CharacterDataCast, DocumentCast, DocumentTypeCast}; +use dom::bindings::codegen::InheritTypes::{ElementCast, NodeCast, ElementDerived, EventTargetCast}; use dom::bindings::codegen::InheritTypes::{HTMLLegendElementDerived, HTMLFieldSetElementDerived}; -use dom::bindings::codegen::InheritTypes::HTMLOptGroupElementDerived; +use dom::bindings::codegen::InheritTypes::{HTMLOptGroupElementDerived, NodeBase, NodeDerived}; +use dom::bindings::codegen::InheritTypes::{ProcessingInstructionCast, TextCast}; use dom::bindings::conversions; use dom::bindings::error::Fallible; use dom::bindings::error::Error::{NotFound, HierarchyRequest, Syntax}; @@ -29,7 +28,7 @@ use dom::bindings::js::{ResultRootable, OptionalRootable, MutNullableJS}; use dom::bindings::trace::JSTraceable; use dom::bindings::trace::RootedVec; use dom::bindings::utils::{Reflectable, reflect_dom_object}; -use dom::characterdata::CharacterData; +use dom::characterdata::{CharacterData, CharacterDataHelpers}; use dom::comment::Comment; use dom::document::{Document, DocumentHelpers, IsHTMLDocument, DocumentSource}; use dom::documentfragment::DocumentFragment; @@ -1601,8 +1600,8 @@ impl Node { NodeCast::from_temporary(doc_fragment) }, NodeTypeId::Comment => { - let comment: JSRef = CommentCast::to_ref(node).unwrap(); - let comment = Comment::new(comment.characterdata().data().clone(), document.r()); + let cdata = CharacterDataCast::to_ref(node).unwrap(); + let comment = Comment::new(cdata.Data(), document.r()); NodeCast::from_temporary(comment) }, NodeTypeId::Document => { @@ -1629,14 +1628,14 @@ impl Node { NodeCast::from_temporary(element) }, NodeTypeId::Text => { - let text: JSRef = TextCast::to_ref(node).unwrap(); - let text = Text::new(text.characterdata().data().clone(), document.r()); + let cdata = CharacterDataCast::to_ref(node).unwrap(); + let text = Text::new(cdata.Data(), document.r()); NodeCast::from_temporary(text) }, NodeTypeId::ProcessingInstruction => { let pi: JSRef = ProcessingInstructionCast::to_ref(node).unwrap(); let pi = ProcessingInstruction::new(pi.target().clone(), - pi.characterdata().data().clone(), document.r()); + CharacterDataCast::from_ref(pi).Data(), document.r()); NodeCast::from_temporary(pi) }, }.root(); @@ -1696,7 +1695,7 @@ impl Node { let node = node.root(); let text = TextCast::to_ref(node.r()); match text { - Some(text) => content.push_str(text.characterdata().data().as_slice()), + Some(text) => content.push_str(&CharacterDataCast::from_ref(text).Data()), None => (), } } @@ -2123,7 +2122,7 @@ impl<'a> NodeMethods for JSRef<'a, Node> { let pi: JSRef = ProcessingInstructionCast::to_ref(node).unwrap(); let other_pi: JSRef = ProcessingInstructionCast::to_ref(other).unwrap(); (*pi.target() == *other_pi.target()) && - (*pi.characterdata().data() == *other_pi.characterdata().data()) + (*CharacterDataCast::from_ref(pi).data() == *CharacterDataCast::from_ref(other_pi).data()) } fn is_equal_characterdata(node: JSRef, other: JSRef) -> bool { let characterdata: JSRef = CharacterDataCast::to_ref(node).unwrap(); diff --git a/components/script/dom/processinginstruction.rs b/components/script/dom/processinginstruction.rs index 528c4cdd64a..c9d102b9862 100644 --- a/components/script/dom/processinginstruction.rs +++ b/components/script/dom/processinginstruction.rs @@ -38,10 +38,6 @@ impl ProcessingInstruction { document, ProcessingInstructionBinding::Wrap) } - pub fn characterdata<'a>(&'a self) -> &'a CharacterData { - &self.characterdata - } - pub fn target<'a>(&'a self) -> &'a DOMString { &self.target } diff --git a/components/script/dom/text.rs b/components/script/dom/text.rs index ea6c2791e96..c2e9c588665 100644 --- a/components/script/dom/text.rs +++ b/components/script/dom/text.rs @@ -42,10 +42,5 @@ impl Text { let document = global.as_window().Document().root(); Ok(Text::new(text, document.r())) } - - #[inline] - pub fn characterdata<'a>(&'a self) -> &'a CharacterData { - &self.characterdata - } } diff --git a/components/script/parse/html.rs b/components/script/parse/html.rs index 66a95f2e879..d3e6b981783 100644 --- a/components/script/parse/html.rs +++ b/components/script/parse/html.rs @@ -7,13 +7,14 @@ use dom::attr::AttrHelpers; use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods; use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; -use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast, HTMLScriptElementCast}; -use dom::bindings::codegen::InheritTypes::{DocumentTypeCast, TextCast, CommentCast}; +use dom::bindings::codegen::InheritTypes::{CharacterDataCast, DocumentTypeCast}; +use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLScriptElementCast}; +use dom::bindings::codegen::InheritTypes::{HTMLFormElementDerived, NodeCast}; use dom::bindings::codegen::InheritTypes::ProcessingInstructionCast; -use dom::bindings::codegen::InheritTypes::HTMLFormElementDerived; use dom::bindings::js::{JS, JSRef, Temporary, OptionalRootable, Root}; use dom::bindings::js::RootedReference; use dom::bindings::trace::RootedVec; +use dom::characterdata::CharacterDataHelpers; use dom::comment::Comment; use dom::document::{Document, DocumentHelpers}; use dom::document::{DocumentSource, IsHTMLDocument}; @@ -234,22 +235,19 @@ impl<'a> Serializable for JSRef<'a, Node> { }, (IncludeNode, NodeTypeId::Text) => { - let text: JSRef = TextCast::to_ref(node).unwrap(); - let data = text.characterdata().data(); - serializer.write_text(data.as_slice()) + let cdata = CharacterDataCast::to_ref(node).unwrap(); + serializer.write_text(&cdata.data()) }, (IncludeNode, NodeTypeId::Comment) => { - let comment: JSRef = CommentCast::to_ref(node).unwrap(); - let data = comment.characterdata().data(); - serializer.write_comment(data.as_slice()) + let cdata = CharacterDataCast::to_ref(node).unwrap(); + serializer.write_comment(&cdata.data()) }, (IncludeNode, NodeTypeId::ProcessingInstruction) => { let pi: JSRef = ProcessingInstructionCast::to_ref(node).unwrap(); - let data = pi.characterdata().data(); - serializer.write_processing_instruction(pi.target().as_slice(), - data.as_slice()) + let data = CharacterDataCast::from_ref(pi).data(); + serializer.write_processing_instruction(&pi.target(), &data) }, (IncludeNode, NodeTypeId::DocumentFragment) => Ok(()), From 702cea6fc31241d6dd9d211db208ce7ff09cbda3 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Thu, 9 Apr 2015 02:40:47 +0200 Subject: [PATCH 6/6] Fix CharacterData::SubstringData() It was not following the spec and it could panic. --- components/script/dom/characterdata.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/components/script/dom/characterdata.rs b/components/script/dom/characterdata.rs index 82fcc459fec..172fda96f47 100644 --- a/components/script/dom/characterdata.rs +++ b/components/script/dom/characterdata.rs @@ -20,6 +20,7 @@ use util::str::DOMString; use std::borrow::ToOwned; use std::cell::Ref; +use std::cmp; #[dom_struct] pub struct CharacterData { @@ -69,9 +70,17 @@ impl<'a> CharacterDataMethods for JSRef<'a, CharacterData> { // https://dom.spec.whatwg.org/#dom-characterdata-substringdata fn SubstringData(self, offset: u32, count: u32) -> Fallible { - // FIXME(https://github.com/rust-lang/rust/issues/23338) let data = self.data.borrow(); - Ok(data.slice_chars(offset as usize, (offset + count) as usize).to_owned()) + // Step 1. + let len = data.chars().count(); + if len > offset as usize { + // Step 2. + return Err(IndexSize); + } + // Step 3. + let end = cmp::min((offset + count) as usize, len); + // Step 4. + Ok(data.slice_chars(offset as usize, end).to_owned()) } // https://dom.spec.whatwg.org/#dom-characterdata-appenddata