aboutsummaryrefslogtreecommitdiffstats
path: root/components/util/str.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/util/str.rs')
-rw-r--r--components/util/str.rs84
1 files changed, 84 insertions, 0 deletions
diff --git a/components/util/str.rs b/components/util/str.rs
index 80e5fb04d6c..afbced05ac4 100644
--- a/components/util/str.rs
+++ b/components/util/str.rs
@@ -4,15 +4,23 @@
use app_units::Au;
use cssparser::{self, Color, RGBA};
+use js::conversions::{FromJSValConvertible, ToJSValConvertible, latin1_to_string};
+use js::jsapi::{JSContext, JSString, HandleValue, MutableHandleValue};
+use js::jsapi::{JS_GetTwoByteStringCharsAndLength, JS_StringHasLatin1Chars};
+use js::rust::ToString;
use libc::c_char;
use num_lib::ToPrimitive;
+use opts;
use std::ascii::AsciiExt;
use std::borrow::ToOwned;
+use std::char;
use std::convert::AsRef;
use std::ffi::CStr;
use std::fmt;
use std::iter::{Filter, Peekable};
use std::ops::{Deref, DerefMut};
+use std::ptr;
+use std::slice;
use std::str::{CharIndices, FromStr, Split, from_utf8};
#[derive(Clone, PartialOrd, Ord, PartialEq, Eq, Deserialize, Serialize, Hash, Debug)]
@@ -71,6 +79,82 @@ impl Into<Vec<u8>> for DOMString {
}
}
+// https://heycam.github.io/webidl/#es-DOMString
+impl ToJSValConvertible for DOMString {
+ unsafe fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) {
+ (**self).to_jsval(cx, rval);
+ }
+}
+
+/// Behavior for stringification of `JSVal`s.
+#[derive(PartialEq)]
+pub enum StringificationBehavior {
+ /// Convert `null` to the string `"null"`.
+ Default,
+ /// Convert `null` to the empty string.
+ Empty,
+}
+
+/// Convert the given `JSString` to a `DOMString`. Fails if the string does not
+/// contain valid UTF-16.
+pub unsafe fn jsstring_to_str(cx: *mut JSContext, s: *mut JSString) -> DOMString {
+ let latin1 = JS_StringHasLatin1Chars(s);
+ DOMString(if latin1 {
+ latin1_to_string(cx, s)
+ } else {
+ let mut length = 0;
+ let chars = JS_GetTwoByteStringCharsAndLength(cx, ptr::null(), s, &mut length);
+ assert!(!chars.is_null());
+ let potentially_ill_formed_utf16 = slice::from_raw_parts(chars, length as usize);
+ let mut s = String::with_capacity(length as usize);
+ for item in char::decode_utf16(potentially_ill_formed_utf16.iter().cloned()) {
+ match item {
+ Ok(c) => s.push(c),
+ Err(_) => {
+ // FIXME: Add more info like document URL in the message?
+ macro_rules! message {
+ () => {
+ "Found an unpaired surrogate in a DOM string. \
+ If you see this in real web content, \
+ please comment on https://github.com/servo/servo/issues/6564"
+ }
+ }
+ if opts::get().replace_surrogates {
+ error!(message!());
+ s.push('\u{FFFD}');
+ } else {
+ panic!(concat!(message!(), " Use `-Z replace-surrogates` \
+ on the command line to make this non-fatal."));
+ }
+ }
+ }
+ }
+ s
+ })
+}
+
+// https://heycam.github.io/webidl/#es-DOMString
+impl FromJSValConvertible for DOMString {
+ type Config = StringificationBehavior;
+ unsafe fn from_jsval(cx: *mut JSContext,
+ value: HandleValue,
+ null_behavior: StringificationBehavior)
+ -> Result<DOMString, ()> {
+ if null_behavior == StringificationBehavior::Empty &&
+ value.get().is_null() {
+ Ok(DOMString::new())
+ } else {
+ let jsstr = ToString(cx, value);
+ if jsstr.is_null() {
+ debug!("ToString failed");
+ Err(())
+ } else {
+ Ok(jsstring_to_str(cx, jsstr))
+ }
+ }
+ }
+}
+
pub type StaticCharVec = &'static [char];
pub type StaticStringVec = &'static [&'static str];