mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
auto merge of #1206 : Ms2ger/servo/strings, r=jdm
I'll probably do a followup to actually pass non-nullable strings to the native functions.
This commit is contained in:
commit
4297aa33ad
2 changed files with 98 additions and 93 deletions
|
@ -443,7 +443,6 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
|
|||
invalidEnumValueFatal=True,
|
||||
defaultValue=None,
|
||||
treatNullAs="Default",
|
||||
treatUndefinedAs="Default",
|
||||
isEnforceRange=False,
|
||||
isClamp=False,
|
||||
exceptionCode=None,
|
||||
|
@ -1058,37 +1057,31 @@ for (uint32_t i = 0; i < length; ++i) {
|
|||
assert not isEnforceRange and not isClamp
|
||||
|
||||
treatAs = {
|
||||
"Default": "eStringify",
|
||||
"EmptyString": "eEmpty",
|
||||
"Null": "eNull"
|
||||
"Default": "Default",
|
||||
"EmptyString": "Empty",
|
||||
}
|
||||
if type.nullable():
|
||||
# For nullable strings null becomes a null string.
|
||||
treatNullAs = "Null"
|
||||
# For nullable strings undefined becomes a null string unless
|
||||
# specified otherwise.
|
||||
if treatUndefinedAs == "Default":
|
||||
treatUndefinedAs = "Null"
|
||||
if treatNullAs not in treatAs:
|
||||
raise TypeError("We don't support [TreatNullAs=%s]" % treatNullAs)
|
||||
nullBehavior = treatAs[treatNullAs]
|
||||
if treatUndefinedAs == "Missing":
|
||||
raise TypeError("We don't support [TreatUndefinedAs=Missing]")
|
||||
undefinedBehavior = treatAs[treatUndefinedAs]
|
||||
|
||||
def getConversionCode(varName, isOptional=False):
|
||||
#XXXjdm support nullBehavior and undefinedBehavior
|
||||
#conversionCode = (
|
||||
# "if (!ConvertJSValueToString(cx, ${val}, ${valPtr}, %s, %s, %s)) {\n"
|
||||
# " return false;\n"
|
||||
# "}" % (nullBehavior, undefinedBehavior, varName))
|
||||
strval = "Some(strval.unwrap())"
|
||||
strval = "strval"
|
||||
if not type.nullable():
|
||||
# XXX #1207 Actually pass non-nullable strings to callees.
|
||||
strval = "Some(%s)" % strval
|
||||
if isOptional:
|
||||
strval = "Some(%s)" % strval
|
||||
if type.nullable():
|
||||
call = "jsval_to_domstring(cx, ${val})"
|
||||
else:
|
||||
call = "jsval_to_str(cx, ${val}, %s)" % nullBehavior
|
||||
conversionCode = (
|
||||
"let strval = jsval_to_str(cx, ${val});\n"
|
||||
"let strval = %s;\n"
|
||||
"if strval.is_err() {\n"
|
||||
" return 0;\n"
|
||||
"}\n"
|
||||
"%s = %s;" % (varName, strval))
|
||||
"let strval = strval.unwrap();\n"
|
||||
"%s = %s;" % (call, varName, strval))
|
||||
if defaultValue is None:
|
||||
return conversionCode
|
||||
|
||||
|
@ -1456,7 +1449,6 @@ class CGArgumentConverter(CGThing):
|
|||
invalidEnumValueFatal=self.invalidEnumValueFatal,
|
||||
defaultValue=self.argument.defaultValue,
|
||||
treatNullAs=self.argument.treatNullAs,
|
||||
treatUndefinedAs=self.argument.treatUndefinedAs,
|
||||
isEnforceRange=self.argument.enforceRange,
|
||||
isClamp=self.argument.clamp),
|
||||
self.replacementVariables,
|
||||
|
@ -3189,7 +3181,6 @@ class FakeArgument():
|
|||
self.variadic = False
|
||||
self.defaultValue = None
|
||||
self.treatNullAs = interfaceMember.treatNullAs
|
||||
self.treatUndefinedAs = interfaceMember.treatUndefinedAs
|
||||
self.enforceRange = False
|
||||
self.clamp = False
|
||||
|
||||
|
@ -4089,8 +4080,7 @@ class CGProxySpecialOperation(CGPerSignatureCall):
|
|||
# arguments[0] is the index or name of the item that we're setting.
|
||||
argument = arguments[1]
|
||||
template = getJSToNativeConversionTemplate(argument.type, descriptor,
|
||||
treatNullAs=argument.treatNullAs,
|
||||
treatUndefinedAs=argument.treatUndefinedAs)
|
||||
treatNullAs=argument.treatNullAs)
|
||||
templateValues = {
|
||||
"declName": argument.identifier.name,
|
||||
"holderName": argument.identifier.name + "_holder",
|
||||
|
@ -4231,16 +4221,7 @@ class CGDOMJSProxyHandler_getOwnPropertyDescriptor(CGAbstractExternMethod):
|
|||
# properties that shadow prototype properties.
|
||||
namedGet = ("\n" +
|
||||
"if set == 0 && RUST_JSID_IS_STRING(id) != 0 && !HasPropertyOnPrototype(cx, proxy, id) {\n" +
|
||||
" let nameVal = RUST_STRING_TO_JSVAL(RUST_JSID_TO_STRING(id));\n" +
|
||||
" //FakeDependentString name;\n"
|
||||
" //if (!ConvertJSValueToString(cx, nameVal, &nameVal,\n" +
|
||||
" // eStringify, eStringify, name)) {\n" +
|
||||
" let strval = jsval_to_str(cx, nameVal);\n" +
|
||||
" if strval.is_err() {\n" +
|
||||
" return 0;\n" +
|
||||
" }\n" +
|
||||
" let name = Some(strval.unwrap());\n" +
|
||||
"\n" +
|
||||
" let name = Some(jsid_to_str(cx, id));\n" +
|
||||
" let this: *%s = UnwrapProxy(proxy);\n" +
|
||||
CGIndenter(CGProxyNamedGetter(self.descriptor, templateValues)).define() + "\n" +
|
||||
"}\n") % (self.descriptor.concreteType)
|
||||
|
@ -4298,33 +4279,14 @@ class CGDOMJSProxyHandler_defineProperty(CGAbstractExternMethod):
|
|||
if namedSetter:
|
||||
if not self.descriptor.operations['NamedCreator'] is namedSetter:
|
||||
raise TypeError("Can't handle creator that's different from the setter")
|
||||
#XXXjdm need to properly support eStringify
|
||||
set += ("if RUST_JSID_IS_STRING(id) != 0 {\n" +
|
||||
" let nameVal: JSVal = RUST_STRING_TO_JSVAL(RUST_JSID_TO_STRING(id));\n" +
|
||||
" let strval = jsval_to_str(cx, nameVal);\n" +
|
||||
" //FakeDependentString name;\n" +
|
||||
" //if (!ConvertJSValueToString(cx, nameVal, &nameVal,\n" +
|
||||
" // eStringify, eStringify, name)) {\n" +
|
||||
" if strval.is_err() {\n" +
|
||||
" return 0;\n" +
|
||||
" }\n" +
|
||||
" let name = Some(strval.unwrap());\n" +
|
||||
"\n" +
|
||||
" let name = Some(jsid_to_str(cx, id));\n" +
|
||||
" let this: *%s = UnwrapProxy(proxy);\n" +
|
||||
CGIndenter(CGProxyNamedSetter(self.descriptor)).define() + "\n" +
|
||||
"}\n") % (self.descriptor.concreteType)
|
||||
elif self.descriptor.operations['NamedGetter']:
|
||||
set += ("if RUST_JSID_IS_STRING(id) {\n" +
|
||||
" let nameVal: JSVal = RUST_STRING_TO_JSVAL(RUST_JSID_TO_STRING(id));\n" +
|
||||
" let strval = jsval_to_str(cx, nameVal);\n" +
|
||||
" //FakeDependentString name;\n"
|
||||
" //if (!ConvertJSValueToString(cx, nameVal, &nameVal,\n" +
|
||||
" // eStringify, eStringify, name)) {\n" +
|
||||
" let strval = jsval_to_str(cx, nameVal);\n" +
|
||||
" if strval.is_err() {\n" +
|
||||
" return 0;\n" +
|
||||
" }\n" +
|
||||
" let name = Some(strval.unwrap());\n" +
|
||||
" let name = Some(jsid_to_str(cx, id));\n" +
|
||||
" let this: %%s = UnwrapProxy(proxy);\n" +
|
||||
CGIndenter(CGProxyNamedGetter(self.descriptor)).define() +
|
||||
" if (found) {\n"
|
||||
|
@ -4360,18 +4322,8 @@ class CGDOMJSProxyHandler_hasOwn(CGAbstractExternMethod):
|
|||
|
||||
namedGetter = self.descriptor.operations['NamedGetter']
|
||||
if namedGetter:
|
||||
#XXXjdm support eStringify
|
||||
named = ("if RUST_JSID_IS_STRING(id) != 0 && !HasPropertyOnPrototype(cx, proxy, id) {\n" +
|
||||
" let nameVal: JSVal = RUST_STRING_TO_JSVAL(RUST_JSID_TO_STRING(id));\n" +
|
||||
" let strval = jsval_to_str(cx, nameVal);\n" +
|
||||
" //FakeDependentString name;\n"
|
||||
" //if (!ConvertJSValueToString(cx, nameVal, &nameVal,\n" +
|
||||
" // eStringify, eStringify, name)) {\n" +
|
||||
" if strval.is_err() {\n" +
|
||||
" return 0;\n" +
|
||||
" }\n" +
|
||||
" let name = Some(strval.unwrap());\n" +
|
||||
"\n" +
|
||||
" let name = Some(jsid_to_str(cx, id));\n" +
|
||||
" let this: *%s = UnwrapProxy(proxy);\n" +
|
||||
CGIndenter(CGProxyNamedGetter(self.descriptor)).define() + "\n" +
|
||||
" *bp = found as JSBool;\n"
|
||||
|
@ -4439,13 +4391,7 @@ if expando.is_not_null() {
|
|||
namedGetter = self.descriptor.operations['NamedGetter']
|
||||
if namedGetter and False: #XXXjdm unfinished
|
||||
getNamed = ("if (JSID_IS_STRING(id)) {\n" +
|
||||
" JS::Value nameVal = STRING_TO_JSVAL(JSID_TO_STRING(id));\n" +
|
||||
" FakeDependentString name;\n"
|
||||
" if (!ConvertJSValueToString(cx, nameVal, &nameVal,\n" +
|
||||
" eStringify, eStringify, name)) {\n" +
|
||||
" return false;\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
" let name = Some(jsid_to_str(cx, id));\n" +
|
||||
" let this = UnwrapProxy(proxy);\n" +
|
||||
CGIndenter(CGProxyNamedGetter(self.descriptor, templateValues)).define() +
|
||||
"}\n") % (self.descriptor.concreteType)
|
||||
|
@ -5736,7 +5682,7 @@ class CGCallbackInterface(CGCallback):
|
|||
|
||||
class FakeMember():
|
||||
def __init__(self):
|
||||
self.treatUndefinedAs = self.treatNullAs = "Default"
|
||||
self.treatNullAs = "Default"
|
||||
def isStatic(self):
|
||||
return False
|
||||
def isAttr(self):
|
||||
|
|
|
@ -29,6 +29,7 @@ use js::jsapi::{JS_ValueToString, JS_GetReservedSlot, JS_SetReservedSlot};
|
|||
use js::jsapi::{JSContext, JSObject, JSBool, jsid, JSClass, JSNative, JSTracer};
|
||||
use js::jsapi::{JSFunctionSpec, JSPropertySpec, JSVal, JSPropertyDescriptor};
|
||||
use js::jsapi::{JSPropertyOp, JSStrictPropertyOp, JS_NewGlobalObject, JS_InitStandardClasses};
|
||||
use js::jsapi::{JSString};
|
||||
use js::jsfriendapi::bindgen::JS_NewObjectWithUniqueType;
|
||||
use js::{JSPROP_ENUMERATE, JSVAL_NULL, JSCLASS_IS_GLOBAL, JSCLASS_IS_DOMJSCLASS};
|
||||
use js::{JSPROP_PERMANENT, JSID_VOID, JSPROP_NATIVE_ACCESSORS, JSPROP_GETTER};
|
||||
|
@ -39,6 +40,32 @@ use js;
|
|||
static TOSTRING_CLASS_RESERVED_SLOT: libc::size_t = 0;
|
||||
static TOSTRING_NAME_RESERVED_SLOT: libc::size_t = 1;
|
||||
|
||||
mod jsval {
|
||||
use js::glue::{RUST_JSVAL_IS_NULL, RUST_JSVAL_IS_VOID};
|
||||
use js::glue::{RUST_JSVAL_IS_STRING, RUST_JSVAL_TO_STRING};
|
||||
use js::jsapi::{JSVal, JSString};
|
||||
|
||||
#[fixed_stack_segment]
|
||||
pub fn is_null(v: JSVal) -> bool {
|
||||
unsafe { RUST_JSVAL_IS_NULL(v) == 1 }
|
||||
}
|
||||
|
||||
#[fixed_stack_segment]
|
||||
pub fn is_undefined(v: JSVal) -> bool {
|
||||
unsafe { RUST_JSVAL_IS_VOID(v) == 1 }
|
||||
}
|
||||
|
||||
#[fixed_stack_segment]
|
||||
pub fn is_string(v: JSVal) -> bool {
|
||||
unsafe { RUST_JSVAL_IS_STRING(v) == 1 }
|
||||
}
|
||||
|
||||
#[fixed_stack_segment]
|
||||
pub unsafe fn to_string(v: JSVal) -> *JSString {
|
||||
RUST_JSVAL_TO_STRING(v)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GlobalStaticData {
|
||||
proxy_handlers: HashMap<uint, *libc::c_void>,
|
||||
attribute_ids: HashMap<uint, ~[jsid]>,
|
||||
|
@ -69,8 +96,6 @@ extern fn InterfaceObjectToString(cx: *JSContext, _argc: c_uint, vp: *mut JSVal)
|
|||
let v = GetFunctionNativeReserved(callee, TOSTRING_CLASS_RESERVED_SLOT);
|
||||
let clasp: *JSClass = cast::transmute(RUST_JSVAL_TO_PRIVATE(*v));
|
||||
|
||||
let v = GetFunctionNativeReserved(callee, TOSTRING_NAME_RESERVED_SLOT);
|
||||
|
||||
if GetObjectJSClass(obj) != clasp {
|
||||
/*let jsname: *JSString = RUST_JSVAL_TO_STRING(*v);
|
||||
let length = 0;
|
||||
|
@ -82,7 +107,9 @@ extern fn InterfaceObjectToString(cx: *JSContext, _argc: c_uint, vp: *mut JSVal)
|
|||
return 0;
|
||||
}
|
||||
|
||||
let name = jsval_to_str(cx, *v).unwrap();
|
||||
let v = *GetFunctionNativeReserved(callee, TOSTRING_NAME_RESERVED_SLOT);
|
||||
assert!(jsval::is_string(v));
|
||||
let name = jsstring_to_str(cx, jsval::to_string(v));
|
||||
let retval = Some(~"function " + name + "() {\n [native code]\n}");
|
||||
*vp = domstring_to_jsval(cx, &retval);
|
||||
return 1;
|
||||
|
@ -191,24 +218,56 @@ pub unsafe fn squirrel_away<T>(x: @mut T) -> *Box<T> {
|
|||
y
|
||||
}
|
||||
|
||||
//XXX very incomplete
|
||||
#[fixed_stack_segment]
|
||||
pub fn jsval_to_str(cx: *JSContext, v: JSVal) -> Result<~str, ()> {
|
||||
pub fn jsstring_to_str(cx: *JSContext, s: *JSString) -> ~str {
|
||||
unsafe {
|
||||
let jsstr;
|
||||
if RUST_JSVAL_IS_STRING(v) == 1 {
|
||||
jsstr = RUST_JSVAL_TO_STRING(v)
|
||||
} else {
|
||||
jsstr = JS_ValueToString(cx, v);
|
||||
if jsstr.is_null() {
|
||||
return Err(());
|
||||
}
|
||||
}
|
||||
|
||||
let length = 0;
|
||||
let chars = JS_GetStringCharsAndLength(cx, jsstr, &length);
|
||||
let chars = JS_GetStringCharsAndLength(cx, s, &length);
|
||||
do vec::raw::buf_as_slice(chars, length as uint) |char_vec| {
|
||||
Ok(str::from_utf16(char_vec))
|
||||
str::from_utf16(char_vec)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[fixed_stack_segment]
|
||||
pub fn jsid_to_str(cx: *JSContext, id: jsid) -> ~str {
|
||||
unsafe {
|
||||
assert!(RUST_JSID_IS_STRING(id) != 0);
|
||||
jsstring_to_str(cx, RUST_JSID_TO_STRING(id))
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(Eq)]
|
||||
pub enum StringificationBehavior {
|
||||
Default,
|
||||
Empty,
|
||||
}
|
||||
|
||||
#[fixed_stack_segment]
|
||||
pub fn jsval_to_str(cx: *JSContext, v: JSVal,
|
||||
nullBehavior: StringificationBehavior) -> Result<~str, ()> {
|
||||
if jsval::is_null(v) && nullBehavior == Empty {
|
||||
Ok(~"")
|
||||
} else {
|
||||
let jsstr = unsafe { JS_ValueToString(cx, v) };
|
||||
if jsstr.is_null() {
|
||||
Err(())
|
||||
} else {
|
||||
Ok(jsstring_to_str(cx, jsstr))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[fixed_stack_segment]
|
||||
pub fn jsval_to_domstring(cx: *JSContext, v: JSVal) -> Result<DOMString, ()> {
|
||||
if jsval::is_null(v) || jsval::is_undefined(v) {
|
||||
Ok(None)
|
||||
} else {
|
||||
let jsstr = unsafe { JS_ValueToString(cx, v) };
|
||||
if jsstr.is_null() {
|
||||
Err(())
|
||||
} else {
|
||||
Ok(Some(jsstring_to_str(cx, jsstr)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue