Make CreateElement comply with the spec.

This commit is contained in:
Jack Moffitt 2013-09-11 16:41:48 -06:00
parent 34f740396e
commit 0695e09568
3 changed files with 70 additions and 3 deletions

View file

@ -770,6 +770,7 @@ pub enum Error {
FailureUnknown,
NotFound,
HierarchyRequest,
InvalidCharacter,
}
pub type ErrorResult = Result<(), Error>;
@ -832,3 +833,59 @@ pub fn CreateDOMGlobal(cx: *JSContext, class: *JSClass) -> *JSObject {
obj
}
}
/// Check if an element name is valid. See http://www.w3.org/TR/xml/#NT-Name
/// for details.
pub fn is_valid_element_name(name: &str) -> bool {
fn is_valid_start(c: char) -> bool {
match c {
':' |
'A' .. 'Z' |
'_' |
'a' .. 'z' |
'\xC0' .. '\xD6' |
'\xD8' .. '\xF6' |
'\xF8' .. '\u02FF' |
'\u0370' .. '\u037D' |
'\u037F' .. '\u1FFF' |
'\u200C' .. '\u200D' |
'\u2070' .. '\u218F' |
'\u2C00' .. '\u2FEF' |
'\u3001' .. '\uD7FF' |
'\uF900' .. '\uFDCF' |
'\uFDF0' .. '\uFFFD' |
'\U00010000' .. '\U000EFFFF' => true,
_ => false,
}
}
fn is_valid_continuation(c: char) -> bool {
is_valid_start(c) || match c {
'-' |
'.' |
'0' .. '9' |
'\xB7' |
'\u0300' .. '\u036F' |
'\u203F' .. '\u2040' => true,
_ => false,
}
}
let mut iter = name.iter();
match iter.next() {
None => return false,
Some(c) => {
if !is_valid_start(c) {
return false;
}
}
}
for c in name.iter() {
if !is_valid_continuation(c) {
return false;
}
}
true
}

View file

@ -5,7 +5,7 @@
use dom::bindings::codegen::DocumentBinding;
use dom::bindings::utils::{DOMString, WrapperCache, ErrorResult, null_string, str};
use dom::bindings::utils::{BindingObject, CacheableWrapper, rust_box, DerivedWrapper};
use dom::bindings::utils::Traceable;
use dom::bindings::utils::{is_valid_element_name, InvalidCharacter, Traceable};
use dom::element::{Element};
use dom::element::{HTMLHtmlElementTypeId, HTMLHeadElementTypeId, HTMLTitleElementTypeId};
use dom::event::Event;
@ -28,6 +28,7 @@ use std::cast;
use std::ptr;
use std::str::eq_slice;
use std::libc;
use std::ascii::StrAsciiExt;
pub trait WrappableDocument {
fn init_wrapper(@mut self, cx: *JSContext);
@ -240,9 +241,16 @@ impl Document {
None
}
pub fn CreateElement(&self, local_name: &DOMString, _rv: &mut ErrorResult) -> AbstractNode<ScriptView> {
pub fn CreateElement(&self, local_name: &DOMString, rv: &mut ErrorResult) -> AbstractNode<ScriptView> {
let cx = self.get_cx();
build_element_from_tag(cx, local_name.to_str())
let local_name = local_name.to_str();
if !is_valid_element_name(local_name) {
*rv = Err(InvalidCharacter);
// FIXME #909: what to return here?
fail!("invalid character");
}
let local_name = local_name.to_ascii_lower();
build_element_from_tag(cx, local_name)
}
pub fn CreateElementNS(&self, _namespace: &DOMString, _qualified_name: &DOMString, _rv: &mut ErrorResult) -> AbstractNode<ScriptView> {

View file

@ -9,6 +9,8 @@
is(elem.tagName, "FOO");
var elem = document.createElement("p");
is(elem instanceof HTMLParagraphElement, true);
var elem = document.createElement("sPAn");
is(elem instanceof HTMLSpanElement, true);
var text = document.createTextNode("hello");
is(text instanceof Text, true);
finish();