Skip to content

Commit 17f19d1

Browse files
authored
Merge pull request #5063 from Shopify/lopert.wasm-opt
Download and run wasm-opt
2 parents 011fc50 + 219b31c commit 17f19d1

File tree

15 files changed

+185
-11
lines changed

15 files changed

+185
-11
lines changed

packages/app/src/cli/models/app/app.test-data.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,7 @@ function defaultFunctionConfiguration(): FunctionConfigType {
501501
build: {
502502
command: 'echo "hello world"',
503503
watch: ['src/**/*.rs'],
504+
wasm_opt: true,
504505
},
505506
api_version: '2022-07',
506507
configuration_ui: true,

packages/app/src/cli/models/app/app.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ describe('validateFunctionExtensionsWithUiHandle', () => {
205205
description: 'description',
206206
build: {
207207
command: 'echo "hello world"',
208+
wasm_opt: true,
208209
},
209210
api_version: '2022-07',
210211
configuration_ui: true,

packages/app/src/cli/models/extensions/extension-instance.test.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ function functionConfiguration(): FunctionConfigType {
3232
api_version: '2023-07',
3333
configuration_ui: true,
3434
metafields: [],
35-
build: {},
35+
build: {
36+
wasm_opt: true,
37+
},
3638
}
3739
}
3840

@@ -41,6 +43,7 @@ describe('watchPaths', async () => {
4143
const config = functionConfiguration()
4244
config.build = {
4345
watch: 'src/single-path.foo',
46+
wasm_opt: true,
4447
}
4548
const extensionInstance = await testFunctionExtension({
4649
config,
@@ -54,7 +57,9 @@ describe('watchPaths', async () => {
5457

5558
test('returns default paths for javascript', async () => {
5659
const config = functionConfiguration()
57-
config.build = {}
60+
config.build = {
61+
wasm_opt: true,
62+
}
5863
const extensionInstance = await testFunctionExtension({
5964
config,
6065
entryPath: 'src/index.js',
@@ -86,6 +91,7 @@ describe('watchPaths', async () => {
8691
const config = functionConfiguration()
8792
config.build = {
8893
watch: ['src/**/*.rs', 'src/**/*.foo'],
94+
wasm_opt: true,
8995
}
9096
const extensionInstance = await testFunctionExtension({
9197
config,
@@ -103,7 +109,9 @@ describe('watchPaths', async () => {
103109

104110
test('returns null if not javascript and not configured', async () => {
105111
const config = functionConfiguration()
106-
config.build = {}
112+
config.build = {
113+
wasm_opt: true,
114+
}
107115
const extensionInstance = await testFunctionExtension({
108116
config,
109117
})

packages/app/src/cli/models/extensions/specifications/function.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ describe('functionConfiguration', () => {
2020
build: {
2121
command: 'make build',
2222
path: 'dist/index.wasm',
23+
wasm_opt: true,
2324
},
2425
ui: {
2526
paths: {

packages/app/src/cli/models/extensions/specifications/function.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const FunctionExtensionSchema = BaseSchema.extend({
2525
.optional(),
2626
path: zod.string().optional(),
2727
watch: zod.union([zod.string(), zod.string().array()]).optional(),
28+
wasm_opt: zod.boolean().optional().default(true),
2829
}),
2930
configuration_ui: zod.boolean().optional().default(true),
3031
ui: zod

packages/app/src/cli/services/build/extension.test.ts

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
import {buildFunctionExtension} from './extension.js'
22
import {testFunctionExtension} from '../../models/app/app.test-data.js'
3-
import {buildJSFunction} from '../function/build.js'
3+
import {buildJSFunction, runWasmOpt} from '../function/build.js'
44
import {ExtensionInstance} from '../../models/extensions/extension-instance.js'
55
import {FunctionConfigType} from '../../models/extensions/specifications/function.js'
66
import {beforeEach, describe, expect, test, vi} from 'vitest'
77
import {exec} from '@shopify/cli-kit/node/system'
88
import lockfile from 'proper-lockfile'
99
import {AbortError} from '@shopify/cli-kit/node/error'
10+
import {fileExistsSync} from '@shopify/cli-kit/node/fs'
1011

1112
vi.mock('@shopify/cli-kit/node/system')
1213
vi.mock('../function/build.js')
1314
vi.mock('proper-lockfile')
15+
vi.mock('@shopify/cli-kit/node/fs')
1416

1517
describe('buildFunctionExtension', () => {
1618
let extension: ExtensionInstance<FunctionConfigType>
@@ -26,6 +28,7 @@ describe('buildFunctionExtension', () => {
2628
build: {
2729
command: 'make build',
2830
path: 'dist/index.wasm',
31+
wasm_opt: true,
2932
},
3033
configuration_ui: true,
3134
api_version: '2022-07',
@@ -138,6 +141,45 @@ describe('buildFunctionExtension', () => {
138141
expect(releaseLock).toHaveBeenCalled()
139142
})
140143

144+
test('performs wasm-opt execution by default', async () => {
145+
// Given
146+
vi.mocked(fileExistsSync).mockResolvedValue(true)
147+
148+
// When
149+
await expect(
150+
buildFunctionExtension(extension, {
151+
stdout,
152+
stderr,
153+
signal,
154+
app,
155+
environment: 'production',
156+
}),
157+
).resolves.toBeUndefined()
158+
159+
// Then
160+
expect(runWasmOpt).toHaveBeenCalled()
161+
})
162+
163+
test('skips wasm-opt execution when the disable-wasm-opt is true', async () => {
164+
// Given
165+
vi.mocked(fileExistsSync).mockResolvedValue(true)
166+
extension.configuration.build.wasm_opt = false
167+
168+
// When
169+
await expect(
170+
buildFunctionExtension(extension, {
171+
stdout,
172+
stderr,
173+
signal,
174+
app,
175+
environment: 'production',
176+
}),
177+
).resolves.toBeUndefined()
178+
179+
// Then
180+
expect(runWasmOpt).not.toHaveBeenCalled()
181+
})
182+
141183
test('fails when build lock cannot be acquired', async () => {
142184
// Given
143185
vi.mocked(lockfile.lock).mockRejectedValue('failed to acquire lock')

packages/app/src/cli/services/build/extension.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {runThemeCheck} from './theme-check.js'
22
import {AppInterface} from '../../models/app/app.js'
33
import {bundleExtension, bundleFlowTemplateExtension} from '../extensions/bundle.js'
4-
import {buildJSFunction} from '../function/build.js'
4+
import {buildJSFunction, runWasmOpt} from '../function/build.js'
55
import {ExtensionInstance} from '../../models/extensions/extension-instance.js'
66
import {FunctionConfigType} from '../../models/extensions/specifications/function.js'
77
import {exec} from '@shopify/cli-kit/node/system'
@@ -175,6 +175,12 @@ export async function buildFunctionExtension(
175175
} else {
176176
await buildOtherFunction(extension, options)
177177
}
178+
179+
const wasmOpt = (extension as ExtensionInstance<FunctionConfigType>).configuration.build.wasm_opt
180+
if (fileExistsSync(extension.outputPath) && wasmOpt) {
181+
await runWasmOpt(extension.outputPath)
182+
}
183+
178184
if (fileExistsSync(extension.outputPath) && bundlePath !== extension.outputPath) {
179185
const base64Contents = await readFile(extension.outputPath, {encoding: 'base64'})
180186
await touchFile(bundlePath)

packages/app/src/cli/services/context/id-matching.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ beforeAll(async () => {
233233
build: {
234234
command: 'make build',
235235
path: 'dist/index.wasm',
236+
wasm_opt: true,
236237
},
237238
configuration_ui: false,
238239
api_version: '2022-07',

packages/app/src/cli/services/context/identifiers-extensions.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ beforeAll(async () => {
263263
build: {
264264
command: 'make build',
265265
path: 'dist/index.wasm',
266+
wasm_opt: true,
266267
},
267268
metafields: [],
268269
configuration_ui: false,

packages/app/src/cli/services/function/binaries.test.ts

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {javyBinary, functionRunnerBinary, downloadBinary, javyPluginBinary} from './binaries.js'
1+
import {javyBinary, functionRunnerBinary, downloadBinary, javyPluginBinary, wasmOptBinary} from './binaries.js'
22
import {fetch, Response} from '@shopify/cli-kit/node/http'
33
import {fileExists, removeFile} from '@shopify/cli-kit/node/fs'
44
import {describe, expect, test, vi} from 'vitest'
@@ -279,3 +279,35 @@ describe('functionRunner', () => {
279279
await expect(fileExists(functionRunner.path)).resolves.toBeTruthy()
280280
})
281281
})
282+
283+
describe('wasm-opt', () => {
284+
const wasmOpt = wasmOptBinary()
285+
286+
test('properties are set correctly', () => {
287+
expect(wasmOpt.name).toBe('wasm-opt.cjs')
288+
expect(wasmOpt.version).match(/\d.\d.\d$/)
289+
expect(wasmOpt.path).toMatch(/(\/|\\)wasm-opt.cjs$/)
290+
})
291+
292+
test('downloadUrl returns the correct URL', () => {
293+
// When
294+
const url = wasmOpt.downloadUrl('', '')
295+
296+
// Then
297+
expect(url).toMatch(/https:\/\/cdn.jsdelivr.net\/npm\/binaryen@\d{3}\.\d\.\d\/bin\/wasm-opt/)
298+
})
299+
300+
test('downloads wasm-opt', async () => {
301+
// Given
302+
await removeFile(wasmOpt.path)
303+
await expect(fileExists(wasmOpt.path)).resolves.toBeFalsy()
304+
vi.mocked(fetch).mockResolvedValue(new Response('wasm-opt'))
305+
306+
// When
307+
await downloadBinary(wasmOpt)
308+
309+
// Then
310+
expect(fetch).toHaveBeenCalledOnce()
311+
await expect(fileExists(wasmOpt.path)).resolves.toBeTruthy()
312+
})
313+
})

0 commit comments

Comments
 (0)