mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Make (dictionary)::empty() safe
It currently works by constructing from null (which will throw a runtime error if there are non-defaultable members). This changes it so that we no longer need a JSContext to construct this, so it can be safely constructed. In the case of non-defaultable members, this method simply does not exist.
This commit is contained in:
parent
c90737e6c8
commit
cceaede96a
2 changed files with 50 additions and 10 deletions
|
@ -744,7 +744,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
if defaultValue:
|
||||
assert isinstance(defaultValue, IDLNullValue)
|
||||
dictionary, = dictionaries
|
||||
default = "%s::%s(%s::%s::empty(cx))" % (
|
||||
default = "%s::%s(%s::%s::empty())" % (
|
||||
union_native_type(type),
|
||||
dictionary.name,
|
||||
CGDictionary.makeModuleName(dictionary.inner),
|
||||
|
@ -1148,7 +1148,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
typeName = "%s::%s" % (CGDictionary.makeModuleName(type.inner),
|
||||
CGDictionary.makeDictionaryName(type.inner))
|
||||
declType = CGGeneric(typeName)
|
||||
empty = "%s::empty(cx)" % typeName
|
||||
empty = "%s::empty()" % typeName
|
||||
|
||||
if type_needs_tracing(type):
|
||||
declType = CGTemplatedType("RootedTraceableBox", declType)
|
||||
|
@ -6274,12 +6274,7 @@ class CGDictionary(CGThing):
|
|||
|
||||
return string.Template(
|
||||
"impl ${selfName} {\n"
|
||||
" pub unsafe fn empty(cx: *mut JSContext) -> ${actualType} {\n"
|
||||
" match ${selfName}::new(cx, HandleValue::null()) {\n"
|
||||
" Ok(ConversionResult::Success(v)) => v,\n"
|
||||
" _ => unreachable!(),\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"${empty}\n"
|
||||
" pub unsafe fn new(cx: *mut JSContext, val: HandleValue) \n"
|
||||
" -> Result<ConversionResult<${actualType}>, ()> {\n"
|
||||
" let object = if val.get().is_null_or_undefined() {\n"
|
||||
|
@ -6315,6 +6310,7 @@ class CGDictionary(CGThing):
|
|||
"}\n").substitute({
|
||||
"selfName": selfName,
|
||||
"actualType": actualType,
|
||||
"empty": CGIndenter(CGGeneric(self.makeEmpty()), indentLevel=4).define(),
|
||||
"initParent": CGIndenter(CGGeneric(initParent), indentLevel=12).define(),
|
||||
"initMembers": CGIndenter(memberInits, indentLevel=12).define(),
|
||||
"insertMembers": CGIndenter(memberInserts, indentLevel=8).define(),
|
||||
|
@ -6380,6 +6376,50 @@ class CGDictionary(CGThing):
|
|||
|
||||
return CGGeneric(conversion)
|
||||
|
||||
def makeEmpty(self):
|
||||
if self.hasRequiredFields(self.dictionary):
|
||||
return ""
|
||||
parentTemplate = "parent: %s::%s::empty(),\n"
|
||||
fieldTemplate = "%s: %s,\n"
|
||||
functionTemplate = (
|
||||
"pub fn empty() -> Self {\n"
|
||||
" Self {\n"
|
||||
"%s"
|
||||
" }\n"
|
||||
"}"
|
||||
)
|
||||
if self.membersNeedTracing():
|
||||
parentTemplate = "dictionary.parent = %s::%s::empty();\n"
|
||||
fieldTemplate = "dictionary.%s = %s;\n"
|
||||
functionTemplate = (
|
||||
"pub fn empty() -> RootedTraceableBox<Self> {\n"
|
||||
" let mut dictionary = RootedTraceableBox::new(Self::default());\n"
|
||||
"%s"
|
||||
" dictionary\n"
|
||||
"}"
|
||||
)
|
||||
s = ""
|
||||
if self.dictionary.parent:
|
||||
s += parentTemplate % (self.makeModuleName(self.dictionary.parent),
|
||||
self.makeClassName(self.dictionary.parent))
|
||||
for member, info in self.memberInfo:
|
||||
if not member.optional:
|
||||
return ""
|
||||
default = info.default
|
||||
if not default:
|
||||
default = "None"
|
||||
s += fieldTemplate % (self.makeMemberName(member.identifier.name), default)
|
||||
return functionTemplate % CGIndenter(CGGeneric(s), 12).define()
|
||||
|
||||
def hasRequiredFields(self, dictionary):
|
||||
if dictionary.parent:
|
||||
if self.hasRequiredFields(dictionary.parent):
|
||||
return True
|
||||
for member in dictionary.members:
|
||||
if not member.optional:
|
||||
return True
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def makeMemberName(name):
|
||||
# Can't use Rust keywords as member names.
|
||||
|
|
|
@ -115,7 +115,7 @@ fn dict_return(cx: *mut JSContext,
|
|||
mut result: MutableHandleObject,
|
||||
done: bool,
|
||||
value: HandleValue) -> Fallible<()> {
|
||||
let mut dict = unsafe { IterableKeyOrValueResult::empty(cx) };
|
||||
let mut dict = IterableKeyOrValueResult::empty();
|
||||
dict.done = done;
|
||||
dict.value.set(value.get());
|
||||
rooted!(in(cx) let mut dict_value = UndefinedValue());
|
||||
|
@ -130,7 +130,7 @@ fn key_and_value_return(cx: *mut JSContext,
|
|||
mut result: MutableHandleObject,
|
||||
key: HandleValue,
|
||||
value: HandleValue) -> Fallible<()> {
|
||||
let mut dict = unsafe { IterableKeyAndValueResult::empty(cx) };
|
||||
let mut dict = IterableKeyAndValueResult::empty();
|
||||
dict.done = false;
|
||||
dict.value = Some(vec![key, value]
|
||||
.into_iter()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue