diff options
Diffstat (limited to 'xpcom/idl-parser')
-rw-r--r-- | xpcom/idl-parser/xpidl/fixtures/xpctest.d.json | 1402 | ||||
-rw-r--r-- | xpcom/idl-parser/xpidl/header.py | 2 | ||||
-rwxr-xr-x | xpcom/idl-parser/xpidl/runtests.py | 41 | ||||
-rw-r--r-- | xpcom/idl-parser/xpidl/rust.py | 4 | ||||
-rw-r--r-- | xpcom/idl-parser/xpidl/typescript.py | 94 | ||||
-rwxr-xr-x | xpcom/idl-parser/xpidl/xpidl.py | 136 |
6 files changed, 1653 insertions, 26 deletions
diff --git a/xpcom/idl-parser/xpidl/fixtures/xpctest.d.json b/xpcom/idl-parser/xpidl/fixtures/xpctest.d.json new file mode 100644 index 0000000000..fb3cb7e6b7 --- /dev/null +++ b/xpcom/idl-parser/xpidl/fixtures/xpctest.d.json @@ -0,0 +1,1402 @@ +[ + { + "interfaces": [ + { + "base": "nsISupports", + "callable": false, + "consts": [], + "enums": [], + "id": "nsIXPCTestObjectReadOnly", + "members": [ + { + "name": "strReadOnly", + "readonly": true, + "type": "string" + }, + { + "name": "boolReadOnly", + "readonly": true, + "type": "boolean" + }, + { + "name": "shortReadOnly", + "readonly": true, + "type": "i16" + }, + { + "name": "longReadOnly", + "readonly": true, + "type": "i32" + }, + { + "name": "floatReadOnly", + "readonly": true, + "type": "float" + }, + { + "name": "charReadOnly", + "readonly": true, + "type": "string" + }, + { + "name": "timeReadOnly", + "readonly": true, + "type": "PRTime" + } + ] + }, + { + "base": "nsISupports", + "callable": false, + "consts": [], + "enums": [], + "id": "nsIXPCTestObjectReadWrite", + "members": [ + { + "name": "stringProperty", + "readonly": false, + "type": "string" + }, + { + "name": "booleanProperty", + "readonly": false, + "type": "boolean" + }, + { + "name": "shortProperty", + "readonly": false, + "type": "i16" + }, + { + "name": "longProperty", + "readonly": false, + "type": "i32" + }, + { + "name": "floatProperty", + "readonly": false, + "type": "float" + }, + { + "name": "charProperty", + "readonly": false, + "type": "string" + }, + { + "name": "timeProperty", + "readonly": false, + "type": "PRTime" + } + ] + } + ], + "path": "js/xpconnect/tests/idl/xpctest_attributes.idl", + "typedefs": [ + [ + "PRTime", + "i64" + ], + [ + "char16_t", + "u16" + ], + [ + "nsresult", + "u32" + ] + ] + }, + { + "interfaces": [ + { + "base": "nsISupports", + "callable": false, + "consts": [], + "enums": [], + "id": "nsIXPCTestBug809674", + "members": [ + { + "args": [ + { + "name": "x", + "optional": false, + "type": "u32" + }, + { + "name": "y", + "optional": false, + "type": "u32" + } + ], + "iid_is": null, + "name": "addArgs", + "type": "u32" + }, + { + "args": [ + { + "name": "x", + "optional": false, + "type": "u32" + }, + { + "name": "y", + "optional": false, + "type": "u32" + }, + { + "name": "subOut", + "optional": false, + "type": "OutParam<u32>" + }, + { + "name": "mulOut", + "optional": false, + "type": "OutParam<u32>" + } + ], + "iid_is": null, + "name": "addSubMulArgs", + "type": "u32" + }, + { + "args": [ + { + "name": "x", + "optional": false, + "type": "any" + }, + { + "name": "y", + "optional": false, + "type": "any" + } + ], + "iid_is": null, + "name": "addVals", + "type": "any" + }, + { + "args": [], + "iid_is": null, + "name": "methodNoArgs", + "type": "u32" + }, + { + "args": [], + "iid_is": null, + "name": "methodNoArgsNoRetVal", + "type": "void" + }, + { + "args": [ + { + "name": "x1", + "optional": false, + "type": "u32" + }, + { + "name": "x2", + "optional": false, + "type": "u32" + }, + { + "name": "x3", + "optional": false, + "type": "u32" + }, + { + "name": "x4", + "optional": false, + "type": "u32" + }, + { + "name": "x5", + "optional": false, + "type": "u32" + }, + { + "name": "x6", + "optional": false, + "type": "u32" + }, + { + "name": "x7", + "optional": false, + "type": "u32" + }, + { + "name": "x8", + "optional": false, + "type": "u32" + } + ], + "iid_is": null, + "name": "addMany", + "type": "u32" + }, + { + "name": "valProperty", + "readonly": false, + "type": "any" + }, + { + "name": "uintProperty", + "readonly": false, + "type": "u32" + }, + { + "args": [], + "iid_is": null, + "name": "methodWithOptionalArgc", + "type": "void" + } + ] + } + ], + "path": "js/xpconnect/tests/idl/xpctest_bug809674.idl", + "typedefs": [ + [ + "PRTime", + "i64" + ], + [ + "char16_t", + "u16" + ], + [ + "nsresult", + "u32" + ] + ] + }, + { + "interfaces": [ + { + "base": "nsISupports", + "callable": false, + "consts": [ + { + "name": "testConst", + "value": 1 + } + ], + "enums": [ + { + "id": "testFlagsExplicit", + "variants": [ + { + "name": "shouldBe1Explicit", + "value": 1 + }, + { + "name": "shouldBe2Explicit", + "value": 2 + }, + { + "name": "shouldBe4Explicit", + "value": 4 + }, + { + "name": "shouldBe8Explicit", + "value": 8 + }, + { + "name": "shouldBe12Explicit", + "value": 12 + } + ] + }, + { + "id": "testFlagsImplicit", + "variants": [ + { + "name": "shouldBe0Implicit", + "value": 0 + }, + { + "name": "shouldBe1Implicit", + "value": 1 + }, + { + "name": "shouldBe2Implicit", + "value": 2 + }, + { + "name": "shouldBe3Implicit", + "value": 3 + }, + { + "name": "shouldBe5Implicit", + "value": 5 + }, + { + "name": "shouldBe6Implicit", + "value": 6 + }, + { + "name": "shouldBe2AgainImplicit", + "value": 2 + }, + { + "name": "shouldBe3AgainImplicit", + "value": 3 + } + ] + } + ], + "id": "nsIXPCTestCEnums", + "members": [ + { + "args": [ + { + "name": "abc", + "optional": false, + "type": "nsIXPCTestCEnums.testFlagsExplicit" + } + ], + "iid_is": null, + "name": "testCEnumInput", + "type": "void" + }, + { + "args": [], + "iid_is": null, + "name": "testCEnumOutput", + "type": "nsIXPCTestCEnums.testFlagsExplicit" + } + ] + } + ], + "path": "js/xpconnect/tests/idl/xpctest_cenums.idl", + "typedefs": [ + [ + "PRTime", + "i64" + ], + [ + "char16_t", + "u16" + ], + [ + "nsresult", + "u32" + ] + ] + }, + { + "interfaces": [ + { + "base": "nsISupports", + "callable": false, + "consts": [], + "enums": [], + "id": "nsIXPCTestInterfaceA", + "members": [ + { + "name": "name", + "readonly": false, + "type": "string" + } + ] + }, + { + "base": "nsISupports", + "callable": false, + "consts": [], + "enums": [], + "id": "nsIXPCTestInterfaceB", + "members": [ + { + "name": "name", + "readonly": false, + "type": "string" + } + ] + }, + { + "base": "nsISupports", + "callable": false, + "consts": [], + "enums": [], + "id": "nsIXPCTestInterfaceC", + "members": [ + { + "name": "someInteger", + "readonly": false, + "type": "i32" + } + ] + } + ], + "path": "js/xpconnect/tests/idl/xpctest_interfaces.idl", + "typedefs": [ + [ + "PRTime", + "i64" + ], + [ + "char16_t", + "u16" + ], + [ + "nsresult", + "u32" + ] + ] + }, + { + "interfaces": [ + { + "base": "nsISupports", + "callable": false, + "consts": [], + "enums": [], + "id": "nsIXPCTestParams", + "members": [ + { + "args": [ + { + "name": "a", + "optional": false, + "type": "boolean" + }, + { + "name": "b", + "optional": false, + "type": "InOutParam<boolean>" + } + ], + "iid_is": null, + "name": "testBoolean", + "type": "boolean" + }, + { + "args": [ + { + "name": "a", + "optional": false, + "type": "u8" + }, + { + "name": "b", + "optional": false, + "type": "InOutParam<u8>" + } + ], + "iid_is": null, + "name": "testOctet", + "type": "u8" + }, + { + "args": [ + { + "name": "a", + "optional": false, + "type": "i16" + }, + { + "name": "b", + "optional": false, + "type": "InOutParam<i16>" + } + ], + "iid_is": null, + "name": "testShort", + "type": "i16" + }, + { + "args": [ + { + "name": "a", + "optional": false, + "type": "i32" + }, + { + "name": "b", + "optional": false, + "type": "InOutParam<i32>" + } + ], + "iid_is": null, + "name": "testLong", + "type": "i32" + }, + { + "args": [ + { + "name": "a", + "optional": false, + "type": "i64" + }, + { + "name": "b", + "optional": false, + "type": "InOutParam<i64>" + } + ], + "iid_is": null, + "name": "testLongLong", + "type": "i64" + }, + { + "args": [ + { + "name": "a", + "optional": false, + "type": "u16" + }, + { + "name": "b", + "optional": false, + "type": "InOutParam<u16>" + } + ], + "iid_is": null, + "name": "testUnsignedShort", + "type": "u16" + }, + { + "args": [ + { + "name": "a", + "optional": false, + "type": "u32" + }, + { + "name": "b", + "optional": false, + "type": "InOutParam<u32>" + } + ], + "iid_is": null, + "name": "testUnsignedLong", + "type": "u32" + }, + { + "args": [ + { + "name": "a", + "optional": false, + "type": "u64" + }, + { + "name": "b", + "optional": false, + "type": "InOutParam<u64>" + } + ], + "iid_is": null, + "name": "testUnsignedLongLong", + "type": "u64" + }, + { + "args": [ + { + "name": "a", + "optional": false, + "type": "float" + }, + { + "name": "b", + "optional": false, + "type": "InOutParam<float>" + } + ], + "iid_is": null, + "name": "testFloat", + "type": "float" + }, + { + "args": [ + { + "name": "a", + "optional": false, + "type": "double" + }, + { + "name": "b", + "optional": false, + "type": "InOutParam<float>" + } + ], + "iid_is": null, + "name": "testDouble", + "type": "double" + }, + { + "args": [ + { + "name": "a", + "optional": false, + "type": "string" + }, + { + "name": "b", + "optional": false, + "type": "InOutParam<string>" + } + ], + "iid_is": null, + "name": "testChar", + "type": "string" + }, + { + "args": [ + { + "name": "a", + "optional": false, + "type": "string" + }, + { + "name": "b", + "optional": false, + "type": "InOutParam<string>" + } + ], + "iid_is": null, + "name": "testString", + "type": "string" + }, + { + "args": [ + { + "name": "a", + "optional": false, + "type": "string" + }, + { + "name": "b", + "optional": false, + "type": "InOutParam<string>" + } + ], + "iid_is": null, + "name": "testWchar", + "type": "string" + }, + { + "args": [ + { + "name": "a", + "optional": false, + "type": "string" + }, + { + "name": "b", + "optional": false, + "type": "InOutParam<string>" + } + ], + "iid_is": null, + "name": "testWstring", + "type": "string" + }, + { + "args": [ + { + "name": "a", + "optional": false, + "type": "string" + }, + { + "name": "b", + "optional": false, + "type": "InOutParam<string>" + } + ], + "iid_is": null, + "name": "testAString", + "type": "string" + }, + { + "args": [ + { + "name": "a", + "optional": false, + "type": "string" + }, + { + "name": "b", + "optional": false, + "type": "InOutParam<string>" + } + ], + "iid_is": null, + "name": "testAUTF8String", + "type": "string" + }, + { + "args": [ + { + "name": "a", + "optional": false, + "type": "string" + }, + { + "name": "b", + "optional": false, + "type": "InOutParam<string>" + } + ], + "iid_is": null, + "name": "testACString", + "type": "string" + }, + { + "args": [ + { + "name": "a", + "optional": false, + "type": "any" + }, + { + "name": "b", + "optional": false, + "type": "InOutParam<any>" + } + ], + "iid_is": null, + "name": "testJsval", + "type": "any" + }, + { + "args": [ + { + "name": "a", + "optional": false, + "type": "i16[]" + }, + { + "name": "b", + "optional": false, + "type": "InOutParam<i16[]>" + } + ], + "iid_is": null, + "name": "testShortSequence", + "type": "i16[]" + }, + { + "args": [ + { + "name": "a", + "optional": false, + "type": "double[]" + }, + { + "name": "b", + "optional": false, + "type": "InOutParam<double[]>" + } + ], + "iid_is": null, + "name": "testDoubleSequence", + "type": "double[]" + }, + { + "args": [ + { + "name": "a", + "optional": false, + "type": "nsIXPCTestInterfaceA[]" + }, + { + "name": "b", + "optional": false, + "type": "InOutParam<nsIXPCTestInterfaceA[]>" + } + ], + "iid_is": null, + "name": "testInterfaceSequence", + "type": "nsIXPCTestInterfaceA[]" + }, + { + "args": [ + { + "name": "a", + "optional": false, + "type": "string[]" + }, + { + "name": "b", + "optional": false, + "type": "InOutParam<string[]>" + } + ], + "iid_is": null, + "name": "testAStringSequence", + "type": "string[]" + }, + { + "args": [ + { + "name": "a", + "optional": false, + "type": "string[]" + }, + { + "name": "b", + "optional": false, + "type": "InOutParam<string[]>" + } + ], + "iid_is": null, + "name": "testACStringSequence", + "type": "string[]" + }, + { + "args": [ + { + "name": "a", + "optional": false, + "type": "any[]" + }, + { + "name": "b", + "optional": false, + "type": "InOutParam<any[]>" + } + ], + "iid_is": null, + "name": "testJsvalSequence", + "type": "any[]" + }, + { + "args": [ + { + "name": "a", + "optional": false, + "type": "i16[][]" + }, + { + "name": "b", + "optional": false, + "type": "InOutParam<i16[][]>" + } + ], + "iid_is": null, + "name": "testSequenceSequence", + "type": "i16[][]" + }, + { + "args": [ + { + "name": "arr", + "optional": true, + "type": "u8[]" + } + ], + "iid_is": null, + "name": "testOptionalSequence", + "type": "u8[]" + }, + { + "args": [ + { + "name": "aLength", + "optional": false, + "type": "u32" + }, + { + "name": "a", + "optional": false, + "type": "i16[]" + }, + { + "name": "bLength", + "optional": false, + "type": "InOutParam<u32>" + }, + { + "name": "b", + "optional": false, + "type": "InOutParam<i16[]>" + }, + { + "name": "rvLength", + "optional": false, + "type": "OutParam<u32>" + } + ], + "iid_is": null, + "name": "testShortArray", + "type": "OutParam<i16[]>" + }, + { + "args": [ + { + "name": "aLength", + "optional": false, + "type": "u32" + }, + { + "name": "a", + "optional": false, + "type": "double[]" + }, + { + "name": "bLength", + "optional": false, + "type": "InOutParam<u32>" + }, + { + "name": "b", + "optional": false, + "type": "InOutParam<double[]>" + }, + { + "name": "rvLength", + "optional": false, + "type": "OutParam<u32>" + } + ], + "iid_is": null, + "name": "testDoubleArray", + "type": "OutParam<double[]>" + }, + { + "args": [ + { + "name": "aLength", + "optional": false, + "type": "u32" + }, + { + "name": "a", + "optional": false, + "type": "string[]" + }, + { + "name": "bLength", + "optional": false, + "type": "InOutParam<u32>" + }, + { + "name": "b", + "optional": false, + "type": "InOutParam<string[]>" + }, + { + "name": "rvLength", + "optional": false, + "type": "OutParam<u32>" + } + ], + "iid_is": null, + "name": "testStringArray", + "type": "OutParam<string[]>" + }, + { + "args": [ + { + "name": "aLength", + "optional": false, + "type": "u32" + }, + { + "name": "a", + "optional": false, + "type": "string[]" + }, + { + "name": "bLength", + "optional": false, + "type": "InOutParam<u32>" + }, + { + "name": "b", + "optional": false, + "type": "InOutParam<string[]>" + }, + { + "name": "rvLength", + "optional": false, + "type": "OutParam<u32>" + } + ], + "iid_is": null, + "name": "testWstringArray", + "type": "OutParam<string[]>" + }, + { + "args": [ + { + "name": "aLength", + "optional": false, + "type": "u32" + }, + { + "name": "a", + "optional": false, + "type": "nsIXPCTestInterfaceA[]" + }, + { + "name": "bLength", + "optional": false, + "type": "InOutParam<u32>" + }, + { + "name": "b", + "optional": false, + "type": "InOutParam<nsIXPCTestInterfaceA[]>" + }, + { + "name": "rvLength", + "optional": false, + "type": "OutParam<u32>" + } + ], + "iid_is": null, + "name": "testInterfaceArray", + "type": "OutParam<nsIXPCTestInterfaceA[]>" + }, + { + "args": [ + { + "name": "a", + "optional": false, + "type": "u8[]" + }, + { + "name": "aLength", + "optional": true, + "type": "u32" + } + ], + "iid_is": null, + "name": "testByteArrayOptionalLength", + "type": "u32" + }, + { + "args": [ + { + "name": "aLength", + "optional": false, + "type": "u32" + }, + { + "name": "a", + "optional": false, + "type": "string" + }, + { + "name": "bLength", + "optional": false, + "type": "InOutParam<u32>" + }, + { + "name": "b", + "optional": false, + "type": "InOutParam<string>" + }, + { + "name": "rvLength", + "optional": false, + "type": "OutParam<u32>" + } + ], + "iid_is": null, + "name": "testSizedString", + "type": "OutParam<string>" + }, + { + "args": [ + { + "name": "aLength", + "optional": false, + "type": "u32" + }, + { + "name": "a", + "optional": false, + "type": "string" + }, + { + "name": "bLength", + "optional": false, + "type": "InOutParam<u32>" + }, + { + "name": "b", + "optional": false, + "type": "InOutParam<string>" + }, + { + "name": "rvLength", + "optional": false, + "type": "OutParam<u32>" + } + ], + "iid_is": null, + "name": "testSizedWstring", + "type": "OutParam<string>" + }, + { + "args": [ + { + "name": "aLength", + "optional": false, + "type": "u32" + }, + { + "name": "a", + "optional": false, + "type": "any[]" + }, + { + "name": "bLength", + "optional": false, + "type": "InOutParam<u32>" + }, + { + "name": "b", + "optional": false, + "type": "InOutParam<any[]>" + }, + { + "name": "rvLength", + "optional": false, + "type": "OutParam<u32>" + } + ], + "iid_is": null, + "name": "testJsvalArray", + "type": "OutParam<any[]>" + }, + { + "args": [ + { + "name": "o", + "optional": false, + "type": "OutParam<string>" + } + ], + "iid_is": null, + "name": "testOutAString", + "type": "void" + }, + { + "args": [ + { + "name": "a", + "optional": false, + "type": "string[]" + }, + { + "name": "aLength", + "optional": true, + "type": "u32" + } + ], + "iid_is": null, + "name": "testStringArrayOptionalSize", + "type": "string" + }, + { + "args": [ + { + "name": "aJSObj", + "optional": false, + "type": "nsIXPCTestParams" + }, + { + "name": "aOut", + "optional": true, + "type": "OutParam<nsIURI>" + } + ], + "iid_is": null, + "name": "testOmittedOptionalOut", + "type": "void" + }, + { + "name": "testNaN", + "readonly": true, + "type": "double" + } + ] + } + ], + "path": "js/xpconnect/tests/idl/xpctest_params.idl", + "typedefs": [ + [ + "PRTime", + "i64" + ], + [ + "char16_t", + "u16" + ], + [ + "nsresult", + "u32" + ] + ] + }, + { + "interfaces": [ + { + "base": "nsISupports", + "callable": false, + "consts": [], + "enums": [], + "id": "nsIXPCTestReturnCodeParent", + "members": [ + { + "args": [ + { + "name": "childBehavior", + "optional": false, + "type": "i32" + } + ], + "iid_is": null, + "name": "callChild", + "type": "nsresult" + } + ] + }, + { + "base": "nsISupports", + "callable": false, + "consts": [ + { + "name": "CHILD_SHOULD_THROW", + "value": 0 + }, + { + "name": "CHILD_SHOULD_RETURN_SUCCESS", + "value": 1 + }, + { + "name": "CHILD_SHOULD_RETURN_RESULTCODE", + "value": 2 + }, + { + "name": "CHILD_SHOULD_NEST_RESULTCODES", + "value": 3 + } + ], + "enums": [], + "id": "nsIXPCTestReturnCodeChild", + "members": [ + { + "args": [ + { + "name": "behavior", + "optional": false, + "type": "i32" + } + ], + "iid_is": null, + "name": "doIt", + "type": "void" + } + ] + } + ], + "path": "js/xpconnect/tests/idl/xpctest_returncode.idl", + "typedefs": [ + [ + "PRTime", + "i64" + ], + [ + "char16_t", + "u16" + ], + [ + "nsresult", + "u32" + ] + ] + }, + { + "interfaces": [ + { + "base": "nsISupports", + "callable": true, + "consts": [], + "enums": [], + "id": "nsIXPCTestFunctionInterface", + "members": [ + { + "args": [ + { + "name": "arg", + "optional": false, + "type": "string" + } + ], + "iid_is": null, + "name": "echo", + "type": "string" + } + ] + }, + { + "base": "nsISupports", + "callable": false, + "consts": [], + "enums": [], + "id": "nsIXPCTestUtils", + "members": [ + { + "args": [ + { + "name": "f", + "optional": false, + "type": "nsIXPCTestFunctionInterface" + } + ], + "iid_is": null, + "name": "doubleWrapFunction", + "type": "nsIXPCTestFunctionInterface" + } + ] + }, + { + "base": "nsISupports", + "callable": false, + "consts": [], + "enums": [], + "id": "nsIXPCTestNoScriptMembers", + "members": [ + { + "name": "exposedProp", + "readonly": false, + "type": "i32" + }, + { + "args": [ + { + "name": "arg", + "optional": false, + "type": "i32" + } + ], + "iid_is": null, + "name": "exposedMethod", + "type": "void" + } + ] + } + ], + "path": "js/xpconnect/tests/idl/xpctest_utils.idl", + "typedefs": [ + [ + "PRTime", + "i64" + ], + [ + "char16_t", + "u16" + ], + [ + "nsresult", + "u32" + ] + ] + } +]
\ No newline at end of file diff --git a/xpcom/idl-parser/xpidl/header.py b/xpcom/idl-parser/xpidl/header.py index ed179b1bad..7f6c65dfc0 100644 --- a/xpcom/idl-parser/xpidl/header.py +++ b/xpcom/idl-parser/xpidl/header.py @@ -339,6 +339,8 @@ def print_header(idl, fd, filename, relpath): write_interface(p, fd) continue if p.kind == "typedef": + if p.substitute: + continue printComments(fd, p.doccomments, "") fd.write("typedef %s %s;\n\n" % (p.realtype.nativeType("in"), p.name)) diff --git a/xpcom/idl-parser/xpidl/runtests.py b/xpcom/idl-parser/xpidl/runtests.py index 2dd269dfd9..b889d40010 100755 --- a/xpcom/idl-parser/xpidl/runtests.py +++ b/xpcom/idl-parser/xpidl/runtests.py @@ -5,6 +5,8 @@ # # Unit tests for xpidl.py +import json +import os import sys # Hack: the first entry in sys.path is the directory containing the script. @@ -16,7 +18,7 @@ import unittest import mozunit -from xpidl import header, xpidl +from xpidl import header, typescript, xpidl class TestParser(unittest.TestCase): @@ -253,5 +255,42 @@ attribute long bar; self.assertEqual(e.args[0], ("cannot find symbol 'Y'")) +class TestTypescript(unittest.TestCase): + """A few basic smoke tests for typescript generation.""" + + dir = os.path.dirname(__file__) + src = os.path.join(dir, "..", "..", "..") + + # We use the xpctest.xpt *.idl files from: + tests_dir = os.path.join(src, "js/xpconnect/tests/idl") + files = [ + "xpctest_attributes.idl", + "xpctest_bug809674.idl", + "xpctest_cenums.idl", + "xpctest_interfaces.idl", + "xpctest_params.idl", + "xpctest_returncode.idl", + "xpctest_utils.idl", + ] + + fixtures = os.path.join(dir, "fixtures") + inc_dirs = [os.path.join(src, "xpcom/base")] + + def setUp(self): + self.parser = xpidl.IDLParser() + + def test_d_json(self): + mods = [] + for file in self.files: + path = os.path.join(self.tests_dir, file) + idl = self.parser.parse(open(path).read(), path) + idl.resolve(self.inc_dirs, self.parser, {}) + mods.append(typescript.ts_source(idl)) + + result = json.dumps(mods, indent=2, sort_keys=True) + expected = open(os.path.join(self.fixtures, "xpctest.d.json")).read() + self.assertEqual(result, expected, "types data json does not match") + + if __name__ == "__main__": mozunit.main(runwith="unittest") diff --git a/xpcom/idl-parser/xpidl/rust.py b/xpcom/idl-parser/xpidl/rust.py index b9fc6627fb..5d906d85ea 100644 --- a/xpcom/idl-parser/xpidl/rust.py +++ b/xpcom/idl-parser/xpidl/rust.py @@ -363,8 +363,8 @@ def print_rust_bindings(idl, fd, relpath): if p.kind == "typedef": try: - # We have to skip the typedef of bool to bool (it doesn't make any sense anyways) - if p.name == "bool": + # Skip bool and C++ stdint typedefs marked with [substitute]. + if p.substitute: continue if printdoccomments: diff --git a/xpcom/idl-parser/xpidl/typescript.py b/xpcom/idl-parser/xpidl/typescript.py new file mode 100644 index 0000000000..614a328edf --- /dev/null +++ b/xpcom/idl-parser/xpidl/typescript.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python +# typescript.py - Collect .d.json TypeScript info from xpidl. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import json + +import mozpack.path as mozpath + +from xpidl import xpidl + + +def ts_enum(e): + variants = [{"name": v.name, "value": v.getValue()} for v in e.variants] + return {"id": e.basename, "variants": variants} + + +def ts_attribute(a): + return {"name": a.name, "type": a.realtype.tsType(), "readonly": a.readonly} + + +def ts_method(m): + args = [] + for p in m.params: + if p.iid_is and not p.retval: + raise xpidl.TSNoncompat(f"{m.name} has unsupported iid_is argument") + args.append({"name": p.name, "optional": p.optional, "type": p.tsType()}) + + iid_is = None + type = m.realtype.tsType() + if args and m.params[-1].retval: + type = args.pop()["type"] + iid_is = m.params[-1].iid_is + + return {"name": m.name, "type": type, "iid_is": iid_is, "args": args} + + +def ts_interface(iface): + enums = [] + consts = [] + members = [] + + for m in iface.members: + try: + if isinstance(m, xpidl.CEnum): + enums.append(ts_enum(m)) + elif isinstance(m, xpidl.ConstMember): + consts.append({"name": m.name, "value": m.getValue()}) + elif isinstance(m, xpidl.Attribute) and m.isScriptable(): + members.append(ts_attribute(m)) + elif isinstance(m, xpidl.Method) and m.isScriptable(): + members.append(ts_method(m)) + except xpidl.TSNoncompat: + # Omit member if any type is unsupported. + pass + + return { + "id": iface.name, + "base": iface.base, + "callable": iface.attributes.function, + "enums": enums, + "consts": consts, + "members": members, + } + + +def ts_typedefs(idl): + for p in idl.getNames(): + if isinstance(p, xpidl.Typedef) and not p.substitute: + try: + yield (p.name, p.realtype.tsType()) + except xpidl.TSNoncompat: + pass + + +def ts_source(idl): + """Collect typescript interface .d.json from a source idl file.""" + root = mozpath.join(mozpath.dirname(__file__), "../../..") + return { + "path": mozpath.relpath(idl.productions[0].location._file, root), + "interfaces": [ + ts_interface(p) + for p in idl.productions + if isinstance(p, xpidl.Interface) and p.attributes.scriptable + ], + "typedefs": sorted(ts_typedefs(idl)), + } + + +def write(d_json, fd): + """Write json type info into fd""" + json.dump(d_json, fd, indent=2, sort_keys=True) diff --git a/xpcom/idl-parser/xpidl/xpidl.py b/xpcom/idl-parser/xpidl/xpidl.py index b95fd14bc5..19d042d1b0 100755 --- a/xpcom/idl-parser/xpidl/xpidl.py +++ b/xpcom/idl-parser/xpidl/xpidl.py @@ -122,10 +122,13 @@ class Builtin(object): kind = "builtin" location = BuiltinLocation - def __init__(self, name, nativename, rustname, signed=False, maybeConst=False): + def __init__( + self, name, nativename, rustname, tsname, signed=False, maybeConst=False + ): self.name = name self.nativename = nativename self.rustname = rustname + self.tsname = tsname self.signed = signed self.maybeConst = maybeConst @@ -171,28 +174,37 @@ class Builtin(object): return "%s%s" % ("*mut " if "out" in calltype else "", rustname) + def tsType(self): + if self.tsname: + return self.tsname + + raise TSNoncompat(f"Builtin type {self.name} unsupported in TypeScript") + builtinNames = [ - Builtin("boolean", "bool", "bool"), - Builtin("void", "void", "libc::c_void"), - Builtin("octet", "uint8_t", "u8", False, True), - Builtin("short", "int16_t", "i16", True, True), - Builtin("long", "int32_t", "i32", True, True), - Builtin("long long", "int64_t", "i64", True, True), - Builtin("unsigned short", "uint16_t", "u16", False, True), - Builtin("unsigned long", "uint32_t", "u32", False, True), - Builtin("unsigned long long", "uint64_t", "u64", False, True), - Builtin("float", "float", "libc::c_float", True, False), - Builtin("double", "double", "libc::c_double", True, False), - Builtin("char", "char", "libc::c_char", True, False), - Builtin("string", "char *", "*const libc::c_char", False, False), - Builtin("wchar", "char16_t", "u16", False, False), - Builtin("wstring", "char16_t *", "*const u16", False, False), + Builtin("boolean", "bool", "bool", "boolean"), + Builtin("void", "void", "libc::c_void", "void"), + Builtin("octet", "uint8_t", "u8", "u8", False, True), + Builtin("short", "int16_t", "i16", "i16", True, True), + Builtin("long", "int32_t", "i32", "i32", True, True), + Builtin("long long", "int64_t", "i64", "i64", True, True), + Builtin("unsigned short", "uint16_t", "u16", "u16", False, True), + Builtin("unsigned long", "uint32_t", "u32", "u32", False, True), + Builtin("unsigned long long", "uint64_t", "u64", "u64", False, True), + Builtin("float", "float", "libc::c_float", "float"), + Builtin("double", "double", "libc::c_double", "double"), + Builtin("char", "char", "libc::c_char", "string"), + Builtin("string", "char *", "*const libc::c_char", "string"), + Builtin("wchar", "char16_t", "u16", "string"), + Builtin("wstring", "char16_t *", "*const u16", "string"), # As seen in mfbt/RefCountType.h, this type has special handling to # maintain binary compatibility with MSCOM's IUnknown that cannot be # expressed in XPIDL. Builtin( - "MozExternalRefCountType", "MozExternalRefCountType", "MozExternalRefCountType" + "MozExternalRefCountType", + "MozExternalRefCountType", + "MozExternalRefCountType", + None, ), ] @@ -308,6 +320,16 @@ class RustNoncompat(Exception): return self.reason +class TSNoncompat(Exception): + """Raised when a type cannot be exposed to TypeScript.""" + + def __init__(self, reason): + self.reason = reason + + def __str__(self): + return self.reason + + class IDLError(Exception): def __init__(self, message, location, warning=False, notes=None): self.message = message @@ -458,12 +480,20 @@ class CDATA(object): class Typedef(object): kind = "typedef" - def __init__(self, type, name, location, doccomments): + def __init__(self, type, name, attlist, location, doccomments): self.type = type self.name = name self.location = location self.doccomments = doccomments + # C++ stdint types and the bool typedef from nsrootidl.idl are marked + # with [substitute], and emit as the underlying builtin type directly. + self.substitute = False + for name, value, aloc in attlist: + if name != "substitute" or value is not None: + raise IDLError(f"Unexpected attribute {name}({value})", aloc) + self.substitute = True + def __eq__(self, other): return self.name == other.name and self.type == other.type @@ -475,14 +505,26 @@ class Typedef(object): raise IDLError("Unsupported typedef target type", self.location) def nativeType(self, calltype): + if self.substitute: + return self.realtype.nativeType(calltype) + return "%s %s" % (self.name, "*" if "out" in calltype else "") def rustType(self, calltype): + if self.substitute: + return self.realtype.rustType(calltype) + if self.name == "nsresult": return "%s::nserror::nsresult" % ("*mut " if "out" in calltype else "") return "%s%s" % ("*mut " if "out" in calltype else "", self.name) + def tsType(self): + if self.substitute: + return self.realtype.tsType() + + return self.name + def __str__(self): return "typedef %s %s\n" % (self.type, self.name) @@ -524,6 +566,9 @@ class Forward(object): return "Option<RefPtr<%s>>" % self.name return "%s*const %s" % ("*mut" if "out" in calltype else "", self.name) + def tsType(self): + return self.name + def __str__(self): return "forward-declared %s\n" % self.name @@ -701,6 +746,21 @@ class Native(object): raise RustNoncompat("native type %s unsupported" % self.nativename) + ts_special = { + "astring": "string", + "cstring": "string", + "jsval": "any", + "nsid": "nsID", + "promise": "Promise<any>", + "utf8string": "string", + } + + def tsType(self): + if type := self.ts_special.get(self.specialtype, None): + return type + + raise TSNoncompat(f"Native type {self.name} unsupported in TypeScript") + def __str__(self): return "native %s(%s)\n" % (self.name, self.nativename) @@ -749,6 +809,9 @@ class WebIDL(object): # Just expose the type as a void* - we can't do any better. return "%s*const libc::c_void" % ("*mut " if "out" in calltype else "") + def tsType(self): + return self.name + def __str__(self): return "webidl %s\n" % self.name @@ -923,6 +986,9 @@ class Interface(object): total += realbase.countEntries() return total + def tsType(self): + return self.name + class InterfaceAttributes(object): uuid = None @@ -1110,6 +1176,9 @@ class CEnum(object): def rustType(self, calltype): return "%s u%d" % ("*mut" if "out" in calltype else "", self.width) + def tsType(self): + return f"{self.iface.name}.{self.basename}" + def __str__(self): body = ", ".join("%s = %s" % v for v in self.variants) return "\tcenum %s : %d { %s };\n" % (self.name, self.width, body) @@ -1523,8 +1592,22 @@ class Param(object): self.name, ) + def tsType(self): + # A generic retval param type needs special handling. + if self.retval and self.iid_is: + return "nsQIResult" + + type = self.realtype.tsType() + if self.paramtype == "inout": + return f"InOutParam<{type}>" + if self.paramtype == "out": + return f"OutParam<{type}>" + return type + class LegacyArray(object): + kind = "legacyarray" + def __init__(self, basetype): self.type = basetype self.location = self.type.location @@ -1555,6 +1638,9 @@ class LegacyArray(object): self.type.rustType("legacyelement"), ) + def tsType(self): + return self.type.tsType() + "[]" + class Array(object): kind = "array" @@ -1594,6 +1680,9 @@ class Array(object): else: return base + def tsType(self): + return self.type.tsType() + "[]" + TypeId = namedtuple("TypeId", "name params") @@ -1751,12 +1840,13 @@ class IDLParser(object): p[0].insert(0, p[1]) def p_typedef(self, p): - """typedef : TYPEDEF type IDENTIFIER ';'""" + """typedef : attributes TYPEDEF type IDENTIFIER ';'""" p[0] = Typedef( - type=p[2], - name=p[3], - location=self.getLocation(p, 1), - doccomments=p.slice[1].doccomments, + type=p[3], + name=p[4], + attlist=p[1]["attlist"], + location=self.getLocation(p, 2), + doccomments=getattr(p[1], "doccomments", []) + p.slice[2].doccomments, ) def p_native(self, p): |