@exodus/test 1.0.0-rc.108 → 1.0.0-rc.109

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -12,7 +12,7 @@ It can run your existing tests on [all runtimes and also browsers](#engines), wi
12
12
  and typestrip (via `--typescript`) modes
13
13
  - Runs on Node.js [node:test](https://nodejs.org/api/test.html), Bun, Deno, Electron,
14
14
  [v8 CLI](https://v8.dev/docs/d8), JSC, [Hermes](https://hermesengine.dev), [SpiderMonkey](https://spidermonkey.dev/),
15
- Chrome, Firefox, WebKit, Brave, Microsoft Edge,
15
+ Chrome, Firefox, WebKit, Brave, Microsoft Edge, [Servo](https://servo.org/),
16
16
  [QuickJS](https://github.com/quickjs-ng/quickjs), [XS](https://github.com/Moddable-OpenSource/moddable-xst),
17
17
  [GraalJS](https://github.com/oracle/graaljs), [Escargot](https://github.com/Samsung/escargot),
18
18
  [Boa](https://github.com/boa-dev/boa), and even [engine262](https://github.com/engine262/engine262).
@@ -66,6 +66,8 @@ Use `--engine` (or `EXODUS_TEST_ENGINE=`) to specify one of:
66
66
  - `firefox:puppeteer` — Firefox
67
67
  - `brave:puppeteer` — Brave
68
68
  - `msedge:puppeteer` — Microsoft Edge
69
+ - Bundle
70
+ - `servo:bundle` — Servo (expects it to be installed in the system or in PATH)
69
71
  - Barebone engines (system-provided or installed with `npx jsvu` / `npx esvu`):
70
72
  - `v8:bundle` — [v8 CLI](https://v8.dev/docs/d8) (Chrome/Blink/Node.js JavaScript engine)
71
73
  - `jsc:bundle` — [JavaScriptCore](https://docs.webkit.org/Deep%20Dive/JSC/JavaScriptCore.html) (Safari/WebKit JavaScript engine)
@@ -128,7 +130,7 @@ Use `--engine` (or `EXODUS_TEST_ENGINE=`) to specify one of:
128
130
  </pre>
129
131
  </details>
130
132
 
131
- See live output in [CI](https://github.com/ExodusMovement/test/actions/workflows/checks.yaml)
133
+ See live output in [CI](https://github.com/ExodusOSS/test/actions/workflows/checks.yaml)
132
134
 
133
135
  ## Library
134
136
 
@@ -91,6 +91,10 @@ function findBinaryOnce(name) {
91
91
  case 'safari':
92
92
  addPaths('darwin', '/Applications/Safari.app/Contents/MacOS/Safari')
93
93
  break
94
+ case 'servo':
95
+ addPaths('darwin', '/Applications/Servo.app/Contents/MacOS/servo')
96
+ addPaths('linux', '/usr/bin/servo')
97
+ break
94
98
  default:
95
99
  throw new Error('Trying to find an unexpected executable name')
96
100
  }
package/bin/index.js CHANGED
@@ -7,7 +7,7 @@ import { fileURLToPath } from 'node:url'
7
7
  import { basename, join } from 'node:path'
8
8
  import { randomUUID } from 'node:crypto'
9
9
  import { existsSync, rmSync, realpathSync } from 'node:fs'
10
- import { unlink } from 'node:fs/promises'
10
+ import { writeFile, unlink } from 'node:fs/promises'
11
11
  import { tmpdir, availableParallelism, homedir } from 'node:os'
12
12
  import assert from 'node:assert/strict'
13
13
  // The following make sense only when we run the code in the same Node.js version, i.e. engineOptions.haveIsOk
@@ -52,6 +52,8 @@ const ENGINES = new Map(
52
52
  'escargot:bundle': { binary: 'escargot', ...bareboneOpts },
53
53
  'boa:bundle': { binary: 'boa', binaryArgs: ['-m'], ...bareboneOpts },
54
54
  'jerryscript:bundle': { binary: 'jerryscript', ...bareboneOpts },
55
+ // Special case: running a browser from CLI like a bundle
56
+ 'servo:bundle': { binary: 'servo', binaryArgs: ['--headless'], ...bundleOpts, html: true },
55
57
  // Browser engines
56
58
  'chrome:puppeteer': { binary: 'chrome', browsers: 'puppeteer', ...bundleOpts },
57
59
  'firefox:puppeteer': { binary: 'firefox', browsers: 'puppeteer', ...bundleOpts },
@@ -65,7 +67,7 @@ const ENGINES = new Map(
65
67
  })
66
68
  )
67
69
  const barebonesOk = ['v8', 'd8', 'spidermonkey', 'quickjs', 'xs', 'hermes', 'shermes']
68
- const barebonesUnhandled = ['jsc', 'escargot', 'boa', 'graaljs', 'jerry', 'engine262']
70
+ const barebonesUnhandled = ['jsc', 'escargot', 'boa', 'graaljs', 'jerry', 'engine262', 'servo']
69
71
 
70
72
  const getEnvFlag = (name) => {
71
73
  if (!Object.hasOwn(process.env, name)) return
@@ -282,7 +284,7 @@ const engineOptions = ENGINES.get(options.engine)
282
284
  assert(engineOptions, `Unknown engine: ${options.engine}`)
283
285
  Object.assign(options, engineOptions)
284
286
  options.platform = options.binary // binary can be overriden by c8 or electron
285
- const isBrowserLike = options.browsers || options.electron
287
+ const isBrowserLike = options.browsers || options.electron || options.html
286
288
  setEnv('EXODUS_TEST_ENGINE', options.engine) // e.g. 'hermes:bundle', 'node:bundle', 'node:test', 'node:pure'
287
289
  setEnv('EXODUS_TEST_PLATFORM', options.binary === 'shermes' ? 'hermes' : options.binary) // e.g. 'hermes', 'node'
288
290
  setEnv('EXODUS_TEST_TIMEOUT', options.testTimeout)
@@ -595,7 +597,7 @@ if (options.binary === 'electron') {
595
597
  }
596
598
  }
597
599
 
598
- if (options.barebone || ['electron', 'workerd'].includes(options.binary)) {
600
+ if (options.barebone || ['electron', 'workerd', 'servo'].includes(options.binary)) {
599
601
  options.binary = findBinary(options.binary)
600
602
  options.binaryCanBeAbsolute = true
601
603
  }
@@ -689,9 +691,14 @@ if (options.pure) {
689
691
  const runOne = async (inputFile) => {
690
692
  const bundled = buildFile ? await buildFile(inputFile) : undefined
691
693
  if (buildFile) assert(bundled.file)
692
- const file = buildFile ? bundled.file : inputFile
693
694
  if (bundled?.errors.length > 0) return { ok: false, output: bundled.errors }
695
+ if (bundled && options.html) {
696
+ bundled.fileHtml = `${bundled.file}.html`
697
+ assert(/^[a-z0-9/_.-]+\.js$/iu.test(bundled.file), bundled.file)
698
+ await writeFile(bundled.fileHtml, `<script src="${bundled.file}"></script>`)
699
+ }
694
700
 
701
+ const file = buildFile ? bundled.fileHtml ?? bundled.file : inputFile
695
702
  const failedBare = 'EXODUS_TEST_FAILED_EXIT_CODE_1'
696
703
  const cleanOut = (out) => out.replaceAll(`\n${failedBare}\n`, '\n').replaceAll(failedBare, '')
697
704
  // Timeout is fallback if timeout in script hangs, 50x as it can be adjusted per-script inside them
@@ -721,6 +728,7 @@ if (options.pure) {
721
728
  throw err // Internal test runner error, e.g. launch() failed
722
729
  } finally {
723
730
  if (bundled) await unlink(bundled.file)
731
+ if (bundled?.fileHtml) await unlink(bundled.fileHtml)
724
732
  }
725
733
  }
726
734
 
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@exodus/test",
3
- "version": "1.0.0-rc.108",
3
+ "version": "1.0.0-rc.109",
4
4
  "author": "Exodus Movement, Inc.",
5
5
  "description": "A test suite runner",
6
- "homepage": "https://github.com/ExodusMovement/test",
6
+ "homepage": "https://github.com/ExodusOSS/test",
7
7
  "repository": {
8
8
  "type": "git",
9
- "url": "https://github.com/ExodusMovement/test.git"
9
+ "url": "https://github.com/ExodusOSS/test.git"
10
10
  },
11
11
  "bugs": {
12
- "url": "https://github.com/ExodusMovement/tests/issues"
12
+ "url": "https://github.com/ExodusOSS/tests/issues"
13
13
  },
14
14
  "keywords": [
15
15
  "test",
@@ -124,6 +124,7 @@
124
124
  "test:hermes": "EXODUS_TEST_ENGINE=hermes:bundle npm run test:_bundle --",
125
125
  "test:shermes": "EXODUS_TEST_ENGINE=shermes:bundle npm run test:_bundle --",
126
126
  "test:spidermonkey": "EXODUS_TEST_ENGINE=spidermonkey:bundle npm run test:_bundle --",
127
+ "test:servo": "EXODUS_TEST_ENGINE=servo:bundle npm run test:_bundle --",
127
128
  "test:engine262": "EXODUS_TEST_ENGINE=engine262:bundle npm run test:_bundle --",
128
129
  "test:quickjs": "EXODUS_TEST_ENGINE=quickjs:bundle npm run test:_bundle --",
129
130
  "test:xs": "EXODUS_TEST_ENGINE=xs:bundle npm run test:_bundle --",
@@ -144,7 +145,7 @@
144
145
  "optionalDependencies": {
145
146
  "@chalker/queue": "^1.0.1",
146
147
  "@exodus/replay": "^1.0.0-rc.9",
147
- "@exodus/test-bundler": "1.0.0-rc.9",
148
+ "@exodus/test-bundler": "1.0.0-rc.10",
148
149
  "c8": "^9.1.0",
149
150
  "expect": "^30.2.0",
150
151
  "fast-glob": "^3.2.11",
package/src/benchmark.js CHANGED
@@ -37,6 +37,7 @@ export async function benchmark(name, options, fn) {
37
37
  let min, max
38
38
  let total = 0n
39
39
  let count = 0
40
+ const endAt = getTime() + BigInt(timeout) * 10n ** 6n
40
41
  while (true) {
41
42
  const arg = args ? args[count % args.length] : count
42
43
  count++
@@ -48,11 +49,11 @@ export async function benchmark(name, options, fn) {
48
49
  total += diff
49
50
  if (min === undefined || min > diff) min = diff
50
51
  if (max === undefined || max < diff) max = diff
51
- if (total >= BigInt(timeout) * 10n ** 6n) break
52
+ if (stop >= endAt) break
52
53
  }
53
54
 
54
55
  const mean = total / BigInt(count)
55
- const rps = 1e9 / Number(mean)
56
+ const rps = (1e9 * count) / Number(total) // Loss in precision to doubles on very fast ops, but this is better than mean rounding
56
57
  let res = `${name} x ${fRps(rps)} ops/sec @ ${fTime(mean)}/op`
57
58
  if (fTime(min) !== fTime(max)) res += ` (${fTime(min)}..${fTime(max)})`
58
59
  console.log(res)
@@ -1,7 +1,7 @@
1
1
  const nameCounts = new Map()
2
2
  let snapshotText, snapshotTextClean
3
3
 
4
- const escapeSnapshot = (str) => str.replaceAll(/([\\`])/gu, '\\$1')
4
+ const escapeSnapshot = (str) => str.replaceAll(/([\\`]|\$\{)/gu, '\\$1')
5
5
 
6
6
  function matchSnapshot(readSnapshot, assert, name, serialized) {
7
7
  // We don't have native snapshots, polyfill reading