diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2019-08-20 17:27:14 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-08-20 17:27:14 -0400 |
commit | 4275420a562cd7c936010a791138554ea2a33fe9 (patch) | |
tree | 6a59fa8d40f4131f142f5bf4f16104b81d60f4cd | |
parent | 17f423723c0206c934f104eb3352f39a9533aa41 (diff) | |
parent | bf70decdd308f24bfe58cebb8f529fbc9cd22001 (diff) | |
download | servo-4275420a562cd7c936010a791138554ea2a33fe9.tar.gz servo-4275420a562cd7c936010a791138554ea2a33fe9.zip |
Auto merge of #23844 - saschanaz:tojson, r=Manishearth
Support default toJSON in WebIDL
<!-- Please describe your changes on the following line: -->
Ported related lines from gecko.
---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: -->
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] These changes fix #22781
<!-- Either: -->
- [x] There are tests for these changes
<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/23844)
<!-- Reviewable:end -->
9 files changed, 99 insertions, 158 deletions
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index 4bea65388b6..93856508e6e 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -2881,6 +2881,42 @@ class PropertyArrays(): return define +class CGCollectJSONAttributesMethod(CGAbstractMethod): + """ + Generate the CollectJSONAttributes method for an interface descriptor + """ + def __init__(self, descriptor, toJSONMethod): + args = [Argument('SafeJSContext', '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 + ret += 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 += 'return true;\n' + return CGGeneric(ret) + + class CGCreateInterfaceObjectsMethod(CGAbstractMethod): """ Generate the CreateInterfaceObjects method for an interface descriptor. @@ -3619,6 +3655,42 @@ class CGSpecializedMethod(CGAbstractExternMethod): 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. @@ -5665,7 +5737,8 @@ class CGInterfaceTrait(CGThing): 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()): @@ -5856,7 +5929,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', @@ -6055,6 +6130,7 @@ class CGDescriptor(CGThing): cgThings = [] + defaultToJSONMethod = None unscopableNames = [] for m in descriptor.interface.members: if (m.isMethod() and @@ -6062,7 +6138,9 @@ class CGDescriptor(CGThing): 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(): @@ -6096,6 +6174,10 @@ class CGDescriptor(CGThing): 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)) @@ -6113,6 +6195,9 @@ class CGDescriptor(CGThing): properties = PropertyArrays(descriptor) + if defaultToJSONMethod: + cgThings.append(CGCollectJSONAttributesMethod(descriptor, defaultToJSONMethod)) + if descriptor.concrete: if descriptor.proxy: # cgThings.append(CGProxyIsProxy(descriptor)) diff --git a/components/script/dom/bindings/codegen/Configuration.py b/components/script/dom/bindings/codegen/Configuration.py index 81f61a648f1..bde6e71bcfb 100644 --- a/components/script/dom/bindings/codegen/Configuration.py +++ b/components/script/dom/bindings/codegen/Configuration.py @@ -250,6 +250,8 @@ class Descriptor(DescriptorProvider): 'Stringifier': None, } + self.hasDefaultToJSON = False + def addOperation(operation, m): if not self.operations[operation]: self.operations[operation] = m @@ -259,6 +261,8 @@ class Descriptor(DescriptorProvider): 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 diff --git a/components/script/dom/rtcsessiondescription.rs b/components/script/dom/rtcsessiondescription.rs index 9aa46f56060..0ef79a321c6 100644 --- a/components/script/dom/rtcsessiondescription.rs +++ b/components/script/dom/rtcsessiondescription.rs @@ -14,12 +14,7 @@ use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::str::DOMString; use crate::dom::globalscope::GlobalScope; use crate::dom::window::Window; -use crate::script_runtime::JSContext; use dom_struct::dom_struct; -use js::conversions::ToJSValConvertible; -use js::jsapi::JSObject; -use js::jsval::UndefinedValue; -use std::ptr::NonNull; #[dom_struct] pub struct RTCSessionDescription { @@ -71,18 +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 - fn ToJSON(&self, cx: JSContext) -> NonNull<JSObject> { - let init = RTCSessionDescriptionInit { - type_: self.ty, - sdp: self.sdp.clone(), - }; - unsafe { - rooted!(in(*cx) let mut jsval = UndefinedValue()); - init.to_jsval(*cx, jsval.handle_mut()); - NonNull::new(jsval.to_object()).unwrap() - } - } } diff --git a/components/script/dom/webidls/DOMMatrixReadOnly.webidl b/components/script/dom/webidls/DOMMatrixReadOnly.webidl index ea5d8caf8e5..317c2860707 100644 --- a/components/script/dom/webidls/DOMMatrixReadOnly.webidl +++ b/components/script/dom/webidls/DOMMatrixReadOnly.webidl @@ -81,7 +81,6 @@ interface DOMMatrixReadOnly { DOMPoint transformPoint(optional DOMPointInit point = {}); Float32Array toFloat32Array(); Float64Array toFloat64Array(); -// stringifier; -// serializer = { attribute }; - +// [Exposed=Window] stringifier; + [Default] object toJSON(); }; diff --git a/components/script/dom/webidls/DOMPointReadOnly.webidl b/components/script/dom/webidls/DOMPointReadOnly.webidl index 23643179333..071252c7690 100644 --- a/components/script/dom/webidls/DOMPointReadOnly.webidl +++ b/components/script/dom/webidls/DOMPointReadOnly.webidl @@ -20,4 +20,6 @@ interface DOMPointReadOnly { readonly attribute unrestricted double y; readonly attribute unrestricted double z; readonly attribute unrestricted double w; + + [Default] object toJSON(); }; diff --git a/components/script/dom/webidls/DOMQuad.webidl b/components/script/dom/webidls/DOMQuad.webidl index 8711dd44215..15f126cfea6 100644 --- a/components/script/dom/webidls/DOMQuad.webidl +++ b/components/script/dom/webidls/DOMQuad.webidl @@ -22,6 +22,8 @@ interface DOMQuad { [SameObject] readonly attribute DOMPoint p3; [SameObject] readonly attribute DOMPoint p4; [NewObject] DOMRect getBounds(); + + [Default] object toJSON(); }; dictionary DOMQuadInit { diff --git a/components/script/dom/webidls/DOMRectReadOnly.webidl b/components/script/dom/webidls/DOMRectReadOnly.webidl index 9464561bef4..58a8c87cd1c 100644 --- a/components/script/dom/webidls/DOMRectReadOnly.webidl +++ b/components/script/dom/webidls/DOMRectReadOnly.webidl @@ -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 diff --git a/tests/wpt/metadata/css/geometry/interfaces.html.ini b/tests/wpt/metadata/css/geometry/interfaces.html.ini index 67e7bfc4757..90a08304978 100644 --- a/tests/wpt/metadata/css/geometry/interfaces.html.ini +++ b/tests/wpt/metadata/css/geometry/interfaces.html.ini @@ -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 @@ -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 - diff --git a/tests/wpt/metadata/css/geometry/interfaces.worker.js.ini b/tests/wpt/metadata/css/geometry/interfaces.worker.js.ini index f21695bbfdc..5ca33a54aab 100644 --- a/tests/wpt/metadata/css/geometry/interfaces.worker.js.ini +++ b/tests/wpt/metadata/css/geometry/interfaces.worker.js.ini @@ -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 - |