Skip to content

Commit

Permalink
Support default toJSON in WebIDL
Browse files Browse the repository at this point in the history
  • Loading branch information
saschanaz committed Jul 24, 2019
1 parent 9a7e266 commit 16b4e34
Show file tree
Hide file tree
Showing 9 changed files with 106 additions and 155 deletions.
96 changes: 94 additions & 2 deletions components/script/dom/bindings/codegen/CodegenRust.py
Expand Up @@ -2881,6 +2881,49 @@ def __str__(self):
return define


class CGCollectJSONAttributesMethod(CGAbstractMethod):
"""
Generate the CollectJSONAttributes method for an interface descriptor
"""
def __init__(self, descriptor, toJSONMethod):
args = [Argument('*mut JSContext', 'cx'),
Argument('HandleObject', 'obj'),
Argument('*const %s' % descriptor.concreteType, 'this'),
Argument('&RootedGuard<*mut JSObject>', 'result')]
CGAbstractMethod.__init__(self, descriptor, 'CollectJSONAttributes',
'bool', args, pub=True, unsafe=True)
self.toJSONMethod = toJSONMethod

def definition_body(self):
ret = ''
interface = self.descriptor.interface
for m in interface.members:
if m.isAttr() and not m.isStatic() and m.type.isJSONType():
name = m.identifier.name
getAndDefine = fill(
"""
rooted!(in(cx) let mut temp = UndefinedValue());
if !get_${name}(cx, obj, this, JSJitGetterCallArgs { _base: temp.handle_mut().into() }) {
return false;
}
if !JS_DefineProperty(cx, result.handle().into(),
${nameAsArray} as *const u8 as *const libc::c_char,
temp.handle(), JSPROP_ENUMERATE as u32) {
return false;
}
""",
name=name, nameAsArray=str_to_const_array(name))
ret += fill(
"""
{ // scope for "temp"
$*{getAndDefine}
}
""",
getAndDefine=getAndDefine)
ret += 'return true;\n'
return CGGeneric(ret)


class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
"""
Generate the CreateInterfaceObjects method for an interface descriptor.
Expand Down Expand Up @@ -3616,6 +3659,42 @@ def makeNativeName(descriptor, method):
return MakeNativeName(nativeName)


class CGDefaultToJSONMethod(CGSpecializedMethod):
def __init__(self, descriptor, method):
assert method.isDefaultToJSON()
CGSpecializedMethod.__init__(self, descriptor, method)

def definition_body(self):
ret = dedent("""
rooted!(in(cx) let result = JS_NewPlainObject(cx));
if result.is_null() {
return false;
}
""")

jsonDescriptors = [self.descriptor]
interface = self.descriptor.interface.parent
while interface:
descriptor = self.descriptor.getDescriptor(interface.identifier.name)
if descriptor.hasDefaultToJSON:
jsonDescriptors.append(descriptor)
interface = interface.parent

form = """
if !${parentclass}CollectJSONAttributes(cx, _obj, this, &result) {
return false;
}
"""

# Iterate the array in reverse: oldest ancestor first
for descriptor in jsonDescriptors[:0:-1]:
ret += fill(form, parentclass=toBindingNamespace(descriptor.name) + "::")
ret += fill(form, parentclass="")
ret += ('(*args).rval().set(ObjectValue(*result));\n'
'return true;\n')
return CGGeneric(ret)


class CGStaticMethod(CGAbstractStaticBindingMethod):
"""
A class for generating the Rust code for an IDL static method.
Expand Down Expand Up @@ -5653,7 +5732,8 @@ def members():
for m in descriptor.interface.members:
if (m.isMethod() and not m.isStatic() and
not m.isMaplikeOrSetlikeOrIterableMethod() and
(not m.isIdentifierLess() or m.isStringifier())):
(not m.isIdentifierLess() or m.isStringifier()) and
not m.isDefaultToJSON()):
name = CGSpecializedMethod.makeNativeName(descriptor, m)
infallible = 'infallible' in descriptor.getExtendedAttributes(m)
for idx, (rettype, arguments) in enumerate(m.signatures()):
Expand Down Expand Up @@ -5844,7 +5924,9 @@ def generate_imports(config, cgthings, descriptors, callbacks=None, dictionaries
'js::jsapi::JS_HasProperty',
'js::jsapi::JS_HasPropertyById',
'js::rust::wrappers::JS_InitializePropertiesFromCompatibleNativeObject',
'js::jsapi::JS_NewPlainObject',
'js::jsapi::JS_NewObject',
'js::rust::RootedGuard',
'js::rust::wrappers::JS_NewObjectWithGivenProto',
'js::rust::wrappers::JS_NewObjectWithoutMetadata',
'js::rust::wrappers::ObjectIsDate',
Expand Down Expand Up @@ -6041,14 +6123,17 @@ def reexportedName(name):

cgThings = []

defaultToJSONMethod = None
unscopableNames = []
for m in descriptor.interface.members:
if (m.isMethod() and
(not m.isIdentifierLess() or m == descriptor.operations["Stringifier"])):
if m.getExtendedAttribute("Unscopable"):
assert not m.isStatic()
unscopableNames.append(m.identifier.name)
if m.isStatic():
if m.isDefaultToJSON():
defaultToJSONMethod = m
elif m.isStatic():
assert descriptor.interface.hasInterfaceObject()
cgThings.append(CGStaticMethod(descriptor, m))
elif not descriptor.interface.isCallback():
Expand Down Expand Up @@ -6082,6 +6167,10 @@ def reexportedName(name):
if (not m.isStatic() and not descriptor.interface.isCallback()):
cgThings.append(CGMemberJITInfo(descriptor, m))

if defaultToJSONMethod:
cgThings.append(CGDefaultToJSONMethod(descriptor, defaultToJSONMethod))
cgThings.append(CGMemberJITInfo(descriptor, defaultToJSONMethod))

if descriptor.concrete:
cgThings.append(CGClassFinalizeHook(descriptor))
cgThings.append(CGClassTraceHook(descriptor))
Expand All @@ -6099,6 +6188,9 @@ def reexportedName(name):

properties = PropertyArrays(descriptor)

if defaultToJSONMethod:
cgThings.append(CGCollectJSONAttributesMethod(descriptor, defaultToJSONMethod))

if descriptor.concrete:
if descriptor.proxy:
# cgThings.append(CGProxyIsProxy(descriptor))
Expand Down
4 changes: 4 additions & 0 deletions components/script/dom/bindings/codegen/Configuration.py
Expand Up @@ -250,6 +250,8 @@ def __init__(self, config, interface, desc):
'Stringifier': None,
}

self.hasDefaultToJSON = False

def addOperation(operation, m):
if not self.operations[operation]:
self.operations[operation] = m
Expand All @@ -259,6 +261,8 @@ def addOperation(operation, m):
for m in self.interface.members:
if m.isMethod() and m.isStringifier():
addOperation('Stringifier', m)
if m.isMethod() and m.isDefaultToJSON():
self.hasDefaultToJSON = True

if self.concrete:
iface = self.interface
Expand Down
16 changes: 0 additions & 16 deletions components/script/dom/rtcsessiondescription.rs
Expand Up @@ -15,10 +15,6 @@ use crate::dom::bindings::str::DOMString;
use crate::dom::globalscope::GlobalScope;
use crate::dom::window::Window;
use dom_struct::dom_struct;
use js::conversions::ToJSValConvertible;
use js::jsapi::{JSContext, JSObject};
use js::jsval::UndefinedValue;
use std::ptr::NonNull;

#[dom_struct]
pub struct RTCSessionDescription {
Expand Down Expand Up @@ -70,16 +66,4 @@ impl RTCSessionDescriptionMethods for RTCSessionDescription {
fn Sdp(&self) -> DOMString {
self.sdp.clone()
}

#[allow(unsafe_code)]
/// https://w3c.github.io/webrtc-pc/#dom-rtcsessiondescription-tojson
unsafe fn ToJSON(&self, cx: *mut JSContext) -> NonNull<JSObject> {
let init = RTCSessionDescriptionInit {
type_: self.ty,
sdp: self.sdp.clone(),
};
rooted!(in(cx) let mut jsval = UndefinedValue());
init.to_jsval(cx, jsval.handle_mut());
NonNull::new(jsval.to_object()).unwrap()
}
}
5 changes: 2 additions & 3 deletions components/script/dom/webidls/DOMMatrixReadOnly.webidl
Expand Up @@ -81,7 +81,6 @@ interface DOMMatrixReadOnly {
DOMPoint transformPoint(optional DOMPointInit point = {});
Float32Array toFloat32Array();
Float64Array toFloat64Array();
// stringifier;
// serializer = { attribute };

// [Exposed=Window] stringifier;
[Default] object toJSON();
};
2 changes: 2 additions & 0 deletions components/script/dom/webidls/DOMPointReadOnly.webidl
Expand Up @@ -20,4 +20,6 @@ interface DOMPointReadOnly {
readonly attribute unrestricted double y;
readonly attribute unrestricted double z;
readonly attribute unrestricted double w;

[Default] object toJSON();
};
2 changes: 2 additions & 0 deletions components/script/dom/webidls/DOMQuad.webidl
Expand Up @@ -22,6 +22,8 @@ interface DOMQuad {
[SameObject] readonly attribute DOMPoint p3;
[SameObject] readonly attribute DOMPoint p4;
[NewObject] DOMRect getBounds();

[Default] object toJSON();
};

dictionary DOMQuadInit {
Expand Down
2 changes: 2 additions & 0 deletions components/script/dom/webidls/DOMRectReadOnly.webidl
Expand Up @@ -17,6 +17,8 @@ interface DOMRectReadOnly {
readonly attribute unrestricted double right;
readonly attribute unrestricted double bottom;
readonly attribute unrestricted double left;

[Default] object toJSON();
};

// https://drafts.fxtf.org/geometry/#dictdef-domrectinit
Expand Down
67 changes: 0 additions & 67 deletions tests/wpt/metadata/css/geometry/interfaces.html.ini
Expand Up @@ -282,36 +282,6 @@
[DOMMatrix interface: calling setMatrixValue(DOMString) on DOMMatrix.fromMatrix({is2D: false}) with too few arguments must throw TypeError]
expected: FAIL
[DOMPointReadOnly interface: operation toJSON()]
expected: FAIL
[DOMPointReadOnly interface: new DOMPointReadOnly() must inherit property "toJSON()" with the proper type]
expected: FAIL
[Test default toJSON operation of DOMPointReadOnly]
expected: FAIL
[DOMPointReadOnly interface: new DOMPoint() must inherit property "toJSON()" with the proper type]
expected: FAIL
[Test default toJSON operation of DOMPoint]
expected: FAIL
[DOMRectReadOnly interface: operation toJSON()]
expected: FAIL
[DOMRectReadOnly interface: new DOMRectReadOnly() must inherit property "toJSON()" with the proper type]
expected: FAIL
[Test default toJSON operation of DOMRectReadOnly]
expected: FAIL
[DOMRectReadOnly interface: new DOMRect() must inherit property "toJSON()" with the proper type]
expected: FAIL
[Test default toJSON operation of DOMRect]
expected: FAIL
[DOMRectList interface: existence and properties of interface object]
expected: FAIL
Expand Down Expand Up @@ -339,42 +309,5 @@
[DOMRectList must be primary interface of [object DOMRect\]]
expected: FAIL
[DOMQuad interface: operation toJSON()]
expected: FAIL
[DOMQuad interface: new DOMQuad() must inherit property "toJSON()" with the proper type]
expected: FAIL
[Test default toJSON operation of DOMQuad]
expected: FAIL
[DOMMatrixReadOnly interface: operation toJSON()]
expected: FAIL
[DOMMatrixReadOnly interface: new DOMMatrixReadOnly() must inherit property "toJSON()" with the proper type]
expected: FAIL
[Test default toJSON operation of DOMMatrixReadOnly]
expected: FAIL
[Geometry APIs interface IDL tests]
expected: FAIL
[DOMPointReadOnly interface: default toJSON operation on new DOMPoint()]
expected: FAIL
[DOMPointReadOnly interface: default toJSON operation on new DOMPointReadOnly()]
expected: FAIL
[DOMRectReadOnly interface: default toJSON operation on new DOMRect()]
expected: FAIL
[DOMRectReadOnly interface: default toJSON operation on new DOMRectReadOnly()]
expected: FAIL
[DOMQuad interface: default toJSON operation on new DOMQuad()]
expected: FAIL
[DOMMatrixReadOnly interface: default toJSON operation on new DOMMatrixReadOnly()]
expected: FAIL
67 changes: 0 additions & 67 deletions tests/wpt/metadata/css/geometry/interfaces.worker.js.ini
Expand Up @@ -29,75 +29,8 @@
[DOMRectReadOnly interface: calling fromRect(DOMRectInit) on new DOMRect() with too few arguments must throw TypeError]
expected: FAIL

[DOMPointReadOnly interface: operation toJSON()]
expected: FAIL

[DOMPointReadOnly interface: new DOMPointReadOnly() must inherit property "toJSON()" with the proper type]
expected: FAIL

[Test default toJSON operation of DOMPointReadOnly]
expected: FAIL

[DOMPointReadOnly interface: new DOMPoint() must inherit property "toJSON()" with the proper type]
expected: FAIL

[Test default toJSON operation of DOMPoint]
expected: FAIL

[DOMRectReadOnly interface: operation toJSON()]
expected: FAIL

[DOMRectReadOnly interface: new DOMRectReadOnly() must inherit property "toJSON()" with the proper type]
expected: FAIL

[Test default toJSON operation of DOMRectReadOnly]
expected: FAIL

[DOMRectReadOnly interface: new DOMRect() must inherit property "toJSON()" with the proper type]
expected: FAIL

[Test default toJSON operation of DOMRect]
expected: FAIL

[DOMQuad interface: operation toJSON()]
expected: FAIL

[DOMQuad interface: new DOMQuad() must inherit property "toJSON()" with the proper type]
expected: FAIL

[Test default toJSON operation of DOMQuad]
expected: FAIL

[DOMMatrixReadOnly interface: operation toJSON()]
expected: FAIL

[DOMMatrixReadOnly interface: new DOMMatrixReadOnly() must inherit property "toJSON()" with the proper type]
expected: FAIL

[Test default toJSON operation of DOMMatrixReadOnly]
expected: FAIL

[Untitled]
expected: FAIL

[interfaces]
expected: FAIL

[DOMPointReadOnly interface: default toJSON operation on new DOMPoint()]
expected: FAIL

[DOMPointReadOnly interface: default toJSON operation on new DOMPointReadOnly()]
expected: FAIL

[DOMRectReadOnly interface: default toJSON operation on new DOMRect()]
expected: FAIL

[DOMRectReadOnly interface: default toJSON operation on new DOMRectReadOnly()]
expected: FAIL

[DOMQuad interface: default toJSON operation on new DOMQuad()]
expected: FAIL

[DOMMatrixReadOnly interface: default toJSON operation on new DOMMatrixReadOnly()]
expected: FAIL

0 comments on commit 16b4e34

Please sign in to comment.