Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ playground/public/yoga.wasm
playground/tsconfig.tsbuildinfo

# Vendor files
yoga.wasm
# yoga.wasm
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,10 @@
}
},
"scripts": {
"prepare": "husky install && pnpm run vendor",
"prepare": "husky install",
"dev": "pnpm run dev:default",
"dev:default": "NODE_ENV=development tsup src/index.ts --watch --ignore-watch playground",
"dev:playground": "turbo dev --filter=satori-playground...",
"vendor": "cp node_modules/yoga-layout/dist/binaries/yoga.wasm .",
"build": "pnpm run build:default && pnpm run build:standalone",
"build:default": "NODE_ENV=production tsup",
"build:standalone": "NODE_ENV=production SATORI_STANDALONE=1 tsup",
Expand Down
278 changes: 6 additions & 272 deletions patches/[email protected]

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

98 changes: 75 additions & 23 deletions src/yoga.external.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,86 @@
import { loadYoga as loadYogaUntyped, type Yoga } from 'yoga-layout/load'

const loadYoga = loadYogaUntyped as (options: {
wasmBinary?: ArrayBuffer | ArrayBufferLike
instantiateWasm?: (
imports: WebAssembly.Imports,
successCallback: (instance: WebAssembly.Instance) => void
) => WebAssembly.Exports | false | undefined
}) => Promise<Yoga>

let resolveYoga: (yoga: Yoga) => void
const yogaPromise: Promise<Yoga> = new Promise((resolve) => {
let rejectYoga: (error: unknown) => void
const yogaPromise: Promise<Yoga> = new Promise((resolve, reject) => {
resolveYoga = resolve
rejectYoga = reject
})

const loadYoga = loadYogaUntyped as (
wasm: ArrayBuffer | ArrayBufferLike | WebAssembly.Instance
) => Promise<Yoga>

export function init(
yogaWasm:
| ArrayBuffer
| ArrayBufferLike
| Buffer
| WebAssembly.Instance
| {
instance: WebAssembly.Instance
export type InitInput =
| RequestInfo
| URL
| Response
| BufferSource
| Buffer
| WebAssembly.Module

async function loadWasm(
input: InitInput,
imports: WebAssembly.Imports
): Promise<WebAssembly.WebAssemblyInstantiatedSource> {
let source: Response | BufferSource | Buffer | WebAssembly.Module = input

if (
typeof source === 'string' ||
(typeof Request === 'function' && source instanceof Request) ||
(typeof URL === 'function' && source instanceof URL)
) {
source = await fetch(source)
}

if (typeof Response === 'function' && source instanceof Response) {
if (typeof WebAssembly.instantiateStreaming === 'function') {
try {
return await WebAssembly.instantiateStreaming(source, imports)
} catch (e) {
if (source.headers.get('Content-Type') !== 'application/wasm') {
console.warn(
'`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n',
e
)
}
}
) {
// Buffer
if ('buffer' in yogaWasm) {
loadYoga(yogaWasm.buffer).then(resolveYoga)
} else if ('instance' in yogaWasm) {
// { instance: WebAssembly.Instance }
loadYoga(yogaWasm.instance).then(resolveYoga)
} else {
// ArrayBuffer or WebAssembly.Instance
loadYoga(yogaWasm).then(resolveYoga)
}

const bytes = await source.arrayBuffer()
return await WebAssembly.instantiate(bytes, imports)
}

const instantiated = (await WebAssembly.instantiate(
'buffer' in source ? source.buffer : source,
imports
)) as WebAssembly.Instance | WebAssembly.WebAssemblyInstantiatedSource

if (instantiated instanceof WebAssembly.Instance) {
return { instance: instantiated, module: source as WebAssembly.Module }
}

return instantiated
}

export function init(input: InitInput) {
loadYoga({
instantiateWasm(imports, successCallback) {
loadWasm(input, imports)
.then(({ instance }) => {
successCallback(instance)
})
.catch(rejectYoga)

return {}
},
})
.then(resolveYoga)
.catch(rejectYoga)
}

export function getYoga() {
Expand Down
5 changes: 3 additions & 2 deletions src/yoga.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { type Yoga } from 'yoga-layout/load'
import { type Node } from 'yoga-layout'
import { type InitInput } from './yoga.external.js'

export { Yoga as TYoga, Node as YogaNode }

export function init(wasm: ArrayBuffer | Buffer) {
export function init(input: InitInput) {
if (process.env.SATORI_STANDALONE === '1') {
return import('./yoga.external.js').then((mod) => mod.init(wasm))
return import('./yoga.external.js').then((mod) => mod.init(input))
} else {
// Do nothing. It's bundled.
}
Expand Down
Binary file added yoga.wasm
Binary file not shown.