From fa2f839cbd4ab27a45558dd9b34343db4aa34653 Mon Sep 17 00:00:00 2001 From: Sameh Khamis Date: Tue, 15 Sep 2026 08:12:13 -0700 Subject: [PATCH] fix: validate feature services before allocating scene owners --- src/app/operations.js | 14 ++++++++------ src/app/operations.test.mjs | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/app/operations.js b/src/app/operations.js index f5e93c78c..f5104e960 100644 --- a/src/app/operations.js +++ b/src/app/operations.js @@ -1,3 +1,4 @@ +import { requireFeatureSource } from '../sources/featureSource.js'; import { createOverpassFeatureSource } from '../sources/overpassFeatures.js'; import { createSurfaceServices } from './surfaceServices.js'; import { createAnnotationResolver } from '../annotations/resolver.js'; @@ -14,17 +15,18 @@ export function createApplicationOperations({ requests, signal, eventTarget }) { if (typeof requests?.[name]?.[method] !== 'function') throw new TypeError(`Missing application request service: ${name}`); } + const features = requireFeatureSource( + requests.features ?? + createOverpassFeatureSource({ + boundarySource: requests.boundaries, + signal, + }), + ); const surface = createSurfaceServices({ terrainSource: requests.terrain, signal, eventTarget, }); - const features = - requests.features ?? - createOverpassFeatureSource({ - boundarySource: requests.boundaries, - signal, - }); const annotationResolver = createAnnotationResolver({ featureSource: features, signal, diff --git a/src/app/operations.test.mjs b/src/app/operations.test.mjs index fa1424750..6a8ca8966 100644 --- a/src/app/operations.test.mjs +++ b/src/app/operations.test.mjs @@ -163,3 +163,22 @@ test('annotation lookup and cached outlines use the supplied source independentl { name: 'AbortError' }, ); }); + +test('invalid feature adapters fail before surface listeners are installed', () => { + let installed = 0; + assert.throws( + () => + createApplicationOperations({ + signal: new AbortController().signal, + requests: { ...requests({ getHeights: async () => [] }), features: {} }, + eventTarget: { + addEventListener() { + installed++; + }, + removeEventListener() {}, + }, + }), + /Missing feature operation/, + ); + assert.equal(installed, 0); +});