Skip to content

Commit

Permalink
Iframe webworker: avoid using toString as tranpiled code was erroring (
Browse files Browse the repository at this point in the history
  • Loading branch information
AquiGorka authored Jun 14, 2019
1 parent 1ef6ec2 commit c49ed53
Showing 1 changed file with 44 additions and 41 deletions.
85 changes: 44 additions & 41 deletions src/iframe-worker.js
Original file line number Diff line number Diff line change
@@ -1,40 +1,3 @@
import { getObjectUrlForScript, fetchScriptUrlAsBlob } from './worker-utils'

const init = async (scriptUrl, name, getObjectUrlForScript) => {
let workerUrl = ''
try {
// WebWorkers can only load scripts from the local origin, so we
// have to fetch the script (from an IPFS gateway) and process it locally.
//
// Note that we **SHOULD** use a data url, to ensure the Worker is
// created with an opaque ("orphaned") origin, see
// https://html.spec.whatwg.org/multipage/workers.html#dom-worker.
//
// The opaque origin is a necessary part of creating the WebWorker sandbox;
// even though the script never has access to the DOM or local storage, it can
// still access global features like IndexedDB if it is not enclosed in an
// opaque origin.
workerUrl = await getObjectUrlForScript(scriptUrl)
} catch (e) {
console.error(`Failed to load ${name}'s script (${scriptUrl}): e`)
return
}
const worker = new Worker(workerUrl, { name })
worker.addEventListener(
'error',
error => window.parent.postMessage({ from: name, error }, '*'),
false
)
worker.addEventListener(
'message',
event => window.parent.postMessage({ from: name, msg: event.data }, '*'),
false
)
window.addEventListener('message', ({ data }) => worker.postMessage(data))
// Clean up the url we created to spawn the worker
URL.revokeObjectURL(workerUrl)
}

class IframeWorker extends EventTarget {
constructor(scriptUrl, { name }) {
super()
Expand All @@ -46,10 +9,50 @@ class IframeWorker extends EventTarget {

const source = `
<script>
const getObjectUrlForScript = ${getObjectUrlForScript.toString()}
const fetchScriptUrlAsBlob = ${fetchScriptUrlAsBlob.toString()}
const init = ${init.toString()}
init('${scriptUrl}', '${name}', getObjectUrlForScript)
const fetchScriptUrlAsBlob = async url => {
// In the future, we might support IPFS protocols in addition to http
const res = await fetch(url, {
method: 'GET',
mode: 'cors',
})
// If status is not a 2xx (based on Response.ok), assume it's an error
// See https://developer.mozilla.org/en-US/docs/Web/API/GlobalFetch/fetch
if (!(res && res.ok)) {
throw res
}
return res.blob()
}
async function getObjectUrlForScript(scriptUrl) {
const blob = await fetchScriptUrlAsBlob(scriptUrl)
return URL.createObjectURL(blob)
}
const init = async () => {
let workerUrl = ''
try {
// WebWorkers can only load scripts from the local origin, so we
// have to fetch the script (from an IPFS gateway) and process it locally.
//
// Note that we **SHOULD** use a data url, to ensure the Worker is
// created with an opaque ("orphaned") origin, see
// https://html.spec.whatwg.org/multipage/workers.html#dom-worker.
//
// The opaque origin is a necessary part of creating the WebWorker sandbox;
// even though the script never has access to the DOM or local storage, it can
// still access global features like IndexedDB if it is not enclosed in an
// opaque origin.
workerUrl = await getObjectUrlForScript('${scriptUrl}')
} catch (e) {
console.error("Failed to load ${name}'s script (${scriptUrl}): ", e)
return
}
const worker = new Worker(workerUrl, { name: '${name}' })
worker.addEventListener('error', error => window.parent.postMessage({ from: '${name}', error }, '*'), false)
worker.addEventListener('message', event => window.parent.postMessage({ from: '${name}', msg: event.data }, '*'), false)
window.addEventListener('message', ({ data }) => worker.postMessage(data))
// Clean up the url we created to spawn the worker
URL.revokeObjectURL(workerUrl)
}
init()
</script>
`
this.iframe.srcdoc = source
Expand Down

1 comment on commit c49ed53

@ottodevs
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing catch, this was getting me mad!
I will try the changes tomorrow but it definitely seems promising by looking at the code :)

Thank you very much @AquiGorka

Please sign in to comment.