Closed Bug 13424 Opened 25 years ago Closed 15 years ago

xpidl could use component declarations in idl

Categories

(Core :: XPCOM, defect, P5)

defect

Tracking

()

RESOLVED WONTFIX
Future

People

(Reporter: jband_mozilla, Assigned: dbradley)

References

Details

from...
news://news.mozilla.org/37A13C72.7F1D8CC7%40netscape.com

I think that xpcom needs something like what MS calls a
'coclass'. This is a way to declare information about components
- what interfaces they expose, their CLSID, and progid, etc.
Ideally this is expressed in idl. We were thinking of punting on
this, but it is a pretty important thing to have. Brendan has
offered to look at implementing this. I am writing to express my
thoughts as a baseline for discussion of a spec to be worked out
(in code if nowhere else :).

We need component declarations for a number of reasons...

1) There are many existing components that do (and must) expose
multiple interfaces. Knowledge about which interfaces these
components expose is implicit rather than explicit.

2) XPConnect wants to use information about the set of interfaces
exposed by particular classes of components in order to 'flatten'
those interfaces. This means that from JavaScript any method of
any of the interfaces on the object could be called without
having to QI the object to one particular interface. This is a
big simplification for JS programmers. It is also a requirement
for eventually moving the DOM to use xpconnect.

3) We don't have generic places to declare progids and clsids.
Now we'd have a standard way.

4) We want to implement components in languages other than C++.
This is going to require extensions to the component manager apis
to have plugable component loaders for different 'types' of
components; e.g. JavaScript components loaded from .js files, or
Java components loaded from .jar files, or whatever. Each type
will require some sort of mechanism for doing the equivalent of
'NSRegisterSelf'. We could use a generic declarative
representation of a component's registration data (expressed in
idl) and then format that data into the appropriate form to pass
on to the component manager. We can use this for C++ components
too! For C++ components this might be compilable C++ code to be
#included into the body of the NSRegisterSelf function. For other
components this might be a series of xpconnected (interpreted)
calls to the component manager.

5) Our 'interface' declaration in our .idl files is the place to
describe *and* document interfaces. However, it is bad form to
assume that all interfaces are implemented by one and only one
component. Thus, we need a place to describe and document
component implementations. This is the place.

I propose that we use the keyword 'component' in our .idl files
to use in place of what MS calls 'coclass'.

What I propose is somewhat different from the MS scheme. It would
look like:

/**
* ...JavaDoc style documentation here...
*/

[
uuid(xxx-xxx...),
progid(some.prog.id),
impersonates(some.other.prog.id),
type(aplication/x-xpjs),
location(@location)
]
component
{
    interface nsIFoo;
    interface nsIBar;
};


Details:

- 'uuid' is the clsid for this particular implementation of the
component. It is required for this all to have meaning.

- 'progid' is the progid to be associated with that cid. It is
optional but highly recommended. It is 'any' string.

- 'impersonates' is an idea I'm kicking around. It is to be used
if in the future the component manager supports the idea that a
component can register that it impersonates some other component.
This way component 'A' could claim to impersonate component 'B'.
So any calls to create a 'B' object would get routed to the 'A'
factory. We might want a way to do more than one of these?
Obviously this is optional.

- 'type' is a way to declare the 'loader' type of the component.
This ought to look like a mime type. This will tell the component
manager which kind of loader to use in order to load the factory
to make this component. Optional - default to whatever type
string we use to mean "native code in a dll"

- 'location' is the string passed to the loader to tell it where
to find this component. This is the equivalent of the 'path'
param passed to NSRegisterSelf. The a given loader this might
mean a filename, a name in a given jar, a database id where the
code lives, whatever. It is loader specific.

NOTE that there is no identifier after the keyword 'component'.
If we always had simple identifiers for progids this would be the
place to put it. But we do not.

The keyword 'interface' is used before each interface mentioned.
This might seem unnecessary, But, though we only support listing
interfaces in the body of the declaration now, we may want to put
other stuff there in the future. We also might want to have
attributes on these lines; e.g.

  [default] interface nsIFoo;

At this point I don't think that there are any attributes we need
(like default) for these lines, but something might come up.

For the component attribute strings (e.g. 'type' or 'location')
we might want to have some way to identify if they are to be
quoted or not in the final output. Perhaps requiring that they be
explicitly quoted in the input is enough. I bring this up because
sometimes we have an exact string to use in the idl file and
sometimes we only want to pass through some identifier to be used
in the generated code. e.g...

[... location(myClass)...]

might be used to reference a particular named classfile in a
known jar and emit code like:

 cm.RegisterComponent(..., "myclass",...);

OR

we might want it to be an identifier that is assumed to be
defined in the #including code:

[... location(aPath)...]

emits into "mycomponent.inc":

rv = cm->RegisterComponent(..., aPath,...);

and is used like:

NSRegisterSelf(...,const char* aPath)
{
...
#include "mycomponent.inc"
...
}

We have not generally been quoting strings in attributes, so
location("myClass") might be an atypical way to produce the more
typical output for the first case. We might quote the output by
default and require some symbol to mean 'don't quote'; e.g.
location(#aPath) or location(%aPath) or something. I don't know.
I just wanted to bring it up.

The list of interface names keyed to the CLSID in the declaration
is not something that would currently go via the component
manager into the registry. I expect that we will either: create a
new service that handles moving these lists into and out of the
registry, or extend the component manager to do this for us. The
component manager is already going to be owning the branch of the
registry where 'per CLSID' information is stored. Either way
we'll expose an api into C++ and JS to which we can use xpidl to
generate code to store these lists. And.. I expect that rather
than store the interface names in the registry, we'll use the
nsInterfaceInfoManager at that time to resolve the interface
names into IIDs. We'll work this out

I'm imagining that we'll have at least two output 'formats': 1)
blocks of C++ component manager calls and 2) blocks of JS
component manager calls. We might want some other format(s). It
might be tempting to determine the format based on the content of
the input files, but I think that this is counter to how we do
other file generation from xpidl. Even though these component
declarations are specific to a specific implementation, I still
think it is fine to generate each type into its own output file
to be used or ignored by other code. Running xpidl is pretty
cheap.

I've been assuming that the output gets merged into the registry
via the component manager one way or another. A reasonable
question is: "why not put this in typelibs like the interface
stuff?". We've discussed this a bit and the consensus so far is
that this is all implementation specific stuff that generally
belongs in the component manager's branch of the registry is not
really generic interface information at all.

That's all I can think of. There is a lot to be worked out - and
some is based on component manager methods (and their reflection
into JS) that are not yet written.
Status: NEW → ASSIGNED
Target Milestone: M14
Assignee: brendan → mccabe
Status: ASSIGNED → NEW
Status: NEW → ASSIGNED
Marking as assigned.  Working on it currently.
Blocks: 12915
Pushing to m16.  I don't think I'm going to get this in for beta.
Target Milestone: M14 → M16
OS: Windows NT → All
Hardware: PC → All
M16 has been out for a while now, these bugs target milestones need to be 
updated.
[SPAM] Marking milestone 'future' as part of nsbeta3 triage.
Target Milestone: M16 → Future
Mass-reassigning mccabe's non-JS, non-Rhino bugs to jband (34 total). 

Would like to cc mccabe; but the mass-reassign page does not allow this. 
I'll leave it up to mccabe to decide if he wants to be cc'ed on these - 
Assignee: mike+mozilla → jband
Status: ASSIGNED → NEW
mass reassign of xpidl bugs to dbradley@netscape.com
Assignee: jband → dbradley
Status: NEW → ASSIGNED
Priority: P3 → P5
Component: xpidl → XPCOM
QA Contact: mike+mozilla → xpcom
Status: ASSIGNED → RESOLVED
Closed: 15 years ago
Resolution: --- → WONTFIX
You need to log in before you can comment on or make changes to this bug.