diff options
Diffstat (limited to 'xpcom/docs/xpidl.rst')
-rw-r--r-- | xpcom/docs/xpidl.rst | 390 |
1 files changed, 390 insertions, 0 deletions
diff --git a/xpcom/docs/xpidl.rst b/xpcom/docs/xpidl.rst new file mode 100644 index 0000000000..9f1a36ebb7 --- /dev/null +++ b/xpcom/docs/xpidl.rst @@ -0,0 +1,390 @@ +XPIDL +===== + +**XPIDL** is an Interface Description Language used to specify XPCOM interface +classes. + +Interface Description Languages (IDL) are used to describe interfaces in a +language- and machine-independent way. IDLs make it possible to define +interfaces which can then be processed by tools to autogenerate +language-dependent interface specifications. + +An xpidl file is essentially just a series of declarations. At the top level, +we can define typedefs, native types, or interfaces. Interfaces may +furthermore contain typedefs, natives, methods, constants, or attributes. +Most declarations can have properties applied to them. + +Types +----- + +There are three ways to make types: a typedef, a native, or an interface. In +addition, there are a few built-in native types. The built-in native types +are those listed under the type_spec production above. The following is the +correspondence table: + +=========================== =============== =========================== ============================ ======================= ======================= +IDL Type Javascript Type C++ in parameter C++ out parameter Rust in parameter Rust out parameter +=========================== =============== =========================== ============================ ======================= ======================= +``boolean`` boolean ``bool`` ``bool*`` ``bool`` ``*mut bool`` +``char`` string ``char`` ``char*`` ``c_char`` ``*mut c_char`` +``double`` number ``double`` ``double*`` ``f64`` ``*mut f64`` +``float`` number ``float`` ``float*`` ``f32`` ``*mut f32`` +``long`` number ``int32_t`` ``int32_t*`` ``i32`` ``*mut i32`` +``long long`` number ``int64_t`` ``int64_t*`` ``i64`` ``*mut i64`` +``octet`` number ``uint8_t`` ``uint8_t*`` ``u8`` ``*mut u8`` +``short`` number ``uint16_t`` ``uint16_t*`` ``u16`` ``*mut u16`` +``string`` [#strptr]_ string ``const char*`` ``char**`` ``*const c_char`` ``*mut *mut c_char`` +``unsigned long`` number ``uint32_t`` ``uint32_t*`` ``u32`` ``*mut u32`` +``unsigned long long`` number ``uint64_t`` ``uint64_t*`` ``u64`` ``*mut u64`` +``unsigned short`` number ``uint16_t`` ``uint16_t*`` ``u16`` ``*mut u16`` +``wchar`` string ``char16_t`` ``char16_t*`` ``i16`` ``*mut i16`` +``wstring`` [#strptr]_ string ``const char16_t*`` ``char16_t**`` ``*const i16`` ``*mut *mut i16`` +``MozExternalRefCountType`` number ``MozExternalRefCountType`` ``MozExternalRefCountType*`` ``u32`` ``*mut u32`` +``Array<T>`` [#array]_ array ``const nsTArray<T>&`` ``nsTArray<T>&`` ``*const ThinVec<T>`` ``*mut ThinVec<T>`` +=========================== =============== =========================== ============================ ======================= ======================= + +.. [#strptr] + + Prefer using the string class types such as ``AString``, ``AUTF8String`` + or ``ACString`` to this type. The behaviour of these types is documented + more in the :ref:`String Guide <stringguide.xpidl>` + +.. [#array] + + The C++ or Rust exposed type ``T`` will be an owned variant. (e.g. + ``ns[C]String``, ``RefPtr<T>``, or ``uint32_t``) + + ``string``, ``wstring``, ``[ptr] native`` and ``[ref] native`` are + unsupported as element types. + + +In addition to this list, nearly every IDL file includes ``nsrootidl.idl`` in +some fashion, which also defines the following types: + +======================= ======================= ======================= ======================= ======================= ======================= +IDL Type Javascript Type C++ in parameter C++ out parameter Rust in parameter Rust out parameter +======================= ======================= ======================= ======================= ======================= ======================= +``PRTime`` number ``uint64_t`` ``uint64_t*`` ``u64`` ``*mut u64`` +``nsresult`` number ``nsresult`` ``nsresult*`` ``u32`` [#rsresult]_ ``*mut u32`` +``size_t`` number ``uint32_t`` ``uint32_t*`` ``u32`` ``*mut u32`` +``voidPtr`` N/A ``void*`` ``void**`` ``*mut c_void`` ``*mut *mut c_void`` +``charPtr`` N/A ``char*`` ``char**`` ``*mut c_char`` ``*mut *mut c_char`` +``unicharPtr`` N/A ``char16_t*`` ``char16_t**`` ``*mut i16`` ``*mut *mut i16`` +``nsIDRef`` ID object ``const nsID&`` ``nsID*`` ``*const nsID`` ``*mut nsID`` +``nsIIDRef`` ID object ``const nsIID&`` ``nsIID*`` ``*const nsIID`` ``*mut nsIID`` +``nsCIDRef`` ID object ``const nsCID&`` ``nsCID*`` ``*const nsCID`` ``*mut nsCID`` +``nsIDPtr`` ID object ``const nsID*`` ``nsID**`` ``*const nsID`` ``*mut *mut nsID`` +``nsIIDPtr`` ID object ``const nsIID*`` ``nsIID**`` ``*const nsIID`` ``*mut *mut nsIID`` +``nsCIDPtr`` ID object ``const nsCID*`` ``nsCID**`` ``*const nsCID`` ``*mut *mut nsCID`` +``nsID`` N/A ``nsID`` ``nsID*`` N/A N/A +``nsIID`` N/A ``nsIID`` ``nsIID*`` N/A N/A +``nsCID`` N/A ``nsCID`` ``nsCID*`` N/A N/A +``nsQIResult`` object ``void*`` ``void**`` ``*mut c_void`` ``*mut *mut c_void`` +``AUTF8String`` [#str]_ string ``const nsACString&`` ``nsACString&`` ``*const nsACString`` ``*mut nsACString`` +``ACString`` [#str]_ string ``const nsACString&`` ``nsACString&`` ``*const nsACString`` ``*mut nsACString`` +``AString`` [#str]_ string ``const nsAString&`` ``nsAString&`` ``*const nsAString`` ``*mut nsAString`` +``jsval`` any ``HandleValue`` ``MutableHandleValue`` N/A N/A +``jsid`` N/A ``jsid`` ``jsid*`` N/A N/A +``Promise`` Promise object ``dom::Promise*`` ``dom::Promise**`` N/A N/A +======================= ======================= ======================= ======================= ======================= ======================= + +.. [#rsresult] + + A bare ``u32`` is only for bare ``nsresult`` in/outparams in XPIDL. The + result should be wrapped as the ``nserror::nsresult`` type. + +.. [#str] + + The behaviour of these types is documented more in the :ref:`String Guide + <stringguide.xpidl>` + +Typedefs in IDL are basically as they are in C or C++: you define first the +type that you want to refer to and then the name of the type. Types can of +course be one of the fundamental types, or any other type declared via a +typedef, interface, or a native type. + +Native types are types which correspond to a given C++ type. Most native +types are not scriptable: if it is not present in the list above, then it is +certainly not scriptable (some of the above, particularly jsid, are not +scriptable). + +The contents of the parentheses of a native type declaration (although native +declarations without parentheses are parsable, I do not trust that they are +properly handled by the xpidl handlers) is a string equivalent to the C++ +type. XPIDL itself does not interpret this string, it just literally pastes +it anywhere the native type is used. The interpretation of the type can be +modified by using the ``[ptr]`` or ``[ref]`` attributes on the native +declaration. Other attributes are only intended for use in ``nsrootidl.idl``. + +WebIDL Interfaces +~~~~~~~~~~~~~~~~~ + +WebIDL interfaces are also valid XPIDL types. To declare a WebIDL interface in +XPIDL, write: + +.. code-block:: + + webidl InterfaceName; + +WebIDL types will be passed as ``mozilla::dom::InterfaceName*`` when used as +in-parameters, as ``mozilla::dom::InterfaceName**`` when used as out or +inout-parameters, and as ``RefPtr<mozilla::dom::InterfaceName>`` when used as +an array element. + +.. note:: + + Other WebIDL types (e.g. dictionaries, enums, and unions) are not currently + supported. + +Constants and CEnums +~~~~~~~~~~~~~~~~~~~~ + +Constants must be attached to an interface. The only constants supported are +those which become integer types when compiled to source code; string constants +and floating point constants are currently not supported. + +Often constants are used to describe a set of enum values. In cases like this +the ``cenum`` construct can be used to group constants together. Constants +grouped in a ``cenum`` will be reflected as-if they were declared directly on +the interface, in Rust and Javascript code. + +.. code-block:: + + cenum MyCEnum : 8 { + eSomeValue, // starts at 0 + eSomeOtherValue, + }; + +The number after the enum name, like ``: 8`` in the example above, defines the +width of enum values with the given type. The cenum's type may be referenced in +xpidl as ``nsIInterfaceName_MyCEnum``. + +Interfaces +---------- + +Interfaces are basically a collection of constants, methods, and attributes. +Interfaces can inherit from one-another, and every interface must eventually +inherit from ``nsISupports``. + +Interface Attributes +~~~~~~~~~~~~~~~~~~~~ + +Interfaces may have the following attributes: + +``uuid`` +```````` + +The internal unique identifier for the interface. it must be unique, and the +uuid must be generated when creating the interface. After that, it doesn't need +to be changed any more. + +Online tools such as http://mozilla.pettay.fi/cgi-bin/mozuuid.pl can help +generate UUIDs for new interfaces. + +``builtinclass`` +```````````````` + +JavaScript classes are forbidden from implementing this interface. All child +interfaces must also be marked with this property. + +``function`` +```````````` + +The JavaScript implementation of this interface may be a function that is +invoked on property calls instead of an object with the given property + +``scriptable`` +`````````````` + +This interface is usable by JavaScript classes. Must inherit from a +``scriptable`` interface. + +Methods and Attributes +~~~~~~~~~~~~~~~~~~~~~~ + +Interfaces declare a series of attributes and methods. Attributes in IDL are +akin to JavaScript properties, in that they are a getter and (optionally) a +setter pair. In JavaScript contexts, attributes are exposed as a regular +property access, while native code sees attributes as a Get and possibly a Set +method. + +Attributes can be declared readonly, in which case setting causes an error to +be thrown in script contexts and native contexts lack the Set method, by using +the ``readonly`` keyword. + +To native code, on attribute declared ``attribute type foo;`` is syntactic +sugar for the declaration of two methods ``type getFoo();`` and ``void +setFoo(in type foo);``. If ``foo`` were declared readonly, the latter method +would not be present. Attributes support all of the properties of methods with +the exception of ``optional_argc``, as this does not make sense for attributes. + +There are some special rules for attribute naming. As a result of vtable +munging by the MSVC++ compiler, an attribute with the name ``IID`` is +forbidden. Also like methods, if the first character of an attribute is +lowercase in IDL, it is made uppercase in native code only. + +Methods define a return type and a series of in and out parameters. When called +from a JavaScript context, they invocation looks as it is declared for the most +part; some parameter properties can adjust what the code looks like. The calls +are more mangled in native contexts. + +An important attribute for methods and attributes is scriptability. A method or +attribute is scriptable if it is declared in a ``scriptable`` interface and it +lacks a ``noscript`` or ``notxpcom`` property. Any method that is not +scriptable can only be accessed by native code. However, ``scriptable`` methods +must contain parameters and a return type that can be translated to script: any +native type, save a few declared in ``nsrootidl.idl`` (see above), may not be +used in a scriptable method or attribute. An exception to the above rule is if +a ``nsQIResult`` parameter has the ``iid_is`` property (a special case for some +QueryInterface-like operations). + +Methods and attributes are mangled on conversion to native code. If a method is +declared ``notxpcom``, the mangling of the return type is prevented, so it is +called mostly as it looks. Otherwise, the return type of the native method is +``nsresult``, and the return type acts as a final outparameter if it is not +``void``. The name is translated so that the first character is +unconditionally uppercase; subsequent characters are unaffected. However, the +presence of the ``binaryname`` property allows the user to select another name +to use in native code (to avoid conflicts with other functions). For example, +the method ``[binaryname(foo)] void bar();`` becomes ``nsresult Foo()`` in +native code (note that capitalization is still applied). However, the +capitalization is not applied when using ``binaryname`` with attributes; i.e., +``[binaryname(foo)] readonly attribute Quux bar;`` becomes ``Getfoo(Quux**)`` +in native code. + +The ``implicit_jscontext`` and ``optional_argc`` parameters are properties +which help native code implementations determine how the call was made from +script. If ``implicit_jscontext`` is present on a method, then an additional +``JSContext* cx`` parameter is added just after the regular list which receives +the context of the caller. If ``optional_argc`` is present, then an additional +``uint8_t _argc`` parameter is added at the end which receives the number of +optional arguments that were actually used (obviously, you need to have an +optional argument in the first place). Note that if both properties are set, +the ``JSContext* cx`` is added first, followed by the ``uint8_t _argc``, and +then ending with return value parameter. Finally, as an exception to everything +already mentioned, for attribute getters and setters the ``JSContext *cx`` +comes before any other arguments. + +Another native-only property is ``nostdcall``. Normally, declarations are made +in the stdcall ABI on Windows to be ABI-compatible with COM interfaces. Any +non-scriptable method or attribute with ``nostdcall`` instead uses the +``thiscall`` ABI convention. Methods without this property generally use +``NS_IMETHOD`` in their declarations and ``NS_IMETHODIMP`` in their definitions +to automatically add in the stdcall declaration specifier on requisite +compilers; those that use this method may use a plain ``nsresult`` instead. + +Another property, ``infallible``, is attribute-only. When present, it causes an +infallible C++ getter function definition to be generated for the attribute +alongside the normal fallible C++ getter declaration. It should only be used if +the fallible getter will be infallible in practice (i.e. always return +``NS_OK``) for all possible implementations. This infallible getter contains +code that calls the fallible getter, asserts success, and returns the gotten +value directly. The point of using this property is to make C++ code nicer -- a +call to the infallible getter is more concise and readable than a call to the +fallible getter. This property can only be used for attributes having built-in +or interface types, and within classes that are marked with ``builtinclass``. +The latter restriction is because C++ implementations of fallible getters can +be audited for infallibility, but JS implementations can always throw (e.g. due +to OOM). + +The ``must_use`` property is useful if the result of a method call or an +attribute get/set should always (or usually) be checked, which is frequently +the case. (e.g. a method that opens a file should almost certainly have its +result checked.) This property will cause ``[[nodiscard]]`` to be added to the +generated function declarations, which means certain compilers (e.g. clang and +GCC) will reports errors if these results are not used. + +Method Parameters +~~~~~~~~~~~~~~~~~ + +Each method parameter can be specified in one of three modes: ``in``, ``out``, +or ``inout``. An ``out`` parameter is essentially an auxiliary return value, +although these are moderately cumbersome to use from script contexts and should +therefore be avoided if reasonable. An ``inout`` parameter is an in parameter +whose value may be changed as a result of the method; these parameters are +rather annoying to use and should generally be avoided if at all possible. + +``out`` and ``inout`` parameters are reflected as objects having the ``.value`` +property which contains the real value of the parameter; the ``value`` +attribute is missing in the case of ``out`` parameters and is initialized to +the passed-in-value for ``inout`` parameters. The script code needs to set this +property to assign a value to the parameter. Regular ``in`` parameters are +reflected more or less normally, with numeric types all representing numbers, +booleans as ``true`` or ``false``, the various strings (including ``AString`` +etc.) as a JavaScript string, and ``nsID`` types as a ``Components.ID`` +instance. In addition, the ``jsval`` type is translated as the appropriate +JavaScript value (since a ``jsval`` is the internal representation of all +JavaScript values), and parameters with the ``nsIVeriant`` interface have their +types automatically boxed and unboxed as appropriate. + +The equivalent representations of all IDL types in native code is given in the +earlier tables; parameters of type ``inout`` follow their ``out`` form. Native +code should pay particular attention to not passing in null values for out +parameters (although some parts of the codebase are known to violate this, it +is strictly enforced at the JS<->native barrier). + +Representations of types additionally depend on some of the many types of +properties they may have. The ``array`` property turns the parameter into an array; +the parameter must also have a corresponding ``size_is`` property whose argument is +the parameter that has the size of the array. In native code, the type gains +another pointer indirection, and JavaScript arrays are used in script code. +Script code callers can ignore the value of array parameter, but implementors +must still set the values appropriately. + +.. note:: + + Prefer using the ``Array<T>`` builtin over the ``[array]`` attribute for + new code. It is more ergonomic to use from both JS and C++. In the future, + ``[array]`` may be deprecated and removed. + +The ``const`` and ``shared`` properties are special to native code. As its name +implies, the ``const`` property makes its corresponding argument ``const``. The +``shared`` property is only meaningful for ``out`` or ``inout`` parameters and +it means that the pointer value should not be freed by the caller. Only simple +native pointer types like ``string``, ``wstring``, and ``octetPtr`` may be +declared shared. The shared property also makes its corresponding argument +const. + +The ``retval`` property indicates that the parameter is actually acting as the +return value, and it is only the need to assign properties to the parameter +that is causing it to be specified as a parameter. It has no effect on native +code, but script code uses it like a regular return value. Naturally, a method +which contains a ``retval`` parameter must be declared ``void``, and the +parameter itself must be an ``out`` parameter and the last parameter. + +Other properties are the ``optional`` and ``iid_is`` property. The ``optional`` +property indicates that script code may omit the property without problems; all +subsequent parameters must either by optional themselves or the retval +parameter. Note that optional out parameters still pass in a variable for the +parameter, but its value will be ignored. The ``iid_is`` parameter indicates +that the real IID of an ``nsQIResult`` parameter may be found in the +corresponding parameter, to allow script code to automatically unbox the type. + +Not all type combinations are possible. Native types with the various string +properties are all forbidden from being used as an ``inout`` parameter or as an +``array`` parameter. In addition, native types with the ``nsid`` property but +lacking either a ``ptr`` or ``ref`` property are forbidden unless the method is +``notxpcom`` and it is used as an ``in`` parameter. + +Ownership Rules +``````````````` + +For types that reference heap-allocated data (strings, arrays, interface +pointers, etc), you must follow the XPIDL data ownership conventions in order +to avoid memory corruption and security vulnerabilities: + +* For ``in`` parameters, the caller allocates and deallocates all data. If the + callee needs to use the data after the call completes, it must make a private + copy of the data, or, in the case of interface pointers, ``AddRef`` it. +* For ``out`` parameters, the callee creates the data, and transfers ownership + to the caller. For buffers, the callee allocates the buffer with ``malloc``, + and the caller frees the buffer with ``free``. For interface pointers, the + callee does the ``AddRef`` on behalf of the caller, and the caller must call + ``Release``. This manual reference/memory management should be performed + using the ``getter_AddRefs`` and ``getter_Transfers`` helpers in new code. +* For ``inout`` parameters, the callee must clean up the old data if it chooses + to replace it. Buffers must be deallocated with ``free``, and interface + pointers must be ``Release``'d. Afterwards, the above rules for ``out`` + apply. +* ``shared`` out-parameters should not be freed, as they are intended to refer + to constant string literals. |