| Index: sky/specs/modules.md
|
| diff --git a/sky/specs/modules.md b/sky/specs/modules.md
|
| index 691c761fa38721ae6f059f4a4f5cac1559f9d4b3..f20e0c7d70ee323270cf1ef12d1a914b208dbec4 100644
|
| --- a/sky/specs/modules.md
|
| +++ b/sky/specs/modules.md
|
| @@ -55,98 +55,65 @@ that were declared by that module except the aforementioned element
|
| tree library.
|
|
|
| At the end of the ``<script>`` block's source, if it parsed correctly
|
| -and completely, the following code is appended:
|
| +and completely, the conceptual equivalent of the following code is
|
| +appended (but without affecting the library's list of declarations and
|
| +without any possibility of it clashing with identifiers described in
|
| +the library itself):
|
|
|
| ```dart
|
| class _ { }
|
| -module.registerElements(reflectClass(_).owner);
|
| +void main() {
|
| + LibraryMirror library = reflectClass(_).owner as LibraryMirror;
|
| + if (library.declarations.containsKey(#init) && library.declarations[#init] is MethodMirror)
|
| + init();
|
| + module.init(library);
|
| +}
|
| ```
|
|
|
| +Then, that ``main()`` function is called.
|
| +
|
| TODO(ianh): decide what URL and name we should give the libraries, as
|
| exposed in MirrorSystem.getName(libraryMirror.qualifiedName) etc
|
|
|
| The ``Module`` class is defined in ``sky:core`` as follows:
|
|
|
| +```dart
|
|
|
| -TODO(ianh): dartification of the rest of this file
|
| -
|
| -### Exporting element definitions ###
|
| -
|
| -When importing a module into another, Sky runs the following steps:
|
| - - let export be the imported module's ``exports`` value
|
| - - try to import export
|
| - - if that fails:
|
| - - try to import each property of export
|
| -
|
| -"Try to import" a value means to run the following steps:
|
| - - if the value is an element constructor (generated by
|
| - ``registerElement()``), call this importer module's
|
| - ``registerElement()`` with the value
|
| -
|
| -### IDL ###
|
| -
|
| -```javascript
|
| -dictionary InternalElementOptions {
|
| - String tagName;
|
| - Boolean shadow = false;
|
| - Object prototype = Element;
|
| -}
|
| -interface InternalElementConstructorWithoutShadow {
|
| - constructor (Module hostModule);
|
| - attribute String tagName;
|
| -}
|
| -interface InternalElementConstructorWithShadow {
|
| - constructor (Module hostModule);
|
| - attribute String tagName;
|
| - attribute Boolean shadow;
|
| -}
|
| -typedef ElementRegistrationOptions (InternalElementOptions or
|
| - InternalElementConstructorWithoutShadow or
|
| - InternalElementConstructorWithShadow);
|
| -
|
| -abstract class AbstractModule : EventTarget {
|
| - readonly attribute Document document; // O(1) // the Document of the module or application
|
| - Promise<any> import(String url); // O(Yikes) // returns the module's exports
|
| - private Array<Module> getImports(); O(N) // returns the Module objects of all the imported modules
|
| -
|
| - readonly attribute String url;
|
| -
|
| - ElementConstructor registerElement(Object options); // O(1)
|
| - // if you call registerElement() with an object that was created by
|
| - // registerElement(), it just returns the object after registering it,
|
| - // rather than creating a new constructor
|
| - // otherwise, it proceeds as follows:
|
| - // - if options is a Function (i.e. it is either an
|
| - // InternalElementConstructorWithoutShadow object or an
|
| - // InternalElementConstructorWithShadow object), then let
|
| - // constructor be that function, and let prototype be that
|
| - // functions's prototype; otherwise, let constructor be a no-op
|
| - // function and let prototype be the prototype property of the
|
| - // object passed in (the InternalElementOptions; prototype
|
| - // defaults to Element).
|
| - // - let shadow be option's shadow property's value coerced to a
|
| - // boolean, if the property is present, or else the value false.
|
| - // - let tagName be option's tagName property's value.
|
| - // - create a new Function that acts as if it had the signature of
|
| - // the constructors in the ElementConstructor interface, and that
|
| - // runs the follows steps when called:
|
| - // - throw if not called as a constructor
|
| - // - create an actual element object (the C++-backed object)
|
| - // called tagName, along with the specified attributes
|
| - // - initialise the shadow tree if shadow is true
|
| - // - call constructor, if it's not null, with the module
|
| - // within which the new element is being constructed as the
|
| - // argument
|
| - // - append all the specified children
|
| - // - mark that new Function as created by registerElement() so that
|
| - // it can be recognised if used as an argument to
|
| - // registerElement()
|
| - // - let that new Function's prototype be the aforementioned prototype
|
| - // - let that new Function have tagName and shadow properties set to
|
| - // the aforementioned tagName and shadow
|
| - // - register the new tagName with this constructor
|
| - // - return the new Function (which is, not coincidentally, an
|
| - // InternalElementConstructorWithShadow)
|
| +abstract class AbstractModule extends EventTarget {
|
| + AbstractModule({this.document, this.url});
|
| +
|
| + final Document document; // O(1)
|
| + // the Document of the module or application
|
| +
|
| + final String url;
|
| +
|
| + @nonnull external Future<@nonnull Module> import(String url); // O(Yikes)
|
| + // load and return the URL at the given Module
|
| + // if it's already loaded, the future will resolve immediately
|
| + // if loading fails, the future will have an error
|
| +
|
| + @nonnull List</*@nonnull*/ Module> getImports(); // O(N)
|
| + // returns the Module objects of all the imported modules
|
| +
|
| + external registerElement(@nonnull String tagname, @nonnull Type elementClass); // O(1)
|
| + // registers a tag name with the parser
|
| + // only useful during parse time
|
| + // verify that tagname isn't null or empty
|
| + // verify that elementClass is the Type of a class that extends Element (directly or indirectly, but not via "implements" or "with")
|
| + // (see the @tagname code for an example of how to verify that from dart)
|
| + // verify that there's not already a class registered for this tag name
|
| + // if there is, then mark this tagname is broken, so that it acts as if it's not registered in the parser,
|
| + // and, if this is the first time it was marked broken, log a console message regarding the issue
|
| + // (mention the tag name but not the classes, so that it's not observable that this currently happens out of order)
|
| +
|
| + void init(LibraryMirror library) {
|
| + library.declarations.forEach((Symbol s, DeclarationMirror d) {
|
| + d.metadata.forEach((InstanceMirror i) {
|
| + if (i.reflectee is AutomaticMetadata)
|
| + i.reflectee.init(d, this);
|
| + });
|
| + });
|
| + }
|
| }
|
|
|
| class Module : AbstractModule {
|
|
|