@@ -123,23 +123,36 @@ function regularFile(packageDir, relativePath) {
123123 return { path, relativePath, sha256 } ;
124124}
125125
126+ function isEnoent ( error ) {
127+ return error !== null && typeof error === "object" && "code" in error && error . code === "ENOENT" ;
128+ }
129+
126130function requireAbsent ( packageDir , relativePath ) {
127131 try {
128132 lstatSync ( resolve ( packageDir , relativePath ) ) ;
129133 } catch ( error ) {
130- if (
131- error !== null &&
132- typeof error === "object" &&
133- "code" in error &&
134- error . code === "ENOENT"
135- ) {
136- return ;
137- }
134+ if ( isEnoent ( error ) ) return ;
138135 throw error ;
139136 }
140137 throw new Error ( `${ relativePath } must not exist in a release package` ) ;
141138}
142139
140+ /**
141+ * Asserts a package manifest's name/version match what is expected. `label`
142+ * identifies the manifest in error messages (a directory path or a
143+ * description such as "platform package").
144+ */
145+ function assertManifestMatches ( label , manifest , expectedName , expectedVersion ) {
146+ if ( manifest . name !== expectedName ) {
147+ throw new Error ( `${ label } name is ${ JSON . stringify ( manifest . name ) } , expected ${ JSON . stringify ( expectedName ) } ` ) ;
148+ }
149+ if ( manifest . version !== expectedVersion ) {
150+ throw new Error (
151+ `${ label } version is ${ JSON . stringify ( manifest . version ) } , expected ${ JSON . stringify ( expectedVersion ) } ` ,
152+ ) ;
153+ }
154+ }
155+
143156/**
144157 * Reject any `.node` file inside `<installedMain>/native`. The main package
145158 * tarball excludes `native/*.node` via the `files` array, so a `.node` file
@@ -152,14 +165,7 @@ function rejectEmbeddedNodeFiles(installedMain) {
152165 try {
153166 entries = readdirSync ( nativeDir , { withFileTypes : true } ) ;
154167 } catch ( error ) {
155- if (
156- error !== null &&
157- typeof error === "object" &&
158- "code" in error &&
159- error . code === "ENOENT"
160- ) {
161- return ; // no native/ dir — fine
162- }
168+ if ( isEnoent ( error ) ) return ; // no native/ dir — fine
163169 throw error ;
164170 }
165171 const nodeFiles = entries . filter ( ( e ) => e . name . endsWith ( ".node" ) ) . map ( ( e ) => e . name ) ;
@@ -184,6 +190,29 @@ function errorMessage(error) {
184190 return error instanceof Error ? ( error . stack ?? error . message ) : String ( error ) ;
185191}
186192
193+ function loadAddon ( loaded , label ) {
194+ const addon = isAddon ( loaded ) ? loaded : isAddon ( loaded ?. default ) ? loaded . default : null ;
195+ if ( addon === null ) throw new Error ( `${ label } does not expose compile, validateJson, and dispose` ) ;
196+ return addon ;
197+ }
198+
199+ /** Compiles and validates one fixed plan/input pair, returning the verdict status. */
200+ function exerciseAddon ( addon , label ) {
201+ let handle ;
202+ try {
203+ handle = addon . compile ( PLAN ) ;
204+ if ( ! Number . isInteger ( handle ) ) throw new Error ( `${ label } returned a non-integer plan handle` ) ;
205+
206+ const verdict = addon . validateJson ( handle , INPUT ) ;
207+ if ( verdict === null || typeof verdict !== "object" || verdict . status !== 0 ) {
208+ throw new Error ( `${ label } returned verdict ${ JSON . stringify ( verdict ) } ; expected status 0` ) ;
209+ }
210+ return verdict . status ;
211+ } finally {
212+ if ( Number . isInteger ( handle ) ) addon . dispose ( handle ) ;
213+ }
214+ }
215+
187216// ---------------------------------------------------------------------------
188217// Native verification — resolves the platform package from the installed
189218// main package's dependency graph, never from the source tree or workspace.
@@ -195,14 +224,7 @@ function verifyNative(packageDir, expectedPackageDir, expectedPlatformDir) {
195224 const expectedVersion = expectedManifest . version ;
196225
197226 const manifest = readManifest ( packageDir ) ;
198- if ( manifest . name !== expectedName ) {
199- throw new Error ( `${ packageDir } name is ${ JSON . stringify ( manifest . name ) } , expected ${ JSON . stringify ( expectedName ) } ` ) ;
200- }
201- if ( manifest . version !== expectedVersion ) {
202- throw new Error (
203- `${ packageDir } version is ${ JSON . stringify ( manifest . version ) } , expected ${ JSON . stringify ( expectedVersion ) } ` ,
204- ) ;
205- }
227+ assertManifestMatches ( packageDir , manifest , expectedName , expectedVersion ) ;
206228
207229 // Reject embedded .node files so a host addon inside the main package
208230 // cannot mask optional-dependency selection.
@@ -259,18 +281,7 @@ function verifyNative(packageDir, expectedPackageDir, expectedPlatformDir) {
259281 }
260282 const platformEntryReal = realpathSync ( platformEntry ) ;
261283 const platformManifest = readManifest ( platformDir ) ;
262-
263- // Validate the platform package manifest.
264- if ( platformManifest . name !== pkgName ) {
265- throw new Error (
266- `platform package name is ${ JSON . stringify ( platformManifest . name ) } , expected ${ JSON . stringify ( pkgName ) } ` ,
267- ) ;
268- }
269- if ( platformManifest . version !== expectedVersion ) {
270- throw new Error (
271- `platform package version is ${ JSON . stringify ( platformManifest . version ) } , expected ${ JSON . stringify ( expectedVersion ) } ` ,
272- ) ;
273- }
284+ assertManifestMatches ( "platform package" , platformManifest , pkgName , expectedVersion ) ;
274285
275286 const nodeFile = platformManifest . main ;
276287 if ( typeof nodeFile !== "string" || ! nodeFile . endsWith ( ".node" ) ) {
@@ -310,21 +321,18 @@ function verifyNative(packageDir, expectedPackageDir, expectedPlatformDir) {
310321 throw new Error ( `platform package files must include ${ nodeFile } ` ) ;
311322 }
312323
313- // The resolved entry must be the declared main .node file.
324+ // The resolved entry must be the declared main .node file, and it must
325+ // stay contained within the platform package directory.
314326 const entryBasename = relative ( platformDir , platformEntryReal ) ;
327+ if ( entryBasename === ".." || entryBasename . startsWith ( `..${ sep } ` ) || isAbsolute ( entryBasename ) ) {
328+ throw new Error ( `platform entry ${ platformEntry } resolves outside ${ platformDir } ` ) ;
329+ }
315330 if ( entryBasename !== nodeFile ) {
316331 throw new Error (
317332 `resolved platform entry ${ entryBasename } does not match manifest main ${ nodeFile } ` ,
318333 ) ;
319334 }
320335
321- // Containment: the entry realpath must be inside the platform dir.
322- const fromRoot = relative ( platformDir , platformEntryReal ) ;
323- if ( fromRoot === ".." || fromRoot . startsWith ( `..${ sep } ` ) || isAbsolute ( fromRoot ) ) {
324- throw new Error ( `platform entry ${ platformEntry } resolves outside ${ platformDir } ` ) ;
325- }
326-
327-
328336 // If an expected platform dir is supplied, compare the raw addon SHA.
329337 let sha256 = null ;
330338 if ( expectedPlatformDir !== undefined ) {
@@ -350,27 +358,10 @@ function verifyNative(packageDir, expectedPackageDir, expectedPlatformDir) {
350358 sha256 = installedSha ;
351359 }
352360
353- // Directly load the raw addon from the resolved platform package entry.
354- const loaded = installedRequire ( platformEntry ) ;
355- const addon = isAddon ( loaded ) ? loaded : isAddon ( loaded ?. default ) ? loaded . default : null ;
356- if ( addon === null ) {
357- throw new Error ( `${ nodeFile } does not expose compile, validateJson, and dispose` ) ;
358- }
359-
360- let handle ;
361- let status ;
362- try {
363- handle = addon . compile ( PLAN ) ;
364- if ( ! Number . isInteger ( handle ) ) throw new Error ( `${ nodeFile } returned a non-integer plan handle` ) ;
365-
366- const verdict = addon . validateJson ( handle , INPUT ) ;
367- if ( verdict === null || typeof verdict !== "object" || verdict . status !== 0 ) {
368- throw new Error ( `${ nodeFile } returned verdict ${ JSON . stringify ( verdict ) } ; expected status 0` ) ;
369- }
370- status = verdict . status ;
371- } finally {
372- if ( Number . isInteger ( handle ) ) addon . dispose ( handle ) ;
373- }
361+ // Directly load and exercise the raw addon from the resolved platform
362+ // package entry.
363+ const addon = loadAddon ( installedRequire ( platformEntry ) , nodeFile ) ;
364+ const status = exerciseAddon ( addon , nodeFile ) ;
374365
375366 return {
376367 tool : TOOL ,
@@ -396,14 +387,7 @@ function verifyWasm(packageDir, expectedPackageDir) {
396387 const expectedVersion = expectedManifest . version ;
397388
398389 const manifest = readManifest ( packageDir ) ;
399- if ( manifest . name !== expectedName ) {
400- throw new Error ( `${ packageDir } name is ${ JSON . stringify ( manifest . name ) } , expected ${ JSON . stringify ( expectedName ) } ` ) ;
401- }
402- if ( manifest . version !== expectedVersion ) {
403- throw new Error (
404- `${ packageDir } version is ${ JSON . stringify ( manifest . version ) } , expected ${ JSON . stringify ( expectedVersion ) } ` ,
405- ) ;
406- }
390+ assertManifestMatches ( packageDir , manifest , expectedName , expectedVersion ) ;
407391
408392 requireAbsent ( expectedPackageDir , DEBUG_WASM ) ;
409393 requireAbsent ( packageDir , DEBUG_WASM ) ;
@@ -419,24 +403,8 @@ function verifyWasm(packageDir, expectedPackageDir) {
419403 } ) ;
420404
421405 const entry = regularFile ( packageDir , tierFiles . entry ) ;
422- const loaded = createRequire ( import . meta. url ) ( entry . path ) ;
423- const addon = isAddon ( loaded ) ? loaded : isAddon ( loaded ?. default ) ? loaded . default : null ;
424- if ( addon === null ) throw new Error ( `${ tierFiles . entry } does not expose compile, validateJson, and dispose` ) ;
425-
426- let handle ;
427- let status ;
428- try {
429- handle = addon . compile ( PLAN ) ;
430- if ( ! Number . isInteger ( handle ) ) throw new Error ( `${ tierFiles . entry } returned a non-integer plan handle` ) ;
431-
432- const verdict = addon . validateJson ( handle , INPUT ) ;
433- if ( verdict === null || typeof verdict !== "object" || verdict . status !== 0 ) {
434- throw new Error ( `${ tierFiles . entry } returned verdict ${ JSON . stringify ( verdict ) } ; expected status 0` ) ;
435- }
436- status = verdict . status ;
437- } finally {
438- if ( Number . isInteger ( handle ) ) addon . dispose ( handle ) ;
439- }
406+ const addon = loadAddon ( createRequire ( import . meta. url ) ( entry . path ) , tierFiles . entry ) ;
407+ const status = exerciseAddon ( addon , tierFiles . entry ) ;
440408
441409 return {
442410 tool : TOOL ,
0 commit comments