snapshot of https://github.com/tldraw/tldraw.git (main, 2026-09-23; blobs > 131072B omitted)
Some checks failed
Deploy analytics worker / Deploy analytics worker to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Failing after 1s
i18n upload strings / Upload latest strings (push) Failing after 1s
Deploy bemo / Deploy bemo to ${{ (github.ref == 'refs/heads/bemo-production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Failing after 1s
Deploy grafana resources / ${{ github.event_name == 'push' && 'Deploy grafana resources' || 'Validate grafana resources (dry run)' }} (push) Failing after 0s
End to end tests (dotcom) / Check for relevant changes (push) Failing after 0s
End to end tests (examples) / Check for relevant changes (push) Failing after 0s
End to end tests (mermaid readability) / Check for relevant changes (push) Failing after 1s
End to end tests (perf) / Check for relevant changes (push) Failing after 0s
Publish editor extensions / Publish editor extensions (push) Failing after 1s
Publish SDK packages / Remove the publish-packages label (push) Has been skipped
Checks / Tests & checks (push) Has been cancelled
Checks / Build all projects (push) Has been cancelled
Deploy templates / Deploy templates (push) Has been cancelled
End to end tests (dotcom) / End to end tests (dotcom) (push) Has been cancelled
End to end tests (mermaid readability) / End to end tests (mermaid readability) (push) Has been cancelled
End to end tests (perf) / End to end tests (perf) (push) Has been cancelled
Deploy .com / Deploy dotcom to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Has been cancelled
End to end tests (examples) / End to end tests (examples) (push) Has been cancelled
Publish SDK packages / Publish SDK packages (push) Has been cancelled
Publish SDK packages / Tell user released version (push) Has been cancelled
Publish SDK packages / Publishes code templates to separate repositories (push) Has been cancelled
Publish SDK packages / Deploys the template demos with the new SDK version (push) Has been cancelled

This commit is contained in:
upstream-mirror
2026-09-23 16:12:52 +05:00
commit a774ac673a
4541 changed files with 770499 additions and 0 deletions

View File

@@ -0,0 +1,99 @@
// @vitest-environment jsdom
import type { Editor } from 'tldraw'
import { beforeAll, describe, expect, it } from 'vitest'
/**
* Regression coverage for the "Illegal invocation" exec failure.
*
* Chromium's window.setTimeout brand-checks its receiver: invoking a captured
* reference as a method of another object (`captured.setTimeout(...)`) throws
* "TypeError: Illegal invocation". The exec timeout race used to do exactly
* that, so its promise rejected synchronously and any exec code containing an
* `await` lost the race and reported "Illegal invocation" while its shapes
* kept appearing.
*
* jsdom's timers don't brand-check, so this suite installs a simulated
* brand-checking setTimeout BEFORE exec-helpers captures its globals at module
* load. A regression to the unbound invocation makes the async test below fail
* with exactly the production error.
*/
let executeCode: typeof import('./exec-helpers').executeCode
beforeAll(async () => {
const native = window.setTimeout.bind(window)
function brandCheckedSetTimeout(this: unknown, ...args: Parameters<typeof setTimeout>) {
if (this !== window && this !== undefined && this !== globalThis) {
throw new TypeError('Illegal invocation')
}
return native(...args)
}
window.setTimeout = brandCheckedSetTimeout as unknown as typeof window.setTimeout
// executeCode resolves the focused proxy's method map from the widget
// bootstrap; an empty map means every editor call passes through, which is
// fine — these tests never touch the editor.
;(window as { __TLDRAW_BOOTSTRAP__?: unknown }).__TLDRAW_BOOTSTRAP__ = { methodMap: {} }
// Import AFTER the brand check is installed so the module captures the
// simulated timer, exactly as it captures Chromium's native one.
;({ executeCode } = await import('./exec-helpers'))
// The import transforms the whole tldraw package on a cold cache, which can
// exceed vitest's default 10s hook timeout in CI.
}, 60_000)
// The Blob-URL module loader cannot run under vitest (Node cannot import
// blob: URLs); compile the exec module with an async Function instead. The
// sandbox and timeout-race behavior under test is unaffected.
const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor as new (
...args: string[]
) => (editor: unknown, helpers: unknown) => Promise<unknown>
async function loadModule(code: string) {
const compiled = new AsyncFunction('editor', 'helpers', code)
return async ({ editor, helpers }: { editor: Editor; helpers: unknown }) =>
compiled(editor, helpers)
}
const stubEditor = {} as Editor
describe('the simulated brand check', () => {
it('throws Illegal invocation for object-method calls, like Chromium', () => {
const captured = { setTimeout: window.setTimeout }
expect(() => captured.setTimeout(() => {}, 1)).toThrow('Illegal invocation')
})
it('allows window-bound calls', () => {
const bound = window.setTimeout.bind(window)
const id = bound(() => {}, 1)
expect(id).toBeDefined()
clearTimeout(id)
})
})
describe('executeCode timeout race', () => {
it('completes async exec code (the case that used to report Illegal invocation)', async () => {
const result = await executeCode(
stubEditor,
'await new Promise((resolve) => queueMicrotask(resolve)); return 42',
{ loadModule }
)
expect(result).toEqual({ success: true, result: 42 })
})
it('completes synchronous exec code', async () => {
const result = await executeCode(stubEditor, 'return 1 + 2', { loadModule })
expect(result).toEqual({ success: true, result: 3 })
})
it('reports runtime errors from exec code', async () => {
const result = await executeCode(stubEditor, 'throw new Error("boom")', { loadModule })
expect(result).toEqual({ success: false, error: 'boom' })
})
it('restores the sandboxed globals after execution', async () => {
await executeCode(stubEditor, 'return 0', { loadModule })
expect(typeof window.setTimeout).toBe('function')
expect(typeof window.fetch).toBe('function')
})
})