Skip to content

Commit

Permalink
add Wasm Loader as App
Browse files Browse the repository at this point in the history
  • Loading branch information
DougAnderson444 committed Apr 3, 2024
1 parent 61eaccf commit a9901a7
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 9 deletions.
16 changes: 8 additions & 8 deletions wallet/src/App.svelte
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<script>
import { onMount, tick } from 'svelte';
import workerFile from './worker.js?raw';
import { Loader } from './lib/index.js';
onMount(async () => {
const worker = new Worker(
new URL(`data:application/javascript,${encodeURIComponent(workerFile)}`),
{
type: 'module'
}
);
});
onMount(async () => {});
</script>

<svelte:head>
<script src="https://cdn.tailwindcss.com"></script>
</svelte:head>

<Loader />
166 changes: 166 additions & 0 deletions wallet/src/lib/WasmLoader.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
<script>
// a component to send data to a plugin
import { onMount, tick, createEventDispatcher } from 'svelte';
import { Wurbo, wurboIn } from 'wurbo';
export let pluginFile;
const files = new Map();
let fileinput;
let name;
const dispatch = createEventDispatcher();
/**
* The rendered component as a string of HTML
* @type {string | null}
*/
let renderedHTML;
/**
* The module that loads the WebAssembly component
*
* @type
*/
let wurbo;
/**
* The location hash frag
**/
let api;
let Graph = null;
onMount(async () => {
// init the graph utility
const g = await import('./graph/graph.js');
g.$init.then(() => (Graph = new g.provider.Graph()));
api = location.hash.substring(1);
});
$: if (pluginFile) {
// name without the .wasm on the end, because we will also store our data here
let path = ['apps', pluginFile.name.replace(/\.wasm$/, ''), 'wasm'];
(async () => {
try {
load(pluginFile.bytes);
pluginFile = null; // reset loader state
fileinput.value = null; // reset file input
} catch (error) {
console.error('error saving plugin', { error });
}
})();
}
const onFileSelected = (e) => {
let plugin = e.target.files[0];
let reader = new FileReader();
files.set(reader, plugin);
reader.addEventListener('loadend', (evt) => {
// reader.result contains the contents of blob as a typed array
pluginFile = { bytes: reader.result, name };
});
reader.addEventListener('load', (evt) => {
const file = files.get(evt.target);
console.log(`The contents of ${file.name}:`);
name = file.name;
});
// reader.readAsDataURL(plugin);
reader.readAsArrayBuffer(plugin);
// reader.readAsText(plugin);
};
// OnFileLoaded: Once the wasm bytes are loaded, we can setup the plugin
// key is a cid string
async function load(arrayBuffer) {
let bytes = new Uint8Array(arrayBuffer);
// use Graph to get the importables from the bytes
let imports;
try {
let component = Graph.addComponent('loaded', bytes);
console.log('component', component);
imports = component.imports;
} catch (error) {
console.error('error getting importables', { error });
}
// filter to select any that contains `/wurbo-in`, set the importable to the `wurboIn` function,
let importables = imports
.filter((i) => i.name.includes('/wurbo-in'))
.map((i) => {
// trim string after the @
let name = i.name.split('@')[0];
return { [name]: wurboIn };
});
// load the import handles into the Wasm component and get the ES module returned
wurbo = new Wurbo({ arrayBuffer, importables }, async (payload) => {
// Relay emitted commands from the Wasm component to PiperNet
console.log('Command emitted: ', { payload });
try {
// return await piper.command(payload);
} catch (error) {
// it's ok to fail silently, not all messages are commands
}
});
// call `render` with your inputs for the component
renderedHTML = await wurbo.render({
tag: 'all-content',
val: { api }
});
}
// Once the HTML is rendered and the module is loaded, we can activate the event emitters
$: if (renderedHTML && wurbo)
(async () => {
// wait for the DOM to reflect the updates first
await tick();
// once the DOM has our elements loaded, we can activate the aggregated event emitters
wurbo.aggregation();
console.log('*** wurbo evt listeners should be activated ***');
})();
</script>

<input
style="display:none"
type="file"
accept=".wasm, .wasm"
on:change={(e) => onFileSelected(e)}
bind:this={fileinput}
/>
<div
class="flex justify-center cursor-pointer border border-green-400 rounded-md px-4 py-2 my-1 shadow"
on:keypress={() => {
fileinput.click();
}}
on:click={() => {
fileinput.click();
}}
>
<div class="flex">
Load wurbo *.wasm file (must export <span class="font-mono mx-1 px-1 bg-amber-100 rounded-lg"
>wurbo-in</span
>
and import
<span class="font-mono mx-1 px-1 bg-amber-100 rounded-lg">wurbo-out</span>
)
</div>
</div>

<!-- Display bytes -->
{#if pluginFile}
<div class="flex flex-col">
<div class="flex-1 flex-row bg-green-50/10 p-2">File loaded</div>
<div class="flex-1 flex-row">{@html pluginFile}</div>
</div>
{/if}

<div>
{#if renderedHTML}
{@html renderedHTML}
{/if}
</div>
2 changes: 1 addition & 1 deletion wallet/src/lib/index.js
Original file line number Diff line number Diff line change
@@ -1 +1 @@
// place files you want to import through the `$lib` alias in this folder.
export { default as Loader } from './WasmLoader.svelte';

0 comments on commit a9901a7

Please sign in to comment.