External
External
(opens in a new tab)
与在 Class 内部中使用的 Object Wrap
(opens in a new tab) 非常相似。
Object Wrap
附加一个原生值到一个 JavaScript 对象上,并且可以在这个对象被 GC 回收时通知你,
External
创建一个空的 JavaScript 对象,它在内部保存了原生值。只会在将对象传回 Rust 时生效:
lib.rs
use napi::bindgen_prelude::*;
use napi_derive::napi;
#[napi]
fn create_source_map(length: u32) -> External<Buffer> {
External::new(vec![0; length as usize].into())
}
⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️
index.d.ts
export class ExternalObject<T> {
readonly '': {
readonly '': unique symbol
[K: symbol]: T
}
}
export function createSourceMap(length: number): ExternalObject<Buffer>
当你想要返回一个包含一些与原生 Rust 代码交互的方法的 JavaScript 对象时,External
是非常有用的,
这里是一个真实的例子:
https://github.com/h-a-n-a/magic-string-rs/blob/v0.3.0/node/src/lib.rs#L96-L103 (opens in a new tab)
https://github.com/h-a-n-a/magic-string-rs/blob/v0.3.0/node/index.js#L7-L23 (opens in a new tab)
lib.rs
impl MagicString {
#[napi(ts_return_type = "{ toString: () => string, toUrl: () => string }")]
pub fn generate_map(
&mut self,
options: Option<magic_string::GenerateDecodedMapOptions>,
) -> Result<External<SourceMap>> {
let external = create_external(self.0.generate_map(options.unwrap_or_default())?);
Ok(external)
}
/// @internal
#[napi]
pub fn to_sourcemap_string(&mut self, sourcemap: External<SourceMap>) -> Result<String> {
Ok((*sourcemap.as_ref()).to_string()?)
}
/// @internal
#[napi]
pub fn to_sourcemap_url(&mut self, sourcemap: External<SourceMap>) -> Result<String> {
Ok((*sourcemap.as_ref()).to_url()?)
}
}
首先,generate_map
方法返回一个 External
对象,然后 JavaScript 函数在闭包中保存 External
对象:
index.js
module.exports.MagicString = class MagicString extends MagicStringNative {
generateMap(options) {
const sourcemap = super.generateMap({
file: null,
source: null,
sourceRoot: null,
includeContent: false,
...options,
})
const toString = () => super.toSourcemapString(sourcemap)
const toUrl = () => super.toSourcemapUrl(sourcemap)
return {
toString,
toUrl,
}
}
}