Skip to content

Commit 64564af

Browse files
committed
Implement SystemJS resource loading (partially).
1 parent 5108948 commit 64564af

File tree

15 files changed

+5500
-204
lines changed

15 files changed

+5500
-204
lines changed

packages/webio/dist/blink.bundle.js

Lines changed: 2555 additions & 67 deletions
Large diffs are not rendered by default.

packages/webio/dist/blink.bundle.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/webio/dist/mux.bundle.js

Lines changed: 2554 additions & 96 deletions
Large diffs are not rendered by default.

packages/webio/dist/mux.bundle.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/webio/package-lock.json

Lines changed: 83 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/webio/package.json

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,22 @@
1010
},
1111
"dependencies": {
1212
"@babel/core": "^7.1.2",
13+
"@babel/plugin-syntax-dynamic-import": "^7.0.0",
1314
"@babel/polyfill": "^7.0.0",
1415
"@babel/runtime": "^7.1.2",
1516
"@types/debug": "0.0.30",
16-
"debug": "^4.0.1"
17+
"@types/scriptjs": "0.0.2",
18+
"@types/systemjs": "^0.20.6",
19+
"debug": "^4.0.1",
20+
"scriptjs": "^2.5.9",
21+
"systemjs": "^0.20.19"
1722
},
1823
"devDependencies": {
19-
"babel-loader": "^8.0.4",
2024
"@babel/preset-env": "^7.1.0",
25+
"babel-loader": "^8.0.4",
2126
"ts-loader": "^5.2.1",
2227
"tsc": "^1.20150623.0",
28+
"tslint": "^5.11.0",
2329
"typescript": "^3.1.1",
2430
"webpack": "^4.6",
2531
"webpack-cli": "^2.1"

packages/webio/src/Node.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,24 @@ export interface WebIONodeParams {
5252
* applied to it.
5353
*/
5454
abstract class WebIONode {
55+
/**
56+
* The actual DOM element associated with this node.
57+
*/
5558
abstract readonly element: WebIODomElement;
56-
abstract children: Array<WebIOScope | WebIODomNode | string>;
59+
60+
/**
61+
* An array of children (or null if not yet initialized).
62+
*/
63+
abstract children: Array<WebIOScope | WebIODomNode | string> | null;
64+
65+
/**
66+
* The closest-ancestor scope associated with this node.
67+
*/
5768
readonly scope?: WebIOScope;
69+
70+
/**
71+
* The top-level WebIO instance associated with this node.
72+
*/
5873
readonly webIO: WebIO;
5974

6075
protected constructor(

packages/webio/src/Scope.ts

Lines changed: 62 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import createLogger from "debug";
2+
import System from "systemjs";
23
const debug = createLogger("WebIO:Scope");
34

45
import WebIONode, {WebIONodeDataBase, WebIONodeParams, WebIONodeType} from "./Node";
@@ -8,6 +9,7 @@ import {WebIOCommand, WebIOMessage} from "./message";
89
import {createWebIOEventListener} from "./events";
910
import WebIODomNode from "./DomNode";
1011
import createNode from "./createNode";
12+
import {BlockImport, importBlock} from "./imports";
1113

1214
/**
1315
* A map of observable names to arrays-of-listeners that should be
@@ -22,7 +24,7 @@ export interface ScopeListeners {
2224
}
2325

2426
export interface ScopePromises {
25-
importsLoaded: Promise<void>; // TODO
27+
importsLoaded: Promise<any[] | null>;
2628
connected: Promise<WebIOScope>;
2729
}
2830

@@ -70,14 +72,26 @@ export interface ScopeNodeData extends WebIONodeDataBase {
7072
handlers?: {
7173
[observableName: string]: string[];
7274
};
75+
76+
imports?: BlockImport;
7377
}
7478
}
7579

80+
/**
81+
* Handlers that are associated with the scope promises.
82+
*
83+
* @todo This needs to be refactored.
84+
*/
85+
export interface PromiseHandlers {
86+
importsLoaded?: string; // (imports: any[] | null) => void;
87+
// TODO: other promise handlers?
88+
}
89+
7690
class WebIOScope extends WebIONode {
7791

7892
readonly id: string;
7993
readonly element: HTMLDivElement;
80-
children: Array<WebIOScope | WebIODomNode | string>;
94+
children: Array<WebIOScope | WebIODomNode | string> | null = null;
8195
handlers: ScopeListeners;
8296
observables: {[observableName: string]: WebIOObservable};
8397
promises: ScopePromises;
@@ -96,40 +110,62 @@ class WebIOScope extends WebIONode {
96110
const {id, observables = {}, handlers = {}} = scopeData.instanceArgs;
97111
this.id = id;
98112

113+
// Create WebIOObservables.
99114
this.observables = {};
100115
Object.keys(observables).forEach((name) => {
101116
this.observables[name] = new WebIOObservable(name, observables[name], this);
102117
});
103118

104-
// Map the function strings into handlers which have `this` bound to the scope's
105-
// element and which have access to the _webIOScope variable (via closure).
106119
this.handlers = {};
107-
Object.keys(handlers).forEach((observableName) => {
120+
121+
// TODO: refactor registerScope as described elsewhere
122+
this.webIO.registerScope(this);
123+
124+
// TODO: refactor way initialization/import promises are done
125+
const initializationPromise = this.initialize(scopeData);
126+
127+
this.promises = {
128+
connected: this.webIO.connected.then(() => this),
129+
importsLoaded: initializationPromise,
130+
};
131+
132+
this.setupScope();
133+
}
134+
135+
/**
136+
* Perform asynchronous initialization tasks.
137+
*/
138+
private async initialize(scopeData: ScopeNodeData) {
139+
const {handlers = {}, imports} = scopeData.instanceArgs;
140+
141+
// (Asynchronously) perform dependency initialization
142+
const {preDependencies = [], _promises = {}, ...restHandlers} = handlers;
143+
preDependencies
144+
.map((functionString) => createWebIOEventListener(this.element, functionString, this))
145+
.forEach((handler) => handler.call(this))
146+
;
147+
148+
// Map the function strings into handlers which have `this` bound to the scope's
149+
// element and which have access to the _webIOScope resources variable (via closure).
150+
Object.keys(restHandlers).forEach((observableName) => {
108151
this.handlers[observableName] = handlers[observableName].map((handlerString) => {
109152
return createWebIOEventListener(this.element, handlerString, this);
110153
});
111154
});
112155

113-
// TODO
114-
this.promises = null as any;
156+
const resources = imports ? await importBlock(imports) : null;
115157

116-
this.webIO.registerScope(this);
158+
// TypeScript hackery to deal with out promiseHandlers is a very special case
159+
const {importsLoaded: importsLoadedHandler} = _promises as any as PromiseHandlers;
160+
if (resources && importsLoadedHandler) {
161+
// `as any` necessary because createWebIOEventListener normally returns
162+
// a function which is expected to be an event listener... but this is kind of a
163+
// special case of that.
164+
debug("Invoking importsLoaded Scope handler.", {importsLoadedHandler, resources});
165+
(createWebIOEventListener(this.element, importsLoadedHandler, this) as any)(...resources);
166+
}
117167

118-
// this.node = node;
119-
// this.handlers = handlers;
120-
// this.observables = observables;
121-
//
122-
// // (Asynchronously) perform dependency initialization
123-
// const {preDependencies = []} = this.handlers;
124-
// preDependencies.forEach((handler) => handler.call(this));
125-
// const importsLoaded = Promise.resolve(); // TODO
126-
//
127-
// // (Asynchronously) connect to the WebIO Julia machinery
128-
// const connected = this.connect().then(() => this);
129-
//
130-
// this.promises = {importsLoaded, connected};
131-
132-
// Create children and append to this node's element.
168+
// Finally, create children.
133169
this.children = scopeData.children.map((nodeData) => {
134170
if (typeof nodeData === "string") {
135171
return nodeData;
@@ -144,7 +180,9 @@ class WebIOScope extends WebIONode {
144180
}
145181
}
146182

147-
this.setupScope();
183+
// This isn't super clean, but this function is used to create the
184+
// importsLoaded promise, so we need to return the promises.
185+
return resources;
148186
}
149187

150188
getObservableValue(observable: ObservableSpecifier) {

0 commit comments

Comments
 (0)