Skip to content

Commit 7c08d3a

Browse files
kumardeohuozhivercel[bot]
authored
fix: correct implementation of init function exported by standalone submodule (#716)
Co-authored-by: Jiachi Liu <inbox@huozhi.im> Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com>
1 parent 6203e87 commit 7c08d3a

File tree

7 files changed

+94
-303
lines changed

7 files changed

+94
-303
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ playground/public/yoga.wasm
1515
playground/tsconfig.tsbuildinfo
1616

1717
# Vendor files
18-
yoga.wasm
18+
# yoga.wasm

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,10 @@
3636
}
3737
},
3838
"scripts": {
39-
"prepare": "husky install && pnpm run vendor",
39+
"prepare": "husky install",
4040
"dev": "pnpm run dev:default",
4141
"dev:default": "NODE_ENV=development tsup src/index.ts --watch --ignore-watch playground",
4242
"dev:playground": "turbo dev --filter=satori-playground...",
43-
"vendor": "cp node_modules/yoga-layout/dist/binaries/yoga.wasm .",
4443
"build": "pnpm run build:default && pnpm run build:standalone",
4544
"build:default": "NODE_ENV=production tsup",
4645
"build:standalone": "NODE_ENV=production SATORI_STANDALONE=1 tsup",

patches/yoga-layout@3.2.1.patch

Lines changed: 6 additions & 272 deletions
Large diffs are not rendered by default.

pnpm-lock.yaml

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/yoga.external.ts

Lines changed: 80 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,91 @@
11
import { loadYoga as loadYogaUntyped, type Yoga } from 'yoga-layout/load'
22

3+
const loadYoga = loadYogaUntyped as (options: {
4+
wasmBinary?: ArrayBuffer | ArrayBufferLike
5+
instantiateWasm?: (
6+
imports: WebAssembly.Imports,
7+
successCallback: (instance: WebAssembly.Instance) => void
8+
) => WebAssembly.Exports | false | undefined
9+
}) => Promise<Yoga>
10+
311
let resolveYoga: (yoga: Yoga) => void
4-
const yogaPromise: Promise<Yoga> = new Promise((resolve) => {
12+
let rejectYoga: (error: unknown) => void
13+
const yogaPromise: Promise<Yoga> = new Promise((resolve, reject) => {
514
resolveYoga = resolve
15+
rejectYoga = reject
616
})
717

8-
const loadYoga = loadYogaUntyped as (
9-
wasm: ArrayBuffer | ArrayBufferLike | WebAssembly.Instance
10-
) => Promise<Yoga>
11-
12-
export function init(
13-
yogaWasm:
14-
| ArrayBuffer
15-
| ArrayBufferLike
16-
| Buffer
17-
| WebAssembly.Instance
18-
| {
19-
instance: WebAssembly.Instance
18+
export type InitInput =
19+
| RequestInfo
20+
| URL
21+
| Response
22+
| BufferSource
23+
| Buffer
24+
| WebAssembly.Module
25+
26+
async function loadWasm(
27+
input: InitInput,
28+
imports: WebAssembly.Imports
29+
): Promise<WebAssembly.WebAssemblyInstantiatedSource> {
30+
let source: Response | BufferSource | Buffer | WebAssembly.Module = input
31+
32+
if (
33+
typeof source === 'string' ||
34+
(typeof Request === 'function' && source instanceof Request) ||
35+
(typeof URL === 'function' && source instanceof URL)
36+
) {
37+
source = await fetch(source)
38+
}
39+
40+
if (typeof Response === 'function' && source instanceof Response) {
41+
if (typeof WebAssembly.instantiateStreaming === 'function') {
42+
try {
43+
return await WebAssembly.instantiateStreaming(source, imports)
44+
} catch (e) {
45+
if (source.headers.get('Content-Type') !== 'application/wasm') {
46+
console.warn(
47+
'`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',
48+
e
49+
)
50+
}
2051
}
21-
) {
22-
// Buffer
23-
if ('buffer' in yogaWasm) {
24-
loadYoga(yogaWasm.buffer).then(resolveYoga)
25-
} else if ('instance' in yogaWasm) {
26-
// { instance: WebAssembly.Instance }
27-
loadYoga(yogaWasm.instance).then(resolveYoga)
28-
} else {
29-
// ArrayBuffer or WebAssembly.Instance
30-
loadYoga(yogaWasm).then(resolveYoga)
52+
}
53+
54+
const bytes = await source.arrayBuffer()
55+
return await WebAssembly.instantiate(bytes, imports)
3156
}
57+
58+
const instantiated = (await WebAssembly.instantiate(
59+
'buffer' in source
60+
? source.buffer.slice(
61+
source.byteOffset,
62+
source.byteOffset + source.byteLength
63+
)
64+
: source,
65+
imports
66+
)) as WebAssembly.Instance | WebAssembly.WebAssemblyInstantiatedSource
67+
68+
if (instantiated instanceof WebAssembly.Instance) {
69+
return { instance: instantiated, module: source as WebAssembly.Module }
70+
}
71+
72+
return instantiated
73+
}
74+
75+
export function init(input: InitInput) {
76+
loadYoga({
77+
instantiateWasm(imports, successCallback) {
78+
loadWasm(input, imports)
79+
.then(({ instance }) => {
80+
successCallback(instance)
81+
})
82+
.catch(rejectYoga)
83+
84+
return {}
85+
},
86+
})
87+
.then(resolveYoga)
88+
.catch(rejectYoga)
3289
}
3390

3491
export function getYoga() {

src/yoga.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { type Yoga } from 'yoga-layout/load'
22
import { type Node } from 'yoga-layout'
3+
import { type InitInput } from './yoga.external.js'
34

45
export { Yoga as TYoga, Node as YogaNode }
56

6-
export function init(wasm: ArrayBuffer | Buffer) {
7+
export function init(input: InitInput) {
78
if (process.env.SATORI_STANDALONE === '1') {
8-
return import('./yoga.external.js').then((mod) => mod.init(wasm))
9+
return import('./yoga.external.js').then((mod) => mod.init(input))
910
} else {
1011
// Do nothing. It's bundled.
1112
}

yoga.wasm

70.1 KB
Binary file not shown.

0 commit comments

Comments
 (0)