зеркало из https://github.com/mozilla/gecko-dev.git
391 строка
22 KiB
ReStructuredText
391 строка
22 KiB
ReStructuredText
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.
|