Kill `bootstrap.js`, load the WASM ourselves.
Instead of forcing a chunk load on Webpack just so we can have Webpack prepare the WASM for us, we're now using the `no-modules` mode of `wasm-pack` manually and loading the resulting files ourselves. I still have to force Ruffle to load outside of the extension sandbox though...
This commit is contained in:
parent
7c6ad57443
commit
8060802465
|
@ -0,0 +1,8 @@
|
|||
#!/bin/bash
|
||||
|
||||
#Really hacky way to build everything until I figure out how to get a better/
|
||||
#dependency-respecting build system going
|
||||
|
||||
rm -r dist
|
||||
wasm-pack build --target=no-modules --out-dir=extension/dist ..
|
||||
npx webpack
|
|
@ -1,7 +0,0 @@
|
|||
__webpack_public_path__ = window.__webpack_public_path__;
|
||||
|
||||
// A dependency graph that contains any wasm must all be imported
|
||||
// asynchronously. This `bootstrap.js` file does the single async import, so
|
||||
// that no one else needs to worry about it again.
|
||||
import("./index.js")
|
||||
.catch(e => console.error("Error importing `index.js`:", e));
|
|
@ -1,28 +1,28 @@
|
|||
/**
|
||||
* This IIFE is *not touched by Webpack* and exists primarily to ensure Webpack
|
||||
* is loaded without extension privileges.
|
||||
(/**
|
||||
* Pierce the extension sandbox by copying our code into window space.
|
||||
*
|
||||
* Inside the IIFE, we do two things:
|
||||
* The isolation extension content scripts get is neat, but it causes problems
|
||||
* based on what browser you use:
|
||||
*
|
||||
* 1. Use our fancy extension powers to generate an unprivileged script to set
|
||||
* the webpack public path.
|
||||
* 2. Generate another unprivileged script with a link to the Ruffle extension
|
||||
* resource.
|
||||
* 1. On Chrome, you are explicitly banned from registering custom elements
|
||||
* 2. On Firefox, you can register custom elements but they can't expose any
|
||||
* useful API surface, and can't even see their own methods.
|
||||
*
|
||||
* This gives webpack the environment it expects, at the expense of breaking
|
||||
* literally every site that uses it's own webpack.
|
||||
* This code exists to pierce the extension sandbox, while maintaining:
|
||||
*
|
||||
* 1. The isolation of not interfering with the page's execution environment
|
||||
* unintentionally.
|
||||
* 2. The ability to load extension resources such as .wasm files
|
||||
*/
|
||||
(function () {
|
||||
// Browser extensions are loaded from a dynamically-generated URL, we have to
|
||||
// tell webpack about that.
|
||||
|
||||
var webpack_path_script = document.createElement('script');
|
||||
webpack_path_script.appendChild(document.createTextNode("__webpack_public_path__ = \"" + browser.runtime.getURL("dist/0.ruffle.js").replace("0.ruffle.js", "") + "\""));
|
||||
webpack_path_script.type = "text/javascript";
|
||||
document.body.appendChild(webpack_path_script);
|
||||
|
||||
var script = document.createElement('script');
|
||||
script.src = browser.runtime.getURL("dist/ruffle.js");
|
||||
script.type = "text/javascript";
|
||||
document.body.appendChild(script);
|
||||
async function() {
|
||||
let ext_path = browser.runtime.getURL("dist/ruffle.js").replace("dist/ruffle.js", "");
|
||||
let ruffle_src_resp = await fetch(ext_path + "dist/ruffle.js");
|
||||
if (ruffle_src_resp.ok) {
|
||||
let ruffle_src = "(function () { var runtime_path = \"" + ext_path + "\";\n" + await ruffle_src_resp.text() + "}())";
|
||||
let scriptelem = document.createElement("script");
|
||||
scriptelem.appendChild(document.createTextNode(ruffle_src));
|
||||
document.head.appendChild(scriptelem);
|
||||
} else {
|
||||
console.error("Critical error loading Ruffle into page")
|
||||
}
|
||||
}());
|
|
@ -1,5 +1,4 @@
|
|||
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
|
||||
const WasmPackPlugin = require("@wasm-tool/wasm-pack-plugin");
|
||||
const webpack = require('webpack');
|
||||
const path = require('path');
|
||||
|
||||
|
@ -12,19 +11,12 @@ module.exports = (env, argv) => {
|
|||
console.log(`Building ${mode}...`);
|
||||
|
||||
return {
|
||||
entry: path.resolve(__dirname, "js/bootstrap.js"),
|
||||
entry: path.resolve(__dirname, "js/index.js"),
|
||||
output: {
|
||||
path: path.resolve(__dirname, "dist"),
|
||||
filename: "ruffle.js",
|
||||
},
|
||||
mode: mode,
|
||||
plugins: [
|
||||
new CleanWebpackPlugin(),
|
||||
new WasmPackPlugin({
|
||||
crateDirectory: path.resolve(__dirname, ".."),
|
||||
extraArgs: "--out-name=ruffle",
|
||||
forceMode: mode,
|
||||
})
|
||||
]
|
||||
plugins: []
|
||||
}
|
||||
};
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
/**
|
||||
* Conditional ruffle loader
|
||||
*/
|
||||
|
||||
/**
|
||||
* Load ruffle from an automatically-detected location.
|
||||
*
|
||||
* This function returns a new instance of Ruffle and downloads it every time.
|
||||
* You should not use it directly; this module will memoize the resource
|
||||
* download.
|
||||
*/
|
||||
async function fetch_ruffle() {
|
||||
let ruffle_bindings_url = "ruffle_web.js";
|
||||
let ruffle_wasm_url = "ruffle_web_bg.wasm";
|
||||
|
||||
//Detect if we are executiong in a webextension context.
|
||||
//If so, download Ruffle from the URL the browser gives us.
|
||||
if (runtime_path) {
|
||||
ruffle_bindings_url = runtime_path + "dist/ruffle_web.js";
|
||||
ruffle_wasm_url = runtime_path + "dist/ruffle_web_bg.wasm";
|
||||
}
|
||||
|
||||
//We load the wasm package early so that both requests are parallelized.
|
||||
//This won't be awaited by us at all.
|
||||
let ruffle_wasm_request = fetch(ruffle_wasm_url);
|
||||
|
||||
//One point of admin: `wasm-pack`, in no-modules mode, stores it's bindings
|
||||
//straight in `window`, which we don't want. We grab whatever was in Window
|
||||
//before loading in the module so we can replace what was there.
|
||||
let ruffle_bindings_request = await fetch(ruffle_bindings_url);
|
||||
let ruffle_bindings_src = await ruffle_bindings_request.text();
|
||||
let noconflict_wasm_bindgen = window.wasm_bindgen;
|
||||
(new Function(ruffle_bindings_src))();
|
||||
let ruffle_wasm_bindgen = window.wasm_bindgen;
|
||||
window.wasm_bindgen = noconflict_wasm_bindgen;
|
||||
|
||||
//Next step: Actually initialize our bindings.
|
||||
let ruffle_wasm_response = await ruffle_wasm_request;
|
||||
let ruffle_wasm_data = await ruffle_wasm_response.arrayBuffer();
|
||||
let ruffle_bindings = await ruffle_wasm_bindgen(ruffle_wasm_data).catch(function (e) {
|
||||
console.error(e);
|
||||
});
|
||||
|
||||
return ruffle_wasm_bindgen.Ruffle;
|
||||
}
|
||||
|
||||
let last_loaded_ruffle = null;
|
||||
|
||||
/**
|
||||
* Obtain an instance of `Ruffle`.
|
||||
*
|
||||
* This function returns a promise which yields `Ruffle` asynchronously.
|
||||
*/
|
||||
export default function load_ruffle() {
|
||||
if (last_loaded_ruffle == null) {
|
||||
last_loaded_ruffle = fetch_ruffle();
|
||||
}
|
||||
|
||||
return last_loaded_ruffle;
|
||||
}
|
|
@ -8,7 +8,7 @@ export default class RuffleEmbed extends RufflePlayer {
|
|||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.stream_swf_url(this.attributes.src.value);
|
||||
super.stream_swf_url(this.attributes.src.value);
|
||||
}
|
||||
|
||||
get src() {
|
||||
|
@ -24,8 +24,10 @@ export default class RuffleEmbed extends RufflePlayer {
|
|||
}
|
||||
|
||||
attributeChangedCallback(name, oldValue, newValue) {
|
||||
//TODO: We get a double play if we just naively load this twice.
|
||||
//Check if the element is connected before doing anything!
|
||||
if (name === "src") {
|
||||
this.stream_swf_url(this.attributes.src.value);
|
||||
//this.stream_swf_url(this.attributes.src.value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ export default class RuffleObject extends RufflePlayer {
|
|||
|
||||
//Kick off the SWF download.
|
||||
if (this.params.movie) {
|
||||
this.stream_swf_url(this.params.movie);
|
||||
super.stream_swf_url(this.params.movie);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Ruffle } from "../pkg/ruffle";
|
||||
import load_ruffle from "./load-ruffle";
|
||||
import ruffle_shadow_template from "./shadow-template";
|
||||
|
||||
export default class RufflePlayer extends HTMLElement {
|
||||
|
@ -9,29 +9,47 @@ export default class RufflePlayer extends HTMLElement {
|
|||
self.shadow.appendChild(ruffle_shadow_template.content.cloneNode(true));
|
||||
|
||||
self.canvas = self.shadow.getElementById("player");
|
||||
self.ruffle = null;
|
||||
self.instance = null;
|
||||
|
||||
self.Ruffle = load_ruffle();
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
stream_swf_url(url) {
|
||||
async stream_swf_url(url) {
|
||||
//TODO: Actually stream files...
|
||||
console.log("Loading SWF file " + url);
|
||||
return fetch(url).then(response => {
|
||||
try {
|
||||
let abs_url = new URL(url, window.location.href).toString();
|
||||
console.log("Loading SWF file " + url);
|
||||
|
||||
let response = await fetch(abs_url);
|
||||
|
||||
if (response.ok) {
|
||||
response.arrayBuffer().then(data => this.play_swf_data(data))
|
||||
let data = await response.arrayBuffer();
|
||||
await this.play_swf_data(data);
|
||||
console.log("Playing " + url);
|
||||
} else {
|
||||
console.error("SWF load failed: " + response.status + " " + response.statusText + " for " + url);
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
console.error("Serious error occured loading SWF file: " + err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
play_swf_data(data) {
|
||||
if (this.ruffle) {
|
||||
this.ruffle.destroy();
|
||||
this.ruffle = null;
|
||||
async play_swf_data(data) {
|
||||
console.log("Got SWF data");
|
||||
|
||||
if (this.instance) {
|
||||
this.instance.destroy();
|
||||
this.instance = null;
|
||||
}
|
||||
|
||||
this.ruffle = Ruffle.new(this.canvas, new Uint8Array(data));
|
||||
let Ruffle = await this.Ruffle.catch(function (e) {
|
||||
console.error("Serious error loading Ruffle: " + e);
|
||||
throw e;
|
||||
});
|
||||
|
||||
this.instance = Ruffle.new(this.canvas, new Uint8Array(data));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue