| OLD | NEW |
| 1 Sky Module System | 1 Sky Module System |
| 2 ================= | 2 ================= |
| 3 | 3 |
| 4 This document describes the Sky module system. | 4 This document describes the Sky module system. |
| 5 | 5 |
| 6 Overview | 6 Overview |
| 7 -------- | 7 -------- |
| 8 | 8 |
| 9 The Sky module system is based on the ``import`` element. In its | 9 The Sky module system is based on the ``import`` element. In its |
| 10 most basic form, you import a module as follows: | 10 most basic form, you import a module as follows: |
| 11 | 11 |
| 12 ```html | 12 ```html |
| 13 <import src="path/to/module.sky" /> | 13 <import src="path/to/module.sky" /> |
| 14 ``` | 14 ``` |
| 15 | 15 |
| 16 As these ``import`` elements are inserted into a document, the | 16 As these ``import`` elements are inserted into a document, the |
| 17 document's list of outstanding dependencies grows. When an imported | 17 document's list of outstanding dependencies grows. When an imported |
| 18 module completes, it is removed from the document's list of | 18 module completes, it is removed from the document's list of |
| 19 outstanding dependencies. | 19 outstanding dependencies. |
| 20 | 20 |
| 21 Before compiling script or inserting an element that is not already | 21 Before compiling script or inserting an element that is not already |
| 22 registered, the parser waits until the list of outstanding | 22 registered, the parser waits until the list of outstanding |
| 23 dependencies is empty. After the parser has finished parsing, the | 23 dependencies is empty. After the parser has finished parsing, the |
| 24 document waits until its list of outstanding dependencies is empty | 24 document waits until its list of outstanding dependencies is empty |
| 25 before the module it represents is marked complete. | 25 before the module it represents is marked complete. |
| 26 | 26 |
| 27 The ``as`` attribute on the ``import`` element binds a name to the |
| 28 imported module: |
| 29 |
| 30 ```html |
| 31 <import src="path/to/chocolate.sky" as="chocolate" /> |
| 32 ``` |
| 33 |
| 27 | 34 |
| 28 Module API | 35 Module API |
| 29 ---------- | 36 ---------- |
| 30 | 37 |
| 31 Each module consists of one or more libraries. The first library in a | 38 Each module consists of one or more libraries. The first library in a |
| 32 module is the *element tree library*, which imports the sky:core | 39 module is the *element tree library*, which imports the sky:core |
| 33 module and then consists of the following code for a Sky module: | 40 module and then consists of the following code for a Sky module: |
| 34 | 41 |
| 35 ```dart | 42 ```dart |
| 36 final Module module = new Module(); | 43 final Module module = new Module(); |
| 37 ``` | 44 ``` |
| 38 | 45 |
| 39 ...and the following code for a Sky application: | 46 ...and the following code for a Sky application: |
| 40 | 47 |
| 41 ```dart | 48 ```dart |
| 42 final Module module = new Application(); | 49 final Module module = new Application(); |
| 43 ``` | 50 ``` |
| 44 | 51 |
| 45 The ``<script>`` elements found in the document create the subsequent | 52 The ``<script>`` elements found in the document create the subsequent |
| 46 libraries. Each one first imports the ``dart:mirror`` library, then | 53 libraries. Each one first imports the ``dart:mirror`` library, then |
| 47 the ``sky:core`` module, then the first library described above, then | 54 the ``sky:core`` module, then the first library described above, then |
| 48 all the modules referenced by ``<import>`` element up to that | 55 all the modules referenced by ``<import>`` element up to that |
| 49 ``<script>`` element and all the libraries defined by ``<script>`` | 56 ``<script>`` element and all the libraries defined by ``<script>`` |
| 50 elements up to that point, interleaved so as to maintain the same | 57 elements up to that point, interleaved so as to maintain the same |
| 51 relative order as those elements were first seen by the parser. | 58 relative order as those elements were first seen by the parser. |
| 52 | 59 |
| 53 When a library imports a module, it actually imports all the libraries | 60 When a library imports a module, it actually imports all the libraries |
| 54 that were declared by that module except the aforementioned element | 61 that were declared by that module except the aforementioned element |
| 55 tree library. | 62 tree library. If the ``as`` attribute is present on the ``import`` |
| 63 element, all the libraries are bound to the same name. |
| 56 | 64 |
| 57 At the end of the ``<script>`` block's source, if it parsed correctly | 65 At the end of the ``<script>`` block's source, if it parsed correctly |
| 58 and completely, the conceptual equivalent of the following code is | 66 and completely, the conceptual equivalent of the following code is |
| 59 appended (but without affecting the library's list of declarations and | 67 appended (but without affecting the library's list of declarations and |
| 60 without any possibility of it clashing with identifiers described in | 68 without any possibility of it clashing with identifiers described in |
| 61 the library itself): | 69 the library itself): |
| 62 | 70 |
| 63 ```dart | 71 ```dart |
| 64 class _ { } | 72 class _ { } |
| 65 void main() { | 73 void main() { |
| 66 LibraryMirror library = reflectClass(_).owner as LibraryMirror; | 74 LibraryMirror library = reflectClass(_).owner as LibraryMirror; |
| 67 if (library.declarations.containsKey(#init) && library.declarations[#init] is
MethodMirror) | 75 if (library.declarations.containsKey(#init) && library.declarations[#init] is
MethodMirror) |
| 68 init(); | 76 init(); |
| 69 AutomaticMetadata.runLibrary(library, module); | 77 AutomaticMetadata.runLibrary(library, module); |
| 70 } | 78 } |
| 71 ``` | 79 ``` |
| 72 | 80 |
| 73 Then, that ``main()`` function is called. | 81 Then, that ``main()`` function is called. |
| 74 | 82 |
| 75 TODO(ianh): decide what URL and name we should give the libraries, as | 83 TODO(ianh): decide what URL and name we should give the libraries, as |
| 76 exposed in MirrorSystem.getName(libraryMirror.qualifiedName) etc | 84 exposed in MirrorSystem.getName(libraryMirror.qualifiedName) etc |
| 77 | 85 |
| 78 The ``Module`` class is defined in ``sky:core`` as follows: | 86 The ``Module`` class is defined in ``sky:core`` as follows: |
| 79 | 87 |
| 80 ```dart | 88 ```dart |
| 81 | |
| 82 abstract class AbstractModule extends EventTarget { | 89 abstract class AbstractModule extends EventTarget { |
| 83 AbstractModule({this.document, this.url}); | 90 AbstractModule({this.url, this.elements}); |
| 84 | |
| 85 final Document document; // O(1) | |
| 86 // the Document of the module or application | |
| 87 | 91 |
| 88 final String url; | 92 final String url; |
| 89 | 93 |
| 90 @nonnull external Future<@nonnull Module> import(String url); // O(Yikes) | 94 final Root elements; // O(1) |
| 95 // the Root node of the module or application's element tree |
| 96 |
| 97 external Future<Module> import(String url); // O(Yikes) |
| 91 // load and return the URL at the given Module | 98 // load and return the URL at the given Module |
| 92 // if it's already loaded, the future will resolve immediately | 99 // if it's already loaded, the future will resolve immediately |
| 93 // if loading fails, the future will have an error | 100 // if loading fails, the future will have an error |
| 94 | 101 |
| 95 @nonnull List</*@nonnull*/ Module> getImports(); // O(N) | 102 List<Module> getImports(); // O(N) |
| 96 // returns the Module objects of all the imported modules | 103 // returns the Module objects of all the imported modules |
| 97 | 104 |
| 98 external registerElement(@nonnull String tagname, @nonnull Type elementClass);
// O(1) | 105 external registerElement(String tagname, Type elementClass); // O(1) |
| 99 // registers a tag name with the parser | 106 // registers a tag name with the parser |
| 100 // only useful during parse time | 107 // only useful during parse time |
| 101 // verify that tagname isn't null or empty | 108 // verify that tagname isn't null or empty |
| 102 // verify that elementClass is the Type of a class that extends Element (direc
tly or indirectly, but not via "implements" or "with") | 109 // verify that elementClass is the Type of a class that extends Element (direc
tly or indirectly, but not via "implements" or "with") |
| 103 // (see the @tagname code for an example of how to verify that from dart) | 110 // (see the @tagname code for an example of how to verify that from dart) |
| 104 // verify that there's not already a class registered for this tag name | 111 // verify that there's not already a class registered for this tag name |
| 105 // if there is, then mark this tagname is broken, so that it acts as if it's n
ot registered in the parser, | 112 // if there is, then mark this tagname is broken, so that it acts as if it's n
ot registered in the parser, |
| 106 // and, if this is the first time it was marked broken, log a console message
regarding the issue | 113 // and, if this is the first time it was marked broken, log a console message
regarding the issue |
| 107 // (mention the tag name but not the classes, so that it's not observable that
this currently happens out of order) | 114 // (mention the tag name but not the classes, so that it's not observable that
this currently happens out of order) |
| 108 } | 115 } |
| 109 | 116 |
| 110 class Module : AbstractModule { | 117 class Module extends AbstractModule { |
| 111 constructor (Application application, Document document, String url); // O(1) | 118 Module({String url, Root elements, this.application}) : |
| 112 readonly attribute Application application; // O(1) | 119 super(url: url, elements: elements); // O(1) |
| 120 final Application application; // O(1) |
| 113 } | 121 } |
| 114 | 122 |
| 115 class Application : AbstractModule { | 123 class Application extends AbstractModule { |
| 116 constructor (Document document, GestureManager gestureManager, String url); //
O(1) | 124 Application({String url, Root elements, this.gestureManager}) : |
| 117 attribute String title; // O(1) | 125 super(url: url, elements: elements); // O(1) |
| 118 readonly attribute GestureManager gestureManager; | 126 external String get title; // O(1) |
| 127 external void set title(String newValue); // O(1) |
| 128 final GestureManager gestureManager; |
| 119 } | 129 } |
| 120 ``` | 130 ``` |
| 121 | |
| 122 | |
| 123 Naming modules | |
| 124 -------------- | |
| 125 | |
| 126 The ``as`` attribute on the ``import`` element binds a name to the | |
| 127 imported module: | |
| 128 | |
| 129 ```html | |
| 130 <import src="path/to/chocolate.sky" as="chocolate" /> | |
| 131 ``` | |
| 132 | |
| 133 The parser executes the contents of script elements inside a module as | |
| 134 if they were executed as follow: | |
| 135 | |
| 136 ```javascript | |
| 137 (new Function(name_1, ..., name_n, module, source_code)).call( | |
| 138 value_1, ..., value_n, source_module); | |
| 139 ``` | |
| 140 | |
| 141 Where ``name_1`` through ``name_n`` are the names bound to the | |
| 142 various named imports in the script element's document, | |
| 143 ``source_code`` is the text content of the script element, | |
| 144 ``source_module`` is the ``Module`` object of the script element's | |
| 145 module, and ``value_1`` through ``value_n`` are the values | |
| 146 exported by the various named imports in the script element's | |
| 147 document. | |
| 148 | |
| 149 When an import fails to load, the ``as`` name for the import gets | |
| 150 bound to ``undefined``. | |
| OLD | NEW |