MCPcopy Create free account
hub / github.com/marijnh/Eloquent-JavaScript / Sandbox

Class Sandbox

src/client/sandbox.mjs:19–266  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

17}
18
19export class Sandbox {
20 static async create(options) {
21 this.emptyPath = options.emptyPath || "./"
22 let frame = document.createElement("iframe")
23 frame.src = this.emptyPath + "empty.html"
24 if (options.place) {
25 options.place(frame)
26 } else {
27 frame.style.height = "0px"
28 frame.style.border = "none"
29 document.body.appendChild(frame)
30 }
31 await awaitEvent(frame, "load")
32
33 let box = new Sandbox(frame)
34 let scripts = (options.loadFiles || []).map(file => {
35 let script = box.win.document.createElement("script")
36 script.src = file
37 box.win.document.body.appendChild(script)
38 return awaitEvent(script, "load")
39 })
40 await Promise.all(scripts)
41 return box
42 }
43
44 constructor(frame) {
45 this.startedAt = null
46 this.extraSecs = 2
47 this.output = null
48 this.handleDeps = true
49
50 this.callbacks = {}
51 // Used to cancel existing events when new code is loaded
52 this.timeouts = []; this.intervals = []; this.frames = []
53 this.framePos = 0
54
55 // Loaded CommonJS modules
56 this.loaded = new Cached(name => resolved.compute(name).then(({name, code}) => this.evalModule(name, code)))
57
58 this.frame = frame
59 this.win = frame.contentWindow
60 this.setupEnv()
61
62 const resize = () => {
63 if (this.frame.style.display != "none") this.resizeFrame()
64 }
65 this.frame.addEventListener("load", resize)
66 let resizeTimeout = null
67 const scheduleResize = () => {
68 this.win.clearTimeout(resizeTimeout)
69 this.win.__setTimeout(resize, 200)
70 }
71 this.win.addEventListener("keydown", scheduleResize)
72 this.win.addEventListener("mousedown", scheduleResize)
73 }
74
75 async run(code, output) {
76 if (output) this.output = output

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected