From d874a4664748d3013c64d2f3f022c5cd6f8624a8 Mon Sep 17 00:00:00 2001 From: liuyi Date: Tue, 3 Jun 2025 19:19:29 +0800 Subject: [PATCH] fix: type generation for shared libs (#2684) --- cli/src/api/build.ts | 259 ++++++------------ .../__snapshots__/config.spec.ts.snap | Bin 790 -> 813 bytes .../__snapshots__/target.spec.ts.snap | Bin 1254 -> 1314 bytes .../__snapshots__/typegen.spec.ts.md | 18 +- .../__snapshots__/typegen.spec.ts.snap | Bin 4257 -> 4195 bytes .../__snapshots__/version.spec.ts.snap | Bin 411 -> 414 bytes cli/src/utils/misc.ts | 19 +- cli/src/utils/typegen.ts | 42 +-- crates/backend/src/typegen.rs | 5 +- crates/macro/Cargo.toml | 2 +- crates/macro/src/expand.rs | 2 + crates/macro/src/expand/napi.rs | 131 +-------- crates/macro/src/expand/typedef.rs | 9 + crates/macro/src/expand/typedef/noop.rs | 4 + crates/macro/src/expand/typedef/typedef.rs | 62 +++++ .../__tests__/__snapshots__/values.spec.ts.md | 7 +- .../__snapshots__/values.spec.ts.snap | Bin 6601 -> 6627 bytes examples/napi/index.d.cts | 7 +- 18 files changed, 206 insertions(+), 361 deletions(-) create mode 100644 crates/macro/src/expand/typedef.rs create mode 100644 crates/macro/src/expand/typedef/noop.rs create mode 100644 crates/macro/src/expand/typedef/typedef.rs diff --git a/cli/src/api/build.ts b/cli/src/api/build.ts index 56e30e37..1373ec17 100644 --- a/cli/src/api/build.ts +++ b/cli/src/api/build.ts @@ -1,18 +1,11 @@ import { spawn } from 'node:child_process' import { createHash } from 'node:crypto' -import { - existsSync, - mkdirSync, - unlinkSync, - readFileSync, - writeFileSync, -} from 'node:fs' +import { existsSync, mkdirSync, rmSync } from 'node:fs' import { createRequire } from 'node:module' -import { tmpdir, homedir } from 'node:os' +import { homedir } from 'node:os' import { parse, join, resolve } from 'node:path' import * as colors from 'colorette' -import { groupBy, split } from 'lodash-es' import { include as setjmpInclude, lib as setjmpLib } from 'wasm-sjlj' import { BuildOptions as RawBuildOptions } from '../def/build.js' @@ -37,6 +30,8 @@ import { tryInstallCargoBinary, unlinkAsync, writeFileAsync, + dirExistsAsync, + readdirAsync, } from '../utils/index.js' import { createCjsBinding, createEsmBinding } from './templates/index.js' @@ -53,22 +48,14 @@ const debug = debugFactory('build') const require = createRequire(import.meta.url) type OutputKind = 'js' | 'dts' | 'node' | 'exe' | 'wasm' -type Output = { - kind: OutputKind - path: string -} +type Output = { kind: OutputKind; path: string } -type BuildOptions = RawBuildOptions & { - cargoOptions?: string[] -} +type BuildOptions = RawBuildOptions & { cargoOptions?: string[] } export async function buildProject(options: BuildOptions) { debug('napi build command receive options: %O', options) - options = { - dtsCache: true, - ...options, - } + options = { dtsCache: true, ...options } const cwd = options.cwd ?? process.cwd() @@ -92,13 +79,6 @@ export async function buildProject(options: BuildOptions) { ) } - const depsNapiPackages = pkg.dependencies - .map((p) => metadata.packages.find((c) => c.name === p.name)) - .filter( - (c): c is Crate => - c != null && c.dependencies.some((d) => d.name == 'napi-derive'), - ) - const crateDir = parse(pkg.manifest_path).dir const builder = new Builder( @@ -121,7 +101,6 @@ export async function buildProject(options: BuildOptions) { ), options.configPath ? resolvePath(options.configPath) : undefined, ), - depsNapiPackages, ) return builder.build() @@ -141,7 +120,6 @@ class Builder { private readonly outputDir: string, private readonly targetDir: string, private readonly config: NapiConfig, - private readonly depsNapiPackages: Crate[], ) {} get cdyLibName() { @@ -323,10 +301,7 @@ class Builder { const command = process.env.CARGO ?? (this.options.useCross ? 'cross' : 'cargo') const buildProcess = spawn(command, this.args, { - env: { - ...process.env, - ...this.envs, - }, + env: { ...process.env, ...this.envs }, stdio: watch ? ['inherit', 'inherit', 'pipe'] : 'inherit', cwd: this.cwd, signal: controller.signal, @@ -342,11 +317,7 @@ class Builder { }) buildProcess.once('error', (e) => { - reject( - new Error(`Build failed with error: ${e.message}`, { - cause: e, - }), - ) + reject(new Error(`Build failed with error: ${e.message}`, { cause: e })) }) // watch mode only, they are piped through stderr @@ -477,76 +448,8 @@ class Builder { } private setEnvs() { - // type definition intermediate file - this.envs.TYPE_DEF_TMP_PATH = this.getIntermediateTypeFile() - // Validate the packages and dependencies - if (existsSync(this.envs.TYPE_DEF_TMP_PATH)) { - const { depsNapiPackages, crate } = this - let shouldInvalidateSelf = false - const content = readFileSync(this.envs.TYPE_DEF_TMP_PATH, 'utf-8') - const typedefRaw = content - .split('\n') - .filter((line) => line.trim().length) - .map((line) => { - const [pkgName, ...jsonContents] = split(line, ':') - return { - pkgName, - jsonContent: jsonContents.join(':'), - } - }) - const groupedTypedefRaw = groupBy(typedefRaw, ({ pkgName }) => pkgName) - const invalidPackages = new Set() - for (const [pkgName, value] of Object.entries(groupedTypedefRaw)) { - const packageInvalidKey = `NAPI_PACKAGE_${pkgName.toUpperCase().replaceAll('-', '_')}_INVALID` - let done = false - for (const { jsonContent } of value) { - try { - // package_name: { "done": true } was written by napi-build in project build.rs - // if it exists, the package was successfully built and typedef was written - const json = JSON.parse(jsonContent) - if (json.done === true) { - done = true - break - } - } catch { - done = false - break - } - } - if (!done) { - process.env[packageInvalidKey] = `${Date.now()}` - shouldInvalidateSelf = true - invalidPackages.add(pkgName) - } - } - const typedefPackages = new Set(Object.keys(groupedTypedefRaw)) - for (const crate of depsNapiPackages) { - if (!typedefPackages.has(crate.name)) { - debug('Set invalid package typedef: %i', crate.name) - shouldInvalidateSelf = true - process.env[ - `NAPI_PACKAGE_${crate.name.toUpperCase().replaceAll('-', '_')}_INVALID` - ] = `${Date.now()}` - } - } - if (shouldInvalidateSelf) { - debug('Set invalid package typedef: %i', crate.name) - process.env[ - `NAPI_PACKAGE_${crate.name.toUpperCase().replaceAll('-', '_')}_INVALID` - ] = `${Date.now()}` - } - // clean invalid packages typedef - if (invalidPackages.size) { - debug('Clean invalid packages typedef: %O', invalidPackages) - writeFileSync( - this.envs.TYPE_DEF_TMP_PATH, - typedefRaw - .filter(({ pkgName }) => !invalidPackages.has(pkgName)) - .map(({ pkgName, jsonContent }) => `${pkgName}:${jsonContent}`) - .join('\n'), - ) - } - } + // folder for intermediate type definition files + this.envs.TYPE_DEF_TMP_FOLDER = this.generateIntermediateTypeDefFolder() // RUSTFLAGS let rustflags = @@ -725,22 +628,25 @@ class Builder { return this } - private getIntermediateTypeFile() { - const dtsPath = join( - tmpdir(), + private generateIntermediateTypeDefFolder() { + let folder = join( + this.targetDir, + 'napi-rs', `${this.crate.name}-${createHash('sha256') .update(this.crate.manifest_path) .update(CLI_VERSION) .digest('hex') - .substring(0, 8)}.napi_type_def`, + .substring(0, 8)}`, ) + if (!this.options.dtsCache) { - try { - unlinkSync(dtsPath) - } catch {} - return `${dtsPath}_${Date.now()}.tmp` + rmSync(folder, { recursive: true, force: true }) + folder += `_${Date.now()}` } - return `${dtsPath}.tmp` + + mkdirAsync(folder, { recursive: true }) + + return folder } private async postBuild() { @@ -838,9 +744,7 @@ class Builder { }) return wasmBinaryName ? join(this.outputDir, wasmBinaryName) : null } catch (e) { - throw new Error('Failed to copy artifact', { - cause: e, - }) + throw new Error('Failed to copy artifact', { cause: e }) } } @@ -889,41 +793,76 @@ class Builder { } private async generateTypeDef() { - if (!(await fileExists(this.envs.TYPE_DEF_TMP_PATH))) { + const typeDefDir = this.envs.TYPE_DEF_TMP_FOLDER + if (!(await dirExistsAsync(typeDefDir))) { return [] } const dest = join(this.outputDir, this.options.dts ?? 'index.d.ts') - const { dts, exports } = await processTypeDef( - this.envs.TYPE_DEF_TMP_PATH, - this.options.constEnum ?? this.config.constEnum ?? true, - !this.options.noDtsHeader - ? (this.options.dtsHeader ?? - (this.config.dtsHeaderFile - ? await readFileAsync( - join(this.cwd, this.config.dtsHeaderFile), - 'utf-8', - ).catch(() => { - debug.warn( - `Failed to read dts header file ${this.config.dtsHeaderFile}`, - ) - return null - }) - : null) ?? - this.config.dtsHeader ?? - DEFAULT_TYPE_DEF_HEADER) - : '', - ) + let header = '' + let dts = '' + let exports: string[] = [] + + if (!this.options.noDtsHeader) { + if (this.options.dtsHeader) { + header = this.options.dtsHeader + } else if (this.config.dtsHeaderFile) { + try { + header = await readFileAsync( + join(this.cwd, this.config.dtsHeaderFile), + 'utf-8', + ) + } catch (e) { + debug.warn( + `Failed to read dts header file ${this.config.dtsHeaderFile}`, + e, + ) + } + } else { + header = DEFAULT_TYPE_DEF_HEADER + } + } + + const files = await readdirAsync(typeDefDir, { withFileTypes: true }) + + if (!files.length) { + debug('No type def files found. Skip generating dts file.') + return [] + } + + for (const file of files) { + if (!file.isFile()) { + continue + } + + const { dts: fileDts, exports: fileExports } = await processTypeDef( + join(typeDefDir, file.name), + this.options.constEnum ?? this.config.constEnum ?? true, + ) + + dts += fileDts + exports.push(...fileExports) + } + + if (dts.indexOf('ExternalObject<') > -1) { + header += ` +export declare class ExternalObject { + readonly '': { + readonly '': unique symbol + [K: symbol]: T + } +} +` + } + + dts = header + dts try { debug('Writing type def to:') debug(' %i', dest) await writeFileAsync(dest, dts, 'utf-8') - this.outputs.push({ - kind: 'dts', - path: dest, - }) + this.outputs.push({ kind: 'dts', path: dest }) } catch (e) { debug.error('Failed to write type def file') debug.error(e as Error) @@ -956,10 +895,7 @@ class Builder { debug('Writing js binding to:') debug(' %i', dest) await writeFileAsync(dest, binding, 'utf-8') - return { - kind: 'js', - path: dest, - } satisfies Output + return { kind: 'js', path: dest } satisfies Output } catch (e) { throw new Error('Failed to write js binding file', { cause: e }) } @@ -1029,26 +965,11 @@ class Builder { `export * from '${this.config.packageName}-wasm32-wasi'\n`, ) return [ - { - kind: 'js', - path: bindingPath, - }, - { - kind: 'js', - path: browserBindingPath, - }, - { - kind: 'js', - path: workerPath, - }, - { - kind: 'js', - path: browserWorkerPath, - }, - { - kind: 'js', - path: browserEntryPath, - }, + { kind: 'js', path: bindingPath }, + { kind: 'js', path: browserBindingPath }, + { kind: 'js', path: workerPath }, + { kind: 'js', path: browserWorkerPath }, + { kind: 'js', path: browserEntryPath }, ] satisfies Output[] } return [] diff --git a/cli/src/utils/__tests__/__snapshots__/config.spec.ts.snap b/cli/src/utils/__tests__/__snapshots__/config.spec.ts.snap index 38093d0501307b08a9f0ae9d12831b289c82ff6c..d542d762cc92ccd589dff434507cf7e3c945649e 100644 GIT binary patch literal 813 zcmV+|1Je9KRzVbRCTm-J{(*Ibk$iXqHGSL@c#U z`*)QLy&sDR00000000B+mA!A%Kp4iK*FHO;UrE)1kYI?A*y^@GsgNpF6uOiFh6f?dol_-;ApadU|m zt>MMM6?P!F7nIyESX(a?c*y7UJ1SC$ev~GC62LS70pJOMO#nOJ?E%vJNxzX_w9JsG zVP>;gP%lUWWiUX>AgLg&pStq4;Qs1$Ubd2@RA>dEEsB!oG2xZ3I<_UkWJMKT8PrGg z6+p7sU5B_9xI)U1Z0#Fo>wx90BtLJSJd+BwA%J zZJO9N0WS!6Nx<90U7PZKz8a;jS(!{GJ{nbOmx;E0e%jS1iyWjBsTIo)Y*!@zwb9|x z;ZaamT&^K8XF<^oLw;8a;fGsA4rJBM%GT;jXdNg2217j5Cu%>Uu9~;eoLHh6sMB!Ib1WmNktVjI z0Ux4|LkA}Gy-yL_^Ayz{hn}biI=KDVk*Mu)*8G%%8cnonr~|EvzPkN{>el}$RBpjK z5~{yKs4g<#CIjv=;8}a2dc%PC41fll(SR8Zxc3Kys>J|p9tqVy`J(?kipKr&uZHQV r!?a2*;SBPqnN|w*N(0_$K#vZb`;7|K`amUlYT4#D_<|LkRSf_DU+abe literal 790 zcmV+x1L^!hRzVXx4s5>iE=OBrCO5ULo; z#lEC&owH>-Z7RV~5DQ}CFK9Ow)U7j9CuSxPf{Fpb06P+&oj9}?w}~i-A8Mjce!lzO zd-t8+-CL`a9oJk89;~y_4jtAQ59ZyvW9en4)3U?#(A9lLE!}i^#jffV->vB$H5X}> zjV%N&w*yW+_=Lggnq|?D&T4mMDJw-k(nqvOJf{E-JOws@ZD5#aLqxk-USMWONZTwH zixL@-h$@i+IGGV5<7J5C$~LF|$_-j$$xt?AL1^=;z&yge+BL^!JWNJpj7VgVkZ;JF z4EDD~T!#iBLNc{8S@8;F+J+yDx3ePPDESdE8&bc@!XQ$u%wl2=cmk{wL2YKYTF|#Z zc?rA%-X(Okvh>xX-rC*uP#*+5vMGqo1_w&%2U9&cQl zm;sq$?`Exz$8jQ)Yu9Vz@uwyM@o@v0%a+iaa(|)q# zfrARtEb1d)kBV|lw$T|_P&3?8Lp=-{Ne-OkZB*pP=x}H_XWH(oNZEB2H7|#Jltk*` z>&HYwx^8Eam)UQjNv|61p;twxZm&jl`~PfIuEh=;)nC!5E&{iJd%*MVjp{8Z9{>sG z?-Vc%-2VfODy4un4ja`!d87Zl6qWk5Uo9rz5|b8MkTXJ~#iVtp*C@sJKpx%c>~HK) U=^HAvr_^PB2l#>&omCA003!r*fB*mh diff --git a/cli/src/utils/__tests__/__snapshots__/target.spec.ts.snap b/cli/src/utils/__tests__/__snapshots__/target.spec.ts.snap index c96c0ce42843632ef43fefa77278994e5166a79c..fcec5bf4ff74d785b91d3159fc1071ea9a7e7297 100644 GIT binary patch literal 1314 zcmV+-1>O2VRzV&-0$0nyl1HC;a(yPQz_foVl(3bgfw_Z?D^)?`&^)ZoT4c zFV#HHDK#o5UB7DA{pni6pFdkJ+YS5h=;;Us!AHbIp#eM%oC014-UQwT-UmJcz5u=h zegdun*MPr(n1H;1Z31=(*ezh6e5PlGHsN{pNg=w*G)+VTkw+wjcvQ&6lS0f35JJj} zfgF+Y_drIZ92)@+XU!I#TE`{cq9vxS$H`M?`7et zYO_MNEjhR?2NOAPa`0*nKF=w(Y{>R^4x)LuJr57(;Y1$J?!4bFR3!(9MtneXQDCJ(ngI9gxcG z>@Y}N3@@*6ZSHb4t0$_pR<*+?eSO%XGfltpAH!Ko;d-pE(B0CTu5Ij#=g*eb0I%g% zckLV$PX>4K!s{z|8@qV*QnBS$%e9u@ajm@4B6DlqHxiw`5l*b&shggd?ai#|TbN&*TgBxzpx|w_y_wku!zI@B_TfwfFYW&TTDT6n><$#tZM{gB zn)|(}LELH~hrBvkORkQ^9_xn&wM4w(?$~y%ysN~URd?3$d|T~ls~p!>XIw9rUhOZ7 zal_5+egn?%T)#BC#={`nK7mf^{)6t;PUNxD3T9p3yMMi2TA#bWOx&MtYrWQTydbvX ztOuXJYwvyP&ew!bChpI-u^qR9TT09JZ`x7xmhI2@PCV%@!yJbAR~oJAqP=`xZyW7~-k-4-TAfC1*3>LppKV))+0bXJ zEz8oY?Zz3yZfYhf+V=8lt){iLp zYv4Ng8$=~S@?bC659Ywb?3$dF!ez_S&PbB06h$FYoJe^hB_!!FiA@f*3?)fSUZOI< zm0>2&Q7JR|4V4il13{XI$wO4em^7)3GkKB91e0r2CYdaTAX7{p zr83RrOH?XMUZyg`mz}iK@o!|&)feR7N77}c0D7gwkQ9|~Cqu^|mvxNoQrzrUx z{0hP`Lhc6D7-y3O+X_nF1|NYR0f`fGAkNt$f~|&<)8JL`F8B_}3C-aPo&z5yIa^$?{f3h3AekcM9`FQsImOu$g6$KOdlwf-nCClI<_zL_E_GdU-TCmko(g3f6_rMPzndNMX zU^|SGM?nR=0^SGLcw0uW?a2{x8z=)Eyav9=aki{r`v)bVJR!G(N5CRDpXY2ju>(+Y z6$A@}+yNd3FBUjkUa(z4$rZ2$q#~LJ94~UV!p*i6+o=@P1PXK~Lth28iotX+#eEaf ztm=aMA*@+Tr8%x5YBscXy=5)A7v!2|^^7K0rnqHg3|KyV#J!#zRI8(gmIvpB`>~+W zn<>qynu)8bJI!|IiD=E5)iP>61ErjDKZ%NNqK47z^wr@+n?<7fRI@XAt}vU_XDY?H zLprc3PS54q?dIw<7n`kK)5*tt9@#=m9lP-#hs&%FH)4J+-7TZj4UC@g>~3`m@$lpy zJm5DTD|X|F^K1hE>6BbUpg_?rr~Fq`~(_n zkib%v9ZsgPR>;T3;VacRos}B2M&Hk-vC9dy4SUAabER+O^4>3Yj|}F$T}<9m zk-DYp72EI8m2k?vn`#FaX*kcMeHAh^p=Bm(EM?GGbX*^uRWM5PrLp@ehNo1==Y{&F zD~26-s!w5lcy6g1-2fMF2DRM>#TIkD9y#Omq5U6%7H$OH@D8}7dq*W*Z}xgpY2BnD z$9#3ntb27-N6arA)GXpn?~Vi4)_0Xyr)hL`%hvckZNlR^;~du;4bSf{!@BX#ZLb3^ zVi|U|JLSV5J6Hi{XzzpWR;Th*bqi;m=exgYR=4NfpAGDtZpLi&bc@zv*|s5{eelqI z{GCrF9~;;^-_AkZ7T!{Nn!V|cBBNl*`}7+%&W0!YU`Ta@g^RUkU8QPTde_i<_p9v% QOV?`lziTT Snapshot 1 - `␊ - export declare class ExternalObject {␊ - readonly '': {␊ - readonly '': unique symbol␊ - [K: symbol]: T␊ - }␊ - }␊ - /**␊ + `/**␊ * \`constructor\` option for \`struct\` requires all fields to be public,␊ * otherwise tag impl fn as constructor␊ * #[napi(constructor)]␊ @@ -620,14 +613,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 - `␊ - export declare class ExternalObject {␊ - readonly '': {␊ - readonly '': unique symbol␊ - [K: symbol]: T␊ - }␊ - }␊ - /**␊ + `/**␊ * \`constructor\` option for \`struct\` requires all fields to be public,␊ * otherwise tag impl fn as constructor␊ * #[napi(constructor)]␊ diff --git a/cli/src/utils/__tests__/__snapshots__/typegen.spec.ts.snap b/cli/src/utils/__tests__/__snapshots__/typegen.spec.ts.snap index 9d88ad1136bf412f456832be4902aeabd139450d..bd57fa11c522d5caf6010d34144f341c9a868325 100644 GIT binary patch literal 4195 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 F006PF#-#uN diff --git a/cli/src/utils/misc.ts b/cli/src/utils/misc.ts index 27549ce8..53a5cd17 100644 --- a/cli/src/utils/misc.ts +++ b/cli/src/utils/misc.ts @@ -7,19 +7,11 @@ import { stat, readdir, } from 'node:fs' -import { createRequire } from 'node:module' import { promisify } from 'node:util' +import pkgJson from '../../package.json' with { type: 'json' } import { debug } from './log.js' -const require = createRequire(import.meta.url) -// NOTE: -// import pkgJson from '@napi-rs/cli/package.json' assert { type: 'json' } -// is experimental feature now, avoid using it. -// see: https://nodejs.org/api/esm.html#import-assertions -// eslint-disable-next-line import/no-extraneous-dependencies -const pkgJson = require('@napi-rs/cli/package.json') - export const readFileAsync = promisify(readFile) export const writeFileAsync = promisify(writeFile) export const unlinkAsync = promisify(unlink) @@ -35,6 +27,15 @@ export async function fileExists(path: string) { return exists } +export async function dirExistsAsync(path: string) { + try { + const stats = await statAsync(path) + return stats.isDirectory() + } catch { + return false + } +} + export function pick(o: O, ...keys: K[]): Pick { return keys.reduce((acc, key) => { acc[key] = o[key] diff --git a/cli/src/utils/typegen.ts b/cli/src/utils/typegen.ts index 731587bd..d2eed68c 100644 --- a/cli/src/utils/typegen.ts +++ b/cli/src/utils/typegen.ts @@ -1,4 +1,4 @@ -import { sortBy, unionWith, isEqual } from 'lodash-es' +import { sortBy } from 'lodash-es' import { readFileAsync } from './misc.js' @@ -85,14 +85,11 @@ function exportDeclare(ambient: boolean): string { export async function processTypeDef( intermediateTypeFile: string, constEnum: boolean, - header?: string, ) { const exports: string[] = [] const defs = await readIntermediateTypeFile(intermediateTypeFile) const groupedDefs = preprocessTypeDef(defs) - header = header ?? '' - const dts = sortBy(Array.from(groupedDefs), ([namespace]) => namespace) .map(([namespace, defs]) => { @@ -130,41 +127,22 @@ export async function processTypeDef( }) .join('\n\n') + '\n' - if (dts.indexOf('ExternalObject<') > -1) { - header += ` -export declare class ExternalObject { - readonly '': { - readonly '': unique symbol - [K: symbol]: T - } -} -` - } - return { - dts: header + dts, + dts, exports, } } async function readIntermediateTypeFile(file: string) { const content = await readFileAsync(file, 'utf8') - const defs = unionWith( - content - .split('\n') - .filter(Boolean) - .map((line) => { - line = line.trim() - if (!line.startsWith('{')) { - // crateName:{ "def": "", ... } - const start = line.indexOf(':') + 1 - line = line.slice(start) - } - return JSON.parse(line) as TypeDefLine - }) - .filter((def) => !!def.kind), - (a, b) => isEqual(a, b), - ) + + const defs = content + .split('\n') + .filter(Boolean) + .map((line) => { + line = line.trim() + return JSON.parse(line) as TypeDefLine + }) // move all `struct` def to the very top // and order the rest alphabetically. diff --git a/crates/backend/src/typegen.rs b/crates/backend/src/typegen.rs index f677f43b..12cfb3ca 100644 --- a/crates/backend/src/typegen.rs +++ b/crates/backend/src/typegen.rs @@ -103,7 +103,6 @@ fn escape_json(src: &str) -> String { impl Display for TypeDef { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - let pkg_name = std::env::var("CARGO_PKG_NAME").expect("CARGO_PKG_NAME is not set"); let js_mod = if let Some(js_mod) = &self.js_mod { format!(", \"js_mod\": \"{}\"", js_mod) } else { @@ -115,11 +114,9 @@ impl Display for TypeDef { "".to_string() }; - let prefix = format!("{}:", pkg_name); write!( f, - r#"{}{{"kind": "{}", "name": "{}", "js_doc": "{}", "def": "{}"{}{}}}"#, - prefix, + r#"{{"kind": "{}", "name": "{}", "js_doc": "{}", "def": "{}"{}{}}}"#, self.kind, self.name, escape_json(&self.js_doc), diff --git a/crates/macro/Cargo.toml b/crates/macro/Cargo.toml index d9981362..822ff115 100644 --- a/crates/macro/Cargo.toml +++ b/crates/macro/Cargo.toml @@ -23,7 +23,7 @@ type-def = ["napi-derive-backend/type-def", "ctor"] [dependencies] convert_case = "0.8" -ctor = { version = "0.4", features = ["dtor"], optional = true } +ctor = { version = "0.4", optional = true } napi-derive-backend = { version = "2.0.0-beta.3", path = "../backend" } proc-macro2 = "1" quote = "1" diff --git a/crates/macro/src/expand.rs b/crates/macro/src/expand.rs index 9809baec..1a8d3222 100644 --- a/crates/macro/src/expand.rs +++ b/crates/macro/src/expand.rs @@ -1,3 +1,5 @@ +mod typedef; + #[cfg(feature = "noop")] mod noop; #[cfg(feature = "noop")] diff --git a/crates/macro/src/expand/napi.rs b/crates/macro/src/expand/napi.rs index a68fcb8c..e8448686 100644 --- a/crates/macro/src/expand/napi.rs +++ b/crates/macro/src/expand/napi.rs @@ -1,18 +1,9 @@ -#[cfg(feature = "type-def")] -use std::env; -#[cfg(feature = "type-def")] -use std::fs; -#[cfg(feature = "type-def")] -use std::io::{BufWriter, Write}; -#[cfg(feature = "type-def")] -use std::sync::atomic::{AtomicBool, Ordering}; - +use super::typedef; use crate::parser::{attrs::BindgenAttrs, ParseNapi}; use napi_derive_backend::{BindgenResult, TryToTokens}; -#[cfg(feature = "type-def")] -use napi_derive_backend::{Napi, ToTypeDef}; use proc_macro2::TokenStream; use quote::ToTokens; +use std::sync::atomic::{AtomicBool, Ordering}; use syn::{Attribute, Item}; /// a flag indicate whether or never at least one `napi` macro has been expanded. @@ -24,52 +15,17 @@ use syn::{Attribute, Item}; /// } /// /// ``` -#[cfg(feature = "type-def")] static BUILT_FLAG: AtomicBool = AtomicBool::new(false); -#[cfg(feature = "type-def")] -#[ctor::dtor] -fn dtor() { - if let Ok(ref type_def_file) = env::var("TYPE_DEF_TMP_PATH") { - let package_name = std::env::var("CARGO_PKG_NAME").expect("CARGO_PKG_NAME is not set"); - - if let Ok(f) = fs::OpenOptions::new() - .read(true) - .append(true) - .open(type_def_file) - { - let mut writer = BufWriter::::new(f); - if let Err(err) = writer - .write_all(format!("{package_name}:{{\"done\": true}}\n").as_bytes()) - .and_then(|_| writer.flush()) - { - eprintln!( - "Failed to write type def file for `{package_name}`: {:?}", - err - ); - } - } - } -} - pub fn expand(attr: TokenStream, input: TokenStream) -> BindgenResult { - #[cfg(feature = "type-def")] - if BUILT_FLAG - .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) - .is_ok() + // logic on first macro expansion + if let Ok(built) = BUILT_FLAG.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) { - // logic on first macro expansion - prepare_type_def_file(); - - if let Ok(wasi_register_file) = env::var("WASI_REGISTER_TMP_PATH") { - if let Err(_e) = remove_existed_def_file(&wasi_register_file) { - #[cfg(debug_assertions)] - { - println!("Failed to manipulate wasi register file: {:?}", _e); - } - } + if !built { + typedef::prepare_type_def_file(); } } + let mut item = syn::parse2::(input)?; let opts: BindgenAttrs = syn::parse2(attr)?; let mut tokens = proc_macro2::TokenStream::new(); @@ -110,11 +66,7 @@ pub fn expand(attr: TokenStream, input: TokenStream) -> BindgenResult BindgenResult::new(file); - writer.write_all(type_def.to_string().as_bytes())?; - writer.write_all("\n".as_bytes())?; - writer.flush() - }) - .unwrap_or_else(|e| { - println!("Failed to write type def file: {:?}", e); - }); - } - } -} - fn replace_napi_attr_in_mod( js_namespace: String, attrs: &mut Vec, @@ -198,43 +125,3 @@ fn replace_napi_attr_in_mod( None } } - -#[cfg(feature = "type-def")] -fn prepare_type_def_file() { - if let Ok(ref type_def_file) = env::var("TYPE_DEF_TMP_PATH") { - if let Err(_e) = remove_existed_def_file(type_def_file) { - #[cfg(debug_assertions)] - { - println!("Failed to manipulate type def file: {:?}", _e); - } - } - } -} - -#[cfg(feature = "type-def")] -fn remove_existed_def_file(def_file: &str) -> std::io::Result<()> { - use std::io::{BufRead, BufReader}; - - let pkg_name = std::env::var("CARGO_PKG_NAME").expect("CARGO_PKG_NAME is not set"); - if let Ok(content) = std::fs::File::open(def_file) { - let reader = BufReader::new(content); - let cleaned_content = reader - .lines() - .filter_map(|line| { - if let Ok(line) = line { - if let Some((package_name, _)) = line.split_once(':') { - if pkg_name == package_name { - return None; - } - } - Some(line) - } else { - None - } - }) - .collect::>() - .join("\n"); - std::fs::write(def_file, format!("{cleaned_content}\n"))?; - } - Ok(()) -} diff --git a/crates/macro/src/expand/typedef.rs b/crates/macro/src/expand/typedef.rs new file mode 100644 index 00000000..12eb603b --- /dev/null +++ b/crates/macro/src/expand/typedef.rs @@ -0,0 +1,9 @@ +#[cfg(feature = "type-def")] +pub mod typedef; +#[cfg(feature = "type-def")] +pub use self::typedef::*; + +#[cfg(not(feature = "type-def"))] +pub mod noop; +#[cfg(not(feature = "type-def"))] +pub use self::noop::*; diff --git a/crates/macro/src/expand/typedef/noop.rs b/crates/macro/src/expand/typedef/noop.rs new file mode 100644 index 00000000..e6ffc2d0 --- /dev/null +++ b/crates/macro/src/expand/typedef/noop.rs @@ -0,0 +1,4 @@ +use napi_derive_backend::Napi; + +pub fn prepare_type_def_file() {} +pub fn output_type_def(_napi: &Napi) {} diff --git a/crates/macro/src/expand/typedef/typedef.rs b/crates/macro/src/expand/typedef/typedef.rs new file mode 100644 index 00000000..7568c711 --- /dev/null +++ b/crates/macro/src/expand/typedef/typedef.rs @@ -0,0 +1,62 @@ +use std::cell::LazyCell; +use std::env; +use std::env::VarError; +use std::fs; +use std::io::{BufWriter, Write}; +use std::path::PathBuf; + +use napi_derive_backend::{Napi, ToTypeDef}; + +const PKG_NAME: LazyCell = + LazyCell::new(|| env::var("CARGO_PKG_NAME").expect("Expected `CARGO_PKG_NAME` to be set")); +const TYPE_DEF_FOLDER: LazyCell> = + LazyCell::new(|| env::var("TYPE_DEF_TMP_FOLDER")); + +fn get_type_def_file() -> Option { + if let Ok(folder) = TYPE_DEF_FOLDER.as_deref() { + let file = PathBuf::from(folder).join(&*PKG_NAME); + Some(file) + } else { + if let Ok(_) = env::var("TYPE_DEF_TMP_PATH") { + panic!("Expected `TYPE_DEF_TMP_FOLDER` to be set. It may caused by an older version of '@napi-rs/cli' used. Please upgrade to the latest version."); + } + None + } +} + +pub fn prepare_type_def_file() { + remove_existed_def_file(); +} + +fn remove_existed_def_file() { + if let Some(file) = get_type_def_file() { + if file.exists() { + if let Err(_e) = fs::remove_file(&file) { + #[cfg(debug_assertions)] + { + println!("Failed to manipulate type def file {:?}: {:?}", file, _e); + } + } + } + } +} + +pub fn output_type_def(napi: &Napi) { + if let Some(file) = get_type_def_file() { + if let Some(type_def) = napi.to_type_def() { + fs::OpenOptions::new() + .append(true) + .create(true) + .open(&file) + .and_then(|file| { + let mut writer = BufWriter::::new(file); + writer.write_all(type_def.to_string().as_bytes())?; + writer.write_all("\n".as_bytes())?; + writer.flush() + }) + .unwrap_or_else(|e| { + println!("Failed to write type def file: {:?}", e); + }); + } + } +} diff --git a/examples/napi/__tests__/__snapshots__/values.spec.ts.md b/examples/napi/__tests__/__snapshots__/values.spec.ts.md index 12bf8a5c..aef4c7d2 100644 --- a/examples/napi/__tests__/__snapshots__/values.spec.ts.md +++ b/examples/napi/__tests__/__snapshots__/values.spec.ts.md @@ -824,10 +824,6 @@ Generated by [AVA](https://avajs.dev). ␊ export declare function setSymbolInObj(symbol: symbol): object␊ ␊ - export interface Shared {␊ - value: number␊ - }␊ - ␊ export declare function shorterEscapableScope(createString: () => string | null): string␊ ␊ export declare function shorterScope(arr: unknown[]): Array␊ @@ -1022,4 +1018,7 @@ Generated by [AVA](https://avajs.dev). export function xxh128(input: Buffer): bigint␊ export function xxh3_64(input: Buffer): bigint␊ }␊ + export interface Shared {␊ + value: number␊ + }␊ ` diff --git a/examples/napi/__tests__/__snapshots__/values.spec.ts.snap b/examples/napi/__tests__/__snapshots__/values.spec.ts.snap index a2a3fdd5dec90708271505eaa8446cf58d929b20..23547d135a3a8a149d48dcb500ffd68d35d7f947 100644 GIT binary patch literal 6627 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 literal 6601 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 string | null): string export declare function shorterScope(arr: unknown[]): Array @@ -984,3 +980,6 @@ export declare namespace xxh3 { export function xxh128(input: Buffer): bigint export function xxh3_64(input: Buffer): bigint } +export interface Shared { + value: number +}