mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-11-05 04:04:07 +00:00
1696162d22
GHSA-jrc7-96c5-q579 covers every maplibre-gl up to 6.4.0 and has no 5.x release, so npm audit kept flagging the patched 5.24.0. Moving to 6.15.0 retires the local backport: patch-maplibre.mjs and its postinstall, predev and prebuild hooks go, along with the Dockerfile copy and its format-baseline entry. 6.x sanitizes attributions against an allow list. What the major changes for TREK: - ESM only, no default export: the engine module imports the namespace and hands that out as its default, so every caller stays as it was. - The worker is no longer inlined, and inside a bundle MapLibre cannot find it next to its own module. The engine sets it from Vite's ?worker&url build before any map, the Leaflet bridge's included. - WebGL2 only: the probe asks for webgl2 alone, so a WebGL1-only browser gets the raster basemap instead of a GPUInitializationError. - 6.9 shapes right-to-left text itself and deprecated setRTLTextPlugin; the old plugin would replace that and could only run through eval in the module worker, so MapLibre no longer registers it. Mapbox does. The lockfile moves maplibre-gl and its own dependencies only; the Leaflet bridge already allows ^6.0.0 as its peer.
92 lines
3.3 KiB
TypeScript
92 lines
3.3 KiB
TypeScript
/**
|
|
* The WebGL probe (#2288).
|
|
*
|
|
* What is under test is the contract the basemap depends on: ask the browser
|
|
* once, ask it the way maplibre-gl asks, give the context straight back, and
|
|
* never throw whatever the browser does.
|
|
*/
|
|
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
|
import { hasWebGL, resetWebGLProbe } from './webgl'
|
|
|
|
const realGetContext = HTMLCanvasElement.prototype.getContext
|
|
|
|
/** A context that records whether its lose-context extension was used. */
|
|
function fakeContext() {
|
|
const loseContext = vi.fn()
|
|
return { ctx: { getExtension: vi.fn(() => ({ loseContext })) }, loseContext }
|
|
}
|
|
|
|
beforeEach(() => {
|
|
resetWebGLProbe()
|
|
vi.restoreAllMocks()
|
|
})
|
|
|
|
afterEach(() => {
|
|
HTMLCanvasElement.prototype.getContext = realGetContext
|
|
resetWebGLProbe()
|
|
})
|
|
|
|
describe('hasWebGL', () => {
|
|
it('FE-UTIL-WEBGL-001: says yes when the browser hands back a context', () => {
|
|
const { ctx } = fakeContext()
|
|
HTMLCanvasElement.prototype.getContext = vi.fn(() => ctx) as unknown as typeof realGetContext
|
|
|
|
expect(hasWebGL()).toBe(true)
|
|
})
|
|
|
|
it('FE-UTIL-WEBGL-002: says no when it hands back null, which is WebGL switched off', () => {
|
|
// jsdom answers this way too, so the whole suite would take the raster path
|
|
// if this were the other way round.
|
|
HTMLCanvasElement.prototype.getContext = vi.fn(() => null) as unknown as typeof realGetContext
|
|
|
|
expect(hasWebGL()).toBe(false)
|
|
})
|
|
|
|
it('FE-UTIL-WEBGL-003: says no when only webgl1 is on offer', () => {
|
|
// MapLibre 6 asks for webgl2 and nothing else. A probe that settled for
|
|
// webgl1 would wave the map through to a GPUInitializationError.
|
|
const { ctx } = fakeContext()
|
|
const getContext = vi.fn((type: string) => (type === 'webgl2' ? null : ctx))
|
|
HTMLCanvasElement.prototype.getContext = getContext as unknown as typeof realGetContext
|
|
|
|
expect(hasWebGL()).toBe(false)
|
|
expect(getContext.mock.calls.map((c) => c[0])).toEqual(['webgl2'])
|
|
})
|
|
|
|
it('FE-UTIL-WEBGL-004: gives the probe context straight back', () => {
|
|
// Contexts are a capped resource, around sixteen in Chrome. A probe that
|
|
// keeps one is a context the map behind it may not get.
|
|
const { ctx, loseContext } = fakeContext()
|
|
HTMLCanvasElement.prototype.getContext = vi.fn(() => ctx) as unknown as typeof realGetContext
|
|
|
|
hasWebGL()
|
|
|
|
expect(ctx.getExtension).toHaveBeenCalledWith('WEBGL_lose_context')
|
|
expect(loseContext).toHaveBeenCalled()
|
|
})
|
|
|
|
it('FE-UTIL-WEBGL-005: asks once and remembers, however often it is called', () => {
|
|
const { ctx } = fakeContext()
|
|
const getContext = vi.fn(() => ctx)
|
|
HTMLCanvasElement.prototype.getContext = getContext as unknown as typeof realGetContext
|
|
|
|
hasWebGL()
|
|
hasWebGL()
|
|
hasWebGL()
|
|
|
|
// One probe, one context. A planner holding a map and a settings preview
|
|
// would otherwise spend three.
|
|
expect(getContext).toHaveBeenCalledTimes(1)
|
|
})
|
|
|
|
it('FE-UTIL-WEBGL-006: a browser that throws out of getContext counts as no', () => {
|
|
// Some locked-down builds throw rather than returning null, and an answer is
|
|
// never worth an exception.
|
|
HTMLCanvasElement.prototype.getContext = vi.fn(() => {
|
|
throw new Error('WebGL is disabled by policy')
|
|
}) as unknown as typeof realGetContext
|
|
|
|
expect(hasWebGL()).toBe(false)
|
|
})
|
|
})
|