Skip to content

Commit 69a24f8

Browse files
committed
Replace callback w/ promise in sandbox code
1 parent cc3afc2 commit 69a24f8

File tree

3 files changed

+59
-51
lines changed

3 files changed

+59
-51
lines changed

html/js/code.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,20 +168,20 @@ addEventListener("load", function() {
168168
function runCode() {
169169
clearSandbox();
170170
var val = editor.getValue(), type = context.type || guessType(val);
171-
sandbox = new SandBox({
171+
SandBox.create({
172172
loadFiles: hasIncludes(val, context.include) ? [] : context.include,
173173
place: type == "html" &&
174174
function(node) {
175175
var out = document.querySelector(".sandbox-output");
176176
out.parentNode.insertBefore(node, out);
177177
}
178-
}, function(box) {
178+
}.then(box => {
179179
output.clear();
180180
if (type == "html")
181181
box.setHTML(val, output);
182182
else
183183
box.run(val, output);
184-
});
184+
})
185185
}
186186

187187
document.querySelector("#solution").addEventListener("click", function() {

html/js/ejs.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,12 +196,12 @@ window.addEventListener("load", function() {
196196
options.place = function(node) { placeFrame(node, snippet); };
197197
if (!forHTML) html = snippet.textContent;
198198
}
199-
new SandBox(options, function(box) {
199+
SandBox.create(options).then(box => {
200200
if (html != null)
201201
box.win.document.documentElement.innerHTML = html;
202202
sandboxes[name] = box;
203203
callback(box);
204-
});
204+
})
205205
}
206206

207207
function resetSandbox(name) {

html/js/sandbox.js

Lines changed: 54 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -17,60 +17,60 @@
1717
}
1818

1919
let SandBox = window.SandBox = class {
20-
constructor(options, callback) {
21-
this.callbacks = {}
20+
static create(options) {
21+
return new Promise(done => {
22+
let frame = document.createElement("iframe")
23+
frame.addEventListener("load", loaded)
24+
frame.src = "empty.html"
25+
if (options.place) {
26+
options.place(frame)
27+
} else {
28+
frame.style.display = "none"
29+
document.body.appendChild(frame)
30+
}
31+
32+
function loaded() {
33+
frame.removeEventListener("load", loaded)
34+
let box = new SandBox(options, frame)
2235

36+
promiseChain((options.loadFiles || []).map(file => () => {
37+
let script = box.win.document.createElement("script")
38+
script.src = file
39+
box.win.document.body.appendChild(script)
40+
return new Promise(done => script.addEventListener("load", done))
41+
})).then(() => done(box))
42+
}
43+
})
44+
}
45+
46+
constructor(options, frame) {
47+
this.startedAt = null
48+
this.extraSecs = 2
49+
this.output = null
50+
51+
this.callbacks = {}
2352
// Used to cancel existing events when new code is loaded
24-
this.timeouts = []; this.intervals = []; this.frames = []; this.framePos = 0
53+
this.timeouts = []; this.intervals = []; this.frames = []
54+
this.framePos = 0
2555

56+
// Loaded CommonJS modules
2657
this.loaded = new Cached(name => resolved.compute(name).then(({name, code}) => this.evalModule(name, code)))
2758

28-
const loaded = () => {
29-
frame.removeEventListener("load", loaded)
30-
this.win = frame.contentWindow
31-
this.setupEnv()
59+
this.frame = frame
60+
this.win = frame.contentWindow
61+
this.setupEnv()
3262

33-
const resize = () => {
34-
if (this.frame.style.display != "none") this.resizeFrame()
35-
}
36-
this.frame.addEventListener("load", resize)
37-
let resizeTimeout = null
38-
const scheduleResize = () => {
39-
this.win.clearTimeout(resizeTimeout)
40-
this.win.__setTimeout(resize, 200)
41-
}
42-
this.win.addEventListener("keydown", scheduleResize)
43-
this.win.addEventListener("mousedown", scheduleResize)
44-
45-
if (options.loadFiles) {
46-
let i = 0
47-
let loadNext = () => {
48-
if (i == options.loadFiles.length) return callback(this)
49-
let script = this.win.document.createElement("script")
50-
script.src = options.loadFiles[i]
51-
this.win.document.body.appendChild(script)
52-
++i
53-
script.addEventListener("load", loadNext)
54-
}
55-
loadNext()
56-
} else {
57-
callback(this)
58-
}
63+
const resize = () => {
64+
if (this.frame.style.display != "none") this.resizeFrame()
5965
}
60-
61-
let frame = this.frame = document.createElement("iframe")
62-
frame.addEventListener("load", loaded)
63-
frame.src = "empty.html"
64-
if (options.place) {
65-
options.place(frame)
66-
} else {
67-
frame.style.display = "none"
68-
document.body.appendChild(frame)
66+
this.frame.addEventListener("load", resize)
67+
let resizeTimeout = null
68+
const scheduleResize = () => {
69+
this.win.clearTimeout(resizeTimeout)
70+
this.win.__setTimeout(resize, 200)
6971
}
70-
71-
this.startedAt = null
72-
this.extraSecs = 2
73-
this.output = null
72+
this.win.addEventListener("keydown", scheduleResize)
73+
this.win.addEventListener("mousedown", scheduleResize)
7474
}
7575

7676
run(code, output) {
@@ -531,4 +531,12 @@
531531
wrap.appendChild(document.createTextNode(type == "array" ? "]" : "}"))
532532
node.parentNode.replaceChild(wrap, node)
533533
}
534+
535+
function promiseChain(thunks) {
536+
function proceed(i, value) {
537+
if (i == thunks.length) return Promise.resolve(value)
538+
else return thunks[i](value).then(value => proceed(i + 1, value))
539+
}
540+
return proceed(0, null)
541+
}
534542
})()

0 commit comments

Comments
 (0)