diff --git a/Cargo.lock b/Cargo.lock index a338b9be..8a7b0fca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -327,6 +327,15 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "convert_case" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "affbf0190ed2caf063e3def54ff444b449371d55c58e513a95ab98eca50adb49" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -402,14 +411,20 @@ dependencies = [ [[package]] name = "ctor" -version = "0.2.9" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" +checksum = "424e0138278faeb2b401f174ad17e715c829512d74f3d1e81eb43365c2e0590e" dependencies = [ - "quote", - "syn 2.0.90", + "ctor-proc-macro", + "dtor", ] +[[package]] +name = "ctor-proc-macro" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52560adf09603e58c9a7ee1fe1dcb95a16927b17c127f0ac02d6e768a0e25bc1" + [[package]] name = "dashmap" version = "5.5.3" @@ -471,6 +486,21 @@ dependencies = [ "dtoa", ] +[[package]] +name = "dtor" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "404d02eeb088a82cfd873006cb713fe411306c7d182c344905e101fb1167d301" +dependencies = [ + "dtor-proc-macro", +] + +[[package]] +name = "dtor-proc-macro" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5" + [[package]] name = "dyn-clone" version = "1.0.17" @@ -526,6 +556,94 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" +[[package]] +name = "futures" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-executor" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" + +[[package]] +name = "futures-macro" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "futures-sink" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "slab", +] + [[package]] name = "getrandom" version = "0.2.15" @@ -744,12 +862,12 @@ checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libloading" -version = "0.8.6" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" +checksum = "754ca22de805bb5744484a5b151a9e1a8e837d5dc232c2d7d8c2e3492edc8b60" dependencies = [ "cfg-if", - "windows-targets", + "windows-link", ] [[package]] @@ -794,7 +912,7 @@ dependencies = [ name = "lightningcss-derive" version = "1.0.0-alpha.43" dependencies = [ - "convert_case", + "convert_case 0.6.0", "proc-macro2", "quote", "syn 1.0.109", @@ -834,7 +952,7 @@ dependencies = [ "jemallocator", "lightningcss-napi", "napi", - "napi-build", + "napi-build 1.2.1", "napi-derive", ] @@ -880,15 +998,17 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "napi" -version = "2.16.13" +version = "3.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "214f07a80874bb96a8433b3cdfc84980d56c7b02e1a0d7ba4ba0db5cef785e2b" +checksum = "e6944d0bf100571cd6e1a98a316cdca262deb6fccf8d93f5ae1502ca3fc88bd3" dependencies = [ "bitflags 2.6.0", "ctor", - "napi-derive", + "futures", + "napi-build 2.3.1", "napi-sys", - "once_cell", + "nohash-hasher", + "rustc-hash", "serde", "serde_json", ] @@ -899,14 +1019,20 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebd4419172727423cf30351406c54f6cc1b354a2cfb4f1dba3e6cd07f6d5522b" +[[package]] +name = "napi-build" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d376940fd5b723c6893cd1ee3f33abbfd86acb1cd1ec079f3ab04a2a3bc4d3b1" + [[package]] name = "napi-derive" -version = "2.16.13" +version = "3.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cbe2585d8ac223f7d34f13701434b9d5f4eb9c332cccce8dee57ea18ab8ab0c" +checksum = "2c914b5e420182bfb73504e0607592cdb8e2e21437d450883077669fb72a114d" dependencies = [ - "cfg-if", - "convert_case", + "convert_case 0.11.0", + "ctor", "napi-derive-backend", "proc-macro2", "quote", @@ -915,28 +1041,32 @@ dependencies = [ [[package]] name = "napi-derive-backend" -version = "1.0.75" +version = "5.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1639aaa9eeb76e91c6ae66da8ce3e89e921cd3885e99ec85f4abacae72fc91bf" +checksum = "f0864cf6a82e2cfb69067374b64c9253d7e910e5b34db833ed7495dda56ccb18" dependencies = [ - "convert_case", - "once_cell", + "convert_case 0.11.0", "proc-macro2", "quote", - "regex", "semver", "syn 2.0.90", ] [[package]] name = "napi-sys" -version = "2.4.0" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "427802e8ec3a734331fec1035594a210ce1ff4dc5bc1950530920ab717964ea3" +checksum = "8eb602b84d7c1edae45e50bbf1374696548f36ae179dfa667f577e384bb90c2b" dependencies = [ "libloading", ] +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + [[package]] name = "nom" version = "7.1.3" @@ -1088,6 +1218,12 @@ dependencies = [ "siphasher", ] +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + [[package]] name = "precomputed-hash" version = "0.1.1" @@ -1332,9 +1468,9 @@ dependencies = [ [[package]] name = "rustc-hash" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "rustix" @@ -1516,6 +1652,12 @@ version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + [[package]] name = "smallvec" version = "1.13.2" @@ -1813,6 +1955,12 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + [[package]] name = "windows-sys" version = "0.59.0" diff --git a/napi/Cargo.toml b/napi/Cargo.toml index 37492595..76e46961 100644 --- a/napi/Cargo.toml +++ b/napi/Cargo.toml @@ -24,10 +24,11 @@ lightningcss = { version = "1.0.0-alpha.71", path = "../", features = [ parcel_sourcemap = { version = "2.1.1", features = ["json"] } serde-detach = "0.0.1" smallvec = { version = "1.7.0", features = ["union"] } -napi = { version = "2", default-features = false, features = [ +napi = { version = "3", default-features = false, features = [ "napi4", "napi5", "serde-json", + "compat-mode" ] } crossbeam-channel = { version = "0.5.6", optional = true } rayon = { version = "1.5.1", optional = true } diff --git a/napi/src/lib.rs b/napi/src/lib.rs index f43a8d46..f6a1f660 100644 --- a/napi/src/lib.rs +++ b/napi/src/lib.rs @@ -11,8 +11,8 @@ use lightningcss::stylesheet::{ MinifyOptions, ParserFlags, ParserOptions, PrinterOptions, PseudoClasses, StyleAttribute, StyleSheet, }; use lightningcss::targets::{Browsers, Features, Targets}; -use napi::bindgen_prelude::{FromNapiValue, ToNapiValue}; -use napi::{CallContext, Env, JsObject, JsUnknown}; +use napi::bindgen_prelude::{BufferSlice, FromNapiValue, JsObjectValue, Null, Object as JsObject, ToNapiValue}; +use napi::{CallContext, Env, JsValue, Unknown as JsUnknown}; use parcel_sourcemap::SourceMap; use serde::{Deserialize, Serialize}; use std::collections::{HashMap, HashSet}; @@ -24,7 +24,6 @@ mod at_rule_parser; mod threadsafe_function; #[cfg(feature = "visitor")] mod transformer; -mod utils; #[cfg(feature = "visitor")] use transformer::JsVisitor; @@ -35,8 +34,6 @@ struct JsVisitor; #[cfg(feature = "visitor")] use lightningcss::visitor::Visit; -use utils::get_named_property; - #[derive(Serialize)] #[serde(rename_all = "camelCase")] struct TransformResult<'i> { @@ -51,32 +48,32 @@ struct TransformResult<'i> { } impl<'i> TransformResult<'i> { - fn into_js(self, env: Env) -> napi::Result { + fn into_js<'env>(self, env: Env) -> napi::Result> { // Manually construct buffers so we avoid a copy and work around // https://github.com/napi-rs/napi-rs/issues/1124. - let mut obj = env.create_object()?; - let buf = env.create_buffer_with_data(self.code)?; - obj.set_named_property("code", buf.into_raw())?; + let mut obj = JsObject::new(&env)?; + let buf = BufferSlice::from_data(&env, self.code)?; + obj.set_named_property("code", buf.into_buffer(&env)?)?; obj.set_named_property( "map", if let Some(map) = self.map { - let buf = env.create_buffer_with_data(map)?; - buf.into_raw().into_unknown() + let buf = BufferSlice::from_data(&env, map)?; + buf.into_buffer(&env)?.into_unknown(&env)? } else { - env.get_null()?.into_unknown() + Null.into_unknown(&env)? }, )?; obj.set_named_property("exports", env.to_js_value(&self.exports)?)?; obj.set_named_property("references", env.to_js_value(&self.references)?)?; obj.set_named_property("dependencies", env.to_js_value(&self.dependencies)?)?; obj.set_named_property("warnings", env.to_js_value(&self.warnings)?)?; - Ok(obj.into_unknown()) + Ok(obj.to_unknown()) } } #[cfg(feature = "visitor")] fn get_visitor(env: Env, opts: &JsObject) -> Option { - if let Ok(visitor) = get_named_property::(opts, "visitor") { + if let Ok(visitor) = opts.get_named_property::("visitor") { Some(JsVisitor::new(env, visitor)) } else { None @@ -88,7 +85,7 @@ fn get_visitor(_env: Env, _opts: &JsObject) -> Option { None } -pub fn transform(ctx: CallContext) -> napi::Result { +pub fn transform<'env>(ctx: CallContext) -> napi::Result> { let opts = ctx.get::(0)?; let mut visitor = get_visitor(*ctx.env, &opts); @@ -102,7 +99,7 @@ pub fn transform(ctx: CallContext) -> napi::Result { } } -pub fn transform_style_attribute(ctx: CallContext) -> napi::Result { +pub fn transform_style_attribute<'env>(ctx: CallContext<'env>) -> napi::Result> { let opts = ctx.get::(0)?; let mut visitor = get_visitor(*ctx.env, &opts); @@ -111,7 +108,7 @@ pub fn transform_style_attribute(ctx: CallContext) -> napi::Result { let res = compile_attr(code, &config, &mut visitor); match res { - Ok(res) => res.into_js(ctx), + Ok(res) => res.into_js(&ctx), Err(err) => Err(err.into_js_error(*ctx.env, Some(code))?), } } @@ -122,9 +119,10 @@ mod bundle { use super::*; use crossbeam_channel::{self, Receiver, Sender}; use lightningcss::bundler::{FileProvider, ResolveResult}; - use napi::{Env, JsBoolean, JsFunction, JsString, NapiRaw}; - use std::path::{Path, PathBuf}; - use std::str::FromStr; + use napi::JsValue; + use napi::bindgen_prelude::JsValuesTupleIntoVec; +use napi::{Env, bindgen_prelude::Function as JsFunction}; + use std::path::Path; use std::sync::Mutex; use threadsafe_function::{ThreadSafeCallContext, ThreadsafeFunction, ThreadsafeFunctionCallMode}; @@ -238,30 +236,30 @@ mod bundle { tx: Sender>, } - fn await_promise(env: Env, result: JsUnknown, tx: Sender>, parse: Cb) -> napi::Result<()> + fn await_promise(env: Env, result: JsUnknown, tx: Sender>, parse: F) -> napi::Result<()> where T: 'static, - Cb: 'static + Fn(JsUnknown) -> Result, + F: 'static + Fn(Env, JsUnknown) -> Result, { // If the result is a promise, wait for it to resolve, and send the result to the channel. // Otherwise, send the result immediately. if result.is_promise()? { - let result: JsObject = result.try_into()?; - let then: JsFunction = get_named_property(&result, "then")?; + let result: JsObject = unsafe { result.cast()? }; + let then: JsFunction = result.get_named_property("then")?; let tx2 = tx.clone(); - let cb = env.create_function_from_closure("callback", move |ctx| { - let res = parse(ctx.get::(0)?)?; + let on_fulfilled = env.create_function_from_closure::<(JsUnknown,), _, _>("callback", move |ctx| { + let res = parse(*ctx.env, ctx.get::(0)?)?; tx.send(Ok(res)).unwrap(); - ctx.env.get_undefined() + Ok(Null) })?; - let eb = env.create_function_from_closure("error_callback", move |ctx| { + let eb = env.create_function_from_closure::<(JsUnknown,), _, _>("error_callback", move |ctx| { let res = ctx.get::(0)?; tx2.send(Err(napi::Error::from(res))).unwrap(); - ctx.env.get_undefined() + Ok(Null) })?; - then.call(Some(&result), &[cb, eb])?; + then.call((on_fulfilled, eb).into_vec(env.raw())?.into_unknown(&env)?)?; } else { - let result = parse(result)?; + let result = parse(env, result)?; tx.send(Ok(result)).unwrap(); } @@ -271,10 +269,8 @@ mod bundle { fn resolve_on_js_thread(ctx: ThreadSafeCallContext) -> napi::Result<()> { let specifier = ctx.env.create_string(&ctx.value.specifier)?; let originating_file = ctx.env.create_string(&ctx.value.originating_file)?; - let result = ctx.callback.unwrap().call(None, &[specifier, originating_file])?; - await_promise(ctx.env, result, ctx.value.tx, move |unknown| { - ctx.env.from_js_value(unknown) - }) + let result = ctx.callback.unwrap().call((specifier, originating_file).into_vec(ctx.env.raw())?.into_unknown(&ctx.env)?)?; + await_promise(ctx.env, result, ctx.value.tx, |env, unknown| env.from_js_value(unknown)) } fn handle_error(tx: Sender>, res: napi::Result<()>) -> napi::Result<()> { @@ -294,10 +290,8 @@ mod bundle { fn read_on_js_thread(ctx: ThreadSafeCallContext) -> napi::Result<()> { let file = ctx.env.create_string(&ctx.value.file)?; - let result = ctx.callback.unwrap().call(None, &[file])?; - await_promise(ctx.env, result, ctx.value.tx, |unknown| { - JsString::try_from(unknown)?.into_utf8()?.into_owned() - }) + let result = ctx.callback.unwrap().call((file).into_vec(ctx.env.raw())?.into_unknown(&ctx.env)?)?; + await_promise(ctx.env, result, ctx.value.tx, |env, unknown| env.from_js_value(unknown)) } fn read_on_js_thread_wrapper(ctx: ThreadSafeCallContext) -> napi::Result<()> { @@ -309,14 +303,14 @@ mod bundle { let opts = ctx.get::(0)?; let visitor = get_visitor(*ctx.env, &opts); - let config: BundleConfig = ctx.env.from_js_value(&opts)?; + let config: BundleConfig = ctx.env.from_js_value(opts)?; - if let Ok(resolver) = get_named_property::(&opts, "resolver") { + if let Ok(resolver) = opts.get_named_property::("resolver") { let read = if resolver.has_named_property("read")? { - let read = get_named_property::(&resolver, "read")?; + let read = resolver.get_named_property::("read")?; Some(ThreadsafeFunction::create( ctx.env.raw(), - unsafe { read.raw() }, + unsafe { ToNapiValue::to_napi_value(ctx.env.raw(), read)? }, 0, read_on_js_thread_wrapper, )?) @@ -325,10 +319,10 @@ mod bundle { }; let resolve = if resolver.has_named_property("resolve")? { - let resolve = get_named_property::(&resolver, "resolve")?; + let resolve = resolver.get_named_property::("resolve")?; Some(ThreadsafeFunction::create( ctx.env.raw(), - unsafe { resolve.raw() }, + unsafe { ToNapiValue::to_napi_value(ctx.env.raw(), resolve)? }, 0, resolve_on_js_thread_wrapper, )?) @@ -342,10 +336,10 @@ mod bundle { inputs: Mutex::new(Vec::new()), }; - run_bundle_task(provider, config, visitor, *ctx.env) + run_bundle_task(provider, config, visitor, ctx.env) } else { let provider = FileProvider::new(); - run_bundle_task(provider, config, visitor, *ctx.env) + run_bundle_task(provider, config, visitor, ctx.env) } } @@ -353,12 +347,12 @@ mod bundle { // because we call back into the JS thread, which might call other tasks in the node threadpool (e.g. fs.readFile), // we may end up deadlocking if the number of rayon threads exceeds node's threadpool size. Therefore, we must // run bundling from a thread not managed by Node. - fn run_bundle_task( + fn run_bundle_task<'env, P: 'static + SourceProvider>( provider: P, config: BundleConfig, visitor: Option, - env: Env, - ) -> napi::Result + env: &'env Env, + ) -> napi::Result> where P::Error: IntoJsError, { @@ -424,7 +418,7 @@ mod bundle { mod bundle { use super::*; use lightningcss::bundler::ResolveResult; - use napi::{Env, JsFunction, JsString, NapiRaw, NapiValue, Ref}; + use napi::{Env, bindgen_prelude::{Function as JsFunction}, JsString, NapiValue, Ref}; use std::cell::UnsafeCell; use std::path::Path; @@ -432,10 +426,10 @@ mod bundle { let opts = ctx.get::(0)?; let mut visitor = get_visitor(*ctx.env, &opts); - let resolver = get_named_property::(&opts, "resolver")?; - let read = get_named_property::(&resolver, "read")?; + let resolver = opts.get_named_property::("resolver")?; + let read = resolver.get_named_property::("read")?; let resolve = if resolver.has_named_property("resolve")? { - let resolve = get_named_property::(&resolver, "resolve")?; + let resolve = resolver.get_named_property::("resolve")?; Some(ctx.env.create_reference(resolve)?) } else { None @@ -524,9 +518,9 @@ mod bundle { fn read<'a>(&'a self, file: &Path) -> Result<&'a str, Self::Error> { let read: JsFunction = self.env.get_reference_value_unchecked(&self.read)?; let file = self.env.create_string(file.to_str().unwrap())?; - let source: JsUnknown = read.call(None, &[file])?; + let source: JsUnknown = read.call((file,))?; let source = get_result(self.env, source)?; - let source: JsString = source.try_into()?; + let source: JsString = unsafe { source.cast()? }; let source = source.into_utf8()?.into_owned()?; // cache the result @@ -544,7 +538,7 @@ mod bundle { let resolve: JsFunction = self.env.get_reference_value_unchecked(resolve)?; let specifier = self.env.create_string(specifier)?; let originating_file = self.env.create_string(originating_file.to_str().unwrap())?; - let result: JsUnknown = resolve.call(None, &[specifier, originating_file])?; + let result: JsUnknown = resolve.call((specifier, originating_file))?; let result = get_result(self.env, result)?; let result = self.env.from_js_value(result)?; Ok(result) @@ -967,15 +961,15 @@ struct AttrResult<'i> { } impl<'i> AttrResult<'i> { - fn into_js(self, ctx: CallContext) -> napi::Result { + fn into_js<'env>(self, ctx: &CallContext<'env>) -> napi::Result> { // Manually construct buffers so we avoid a copy and work around // https://github.com/napi-rs/napi-rs/issues/1124. - let mut obj = ctx.env.create_object()?; - let buf = ctx.env.create_buffer_with_data(self.code)?; - obj.set_named_property("code", buf.into_raw())?; + let mut obj = JsObject::new(&ctx.env)?; + let buf = BufferSlice::from_data(&ctx.env, self.code)?; + obj.set_named_property("code", buf.into_buffer(&ctx.env))?; obj.set_named_property("dependencies", ctx.env.to_js_value(&self.dependencies)?)?; obj.set_named_property("warnings", ctx.env.to_js_value(&self.warnings)?)?; - Ok(obj.into_unknown()) + Ok(obj.to_unknown()) } } @@ -1078,7 +1072,7 @@ impl<'i, E: IntoJsError + std::error::Error> CompileError<'i, E> { CompileError::PrinterError(Error { kind, .. }) => env.to_js_value(kind)?, CompileError::MinifyError(Error { kind, .. }) => env.to_js_value(kind)?, CompileError::BundleError(Error { kind, .. }) => env.to_js_value(kind)?, - _ => env.get_null()?.into_unknown(), + _ => Null.into_unknown(&env)?, }; let (js_error, loc) = match self { @@ -1094,16 +1088,16 @@ impl<'i, E: IntoJsError + std::error::Error> CompileError<'i, E> { | CompileError::MinifyError(Error { loc, .. }) | CompileError::BundleError(Error { loc, .. }) => { // Generate an error with location information. - let syntax_error = env.get_global()?.get_named_property::("SyntaxError")?; + let syntax_error = env.get_global()?.get_named_property::("SyntaxError")?; let reason = env.create_string_from_std(reason)?; - let obj = syntax_error.new_instance(&[reason])?; - (obj.into_unknown(), loc) + let obj = syntax_error.new_instance(reason.to_unknown())?; + (obj.into_unknown(&env)?, loc) } _ => return Ok(self.into()), }; if js_error.get_type()? == napi::ValueType::Object { - let mut obj: JsObject = unsafe { js_error.cast() }; + let mut obj: JsObject = unsafe { js_error.cast()? }; if let Some(loc) = loc { let line = env.create_int32((loc.line + 1) as i32)?; let col = env.create_int32(loc.column as i32)?; @@ -1113,35 +1107,35 @@ impl<'i, E: IntoJsError + std::error::Error> CompileError<'i, E> { let source = env.create_string(code)?; obj.set_named_property("source", source)?; } - let mut loc = env.create_object()?; + let mut loc = JsObject::new(&env)?; loc.set_named_property("line", line)?; loc.set_named_property("column", col)?; obj.set_named_property("loc", loc)?; } obj.set_named_property("data", data)?; - Ok(obj.into_unknown().into()) + Ok(napi::Error::from(obj.to_unknown())) } else { - Ok(js_error.into()) + Ok(napi::Error::from(js_error)) } } } trait IntoJsError { - fn into_js_error(self, env: Env) -> napi::Result; + fn into_js_error<'env>(self, env: Env) -> napi::Result>; } impl IntoJsError for std::io::Error { - fn into_js_error(self, env: Env) -> napi::Result { + fn into_js_error<'env>(self, env: Env) -> napi::Result> { let reason = self.to_string(); - let syntax_error = env.get_global()?.get_named_property::("SyntaxError")?; + let syntax_error = env.get_global()?.get_named_property::("SyntaxError")?; let reason = env.create_string_from_std(reason)?; - let obj = syntax_error.new_instance(&[reason])?; - Ok(obj.into_unknown()) + let obj = syntax_error.new_instance(reason.to_unknown())?; + Ok(obj) } } impl IntoJsError for napi::Error { - fn into_js_error(self, env: Env) -> napi::Result { + fn into_js_error<'env>(self, env: Env) -> napi::Result> { unsafe { JsUnknown::from_napi_value(env.raw(), ToNapiValue::to_napi_value(env.raw(), self)?) } } } diff --git a/napi/src/threadsafe_function.rs b/napi/src/threadsafe_function.rs index 45ac6ec1..c2b9665a 100644 --- a/napi/src/threadsafe_function.rs +++ b/napi/src/threadsafe_function.rs @@ -11,15 +11,16 @@ use std::ptr; use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use std::sync::Arc; +use napi::bindgen_prelude::FromNapiValue; use napi::{check_status, sys, Env, Result, Status}; -use napi::{JsError, JsFunction, NapiValue}; +use napi::{JsError, bindgen_prelude::Function as JsFunction}; /// ThreadSafeFunction Context object /// the `value` is the value passed to `call` method -pub struct ThreadSafeCallContext { +pub struct ThreadSafeCallContext<'env, T: 'static> { pub env: Env, pub value: T, - pub callback: Option, + pub callback: Option>, } #[repr(u8)] @@ -128,7 +129,7 @@ impl ThreadsafeFunction { let s = "napi_rs_threadsafe_function"; let len = s.len(); let s = CString::new(s)?; - check_status!(unsafe { sys::napi_create_string_utf8(env, s.as_ptr(), len, &mut async_resource_name) })?; + check_status!(unsafe { sys::napi_create_string_utf8(env, s.as_ptr(), len as isize, &mut async_resource_name) })?; let initial_thread_count = 1usize; let mut raw_tsfn = ptr::null_mut(); @@ -232,7 +233,7 @@ unsafe extern "C" fn call_js_cb( callback: if js_callback.is_null() { None } else { - Some(JsFunction::from_raw(raw_env, js_callback).unwrap()) // TODO: unwrap + Some(JsFunction::from_napi_value(raw_env, js_callback).unwrap()) // TODO: unwrap }, }) }); @@ -262,7 +263,7 @@ unsafe extern "C" fn call_js_cb( sys::napi_create_string_utf8( raw_env, error_code_string.as_ptr() as *const _, - error_code_string.len(), + error_code_string.len() as isize, &mut error_code_value, ), sys::Status::napi_ok, @@ -273,7 +274,7 @@ unsafe extern "C" fn call_js_cb( sys::napi_create_string_utf8( raw_env, error_msg.as_ptr() as *const _, - error_msg.len(), + error_msg.len() as isize, &mut error_msg_value, ), sys::Status::napi_ok, diff --git a/napi/src/transformer.rs b/napi/src/transformer.rs index bab931f2..36921c2e 100644 --- a/napi/src/transformer.rs +++ b/napi/src/transformer.rs @@ -20,39 +20,45 @@ use lightningcss::{ visitor::{Visit, VisitTypes, Visitor}, }; use lightningcss::{stylesheet::StyleSheet, traits::IntoOwned}; -use napi::{Env, JsFunction, JsObject, JsUnknown, Ref, ValueType}; +use napi::{ + Env, Ref, Unknown as JsUnknown, ValueType, + bindgen_prelude::{FromNapiValue, Function as JsFunction, JsObjectValue, JsValuesTupleIntoVec, Object as JsObject, ToNapiValue}, +}; use serde::{Deserialize, Serialize}; use smallvec::SmallVec; -use crate::{at_rule_parser::AtRule, utils::get_named_property}; +use crate::at_rule_parser::AtRule; + +type JsFn = JsFunction<'static, JsUnknown<'static>, JsUnknown<'static>>; +type JsObj = JsObject<'static>; pub struct JsVisitor { env: Env, - visit_stylesheet: VisitorsRef, - visit_rule: VisitorsRef, - rule_map: VisitorsRef, - property_map: VisitorsRef, - visit_declaration: VisitorsRef, - visit_length: Option>, - visit_angle: Option>, - visit_ratio: Option>, - visit_resolution: Option>, - visit_time: Option>, - visit_color: Option>, - visit_image: VisitorsRef, - visit_url: Option>, - visit_media_query: VisitorsRef, - visit_supports_condition: VisitorsRef, - visit_custom_ident: Option>, - visit_dashed_ident: Option>, - visit_selector: Option>, - visit_token: VisitorsRef, - token_map: VisitorsRef, - visit_function: VisitorsRef, - function_map: VisitorsRef, - visit_variable: VisitorsRef, - visit_env: VisitorsRef, - env_map: VisitorsRef, + visit_stylesheet: Visitors>, + visit_rule: Visitors>, + rule_map: Visitors>, + property_map: Visitors>, + visit_declaration: Visitors>, + visit_length: Option>, + visit_angle: Option>, + visit_ratio: Option>, + visit_resolution: Option>, + visit_time: Option>, + visit_color: Option>, + visit_image: Visitors>, + visit_url: Option>, + visit_media_query: Visitors>, + visit_supports_condition: Visitors>, + visit_custom_ident: Option>, + visit_dashed_ident: Option>, + visit_selector: Option>, + visit_token: Visitors>, + token_map: Visitors>, + visit_function: Visitors>, + function_map: Visitors>, + visit_variable: Visitors>, + visit_env: Visitors>, + env_map: Visitors>, types: VisitTypes, } @@ -66,8 +72,6 @@ enum VisitStage { Exit, } -type VisitorsRef = Visitors>; - struct Visitors { enter: Option, exit: Option, @@ -86,33 +90,40 @@ impl Visitors { } } -impl Visitors> { - fn get(&self, env: &Env) -> Visitors { +impl Visitors> +where + T: FromNapiValue, +{ + fn get(&self, env: &Env) -> Visitors { Visitors { - enter: self.enter.as_ref().and_then(|p| env.get_reference_value_unchecked(p).ok()), - exit: self.exit.as_ref().and_then(|p| env.get_reference_value_unchecked(p).ok()), + enter: self.enter.as_ref().and_then(|p| p.get_value(env).ok()), + exit: self.exit.as_ref().and_then(|p| p.get_value(env).ok()), } } } -impl Visitors { - fn named(&self, stage: VisitStage, name: &str) -> Option { +impl Visitors { + fn named(&self, stage: VisitStage, name: &str) -> Option> { self .for_stage(stage) - .and_then(|m| get_named_property::(m, name).ok()) + .and_then(|m| m.get_named_property::(name).ok()) } - fn custom(&self, stage: VisitStage, obj: &str, name: &str) -> Option { + fn custom(&self, stage: VisitStage, obj: &str, name: &str) -> Option> { self .for_stage(stage) .and_then(|m| m.get_named_property::(obj).ok()) .and_then(|v| { match v.get_type() { - Ok(ValueType::Function) => return v.try_into().ok(), + Ok(ValueType::Function) => { + // SAFETY: type is checked above via get_type + return unsafe { v.cast::() }.ok(); + } Ok(ValueType::Object) => { - let o: napi::Result = v.try_into(); + // SAFETY: type is checked above via get_type + let o: napi::Result = unsafe { v.cast() }; if let Ok(o) = o { - return get_named_property::(&o, name).ok(); + return o.get_named_property::(name).ok(); } } _ => {} @@ -128,7 +139,7 @@ impl Drop for JsVisitor { macro_rules! drop { ($id: ident) => { if let Some(v) = &mut self.$id { - drop(v.unref(self.env)); + drop(v.unref(&self.env)); } }; } @@ -136,10 +147,10 @@ impl Drop for JsVisitor { macro_rules! drop_tuple { ($id: ident) => { if let Some(v) = &mut self.$id.enter { - drop(v.unref(self.env)); + drop(v.unref(&self.env)); } if let Some(v) = &mut self.$id.exit { - drop(v.unref(self.env)); + drop(v.unref(&self.env)); } }; } @@ -177,7 +188,7 @@ impl JsVisitor { let mut types = VisitTypes::empty(); macro_rules! get { ($name: literal, $( $t: ident )|+) => {{ - let res: Option = get_named_property(&visitor, $name).ok(); + let res: Option = visitor.get_named_property($name).ok(); if res.is_some() { types |= $( VisitTypes::$t )|+; @@ -185,54 +196,54 @@ impl JsVisitor { // We must create a reference so that the garbage collector doesn't destroy // the function before we try to call it (in the async bundle case). - res.and_then(|res| env.create_reference(res).ok()) + res.as_ref().and_then(|res| Ref::new(&env, res).ok()) }}; } macro_rules! map { ($name: literal, $( $t: ident )|+) => {{ - let obj: Option = get_named_property(&visitor, $name).ok(); + let obj: Option = visitor.get_named_property($name).ok(); if obj.is_some() { types |= $( VisitTypes::$t )|+; } - obj.and_then(|obj| env.create_reference(obj).ok()) + obj.as_ref().and_then(|obj| Ref::new(&env, obj).ok()) }}; } Self { env, - visit_stylesheet: VisitorsRef::new(get!("StyleSheet", RULES), get!("StyleSheetExit", RULES)), - visit_rule: VisitorsRef::new(get!("Rule", RULES), get!("RuleExit", RULES)), - rule_map: VisitorsRef::new(map!("Rule", RULES), get!("RuleExit", RULES)), - visit_declaration: VisitorsRef::new(get!("Declaration", PROPERTIES), get!("DeclarationExit", PROPERTIES)), - property_map: VisitorsRef::new(map!("Declaration", PROPERTIES), map!("DeclarationExit", PROPERTIES)), + visit_stylesheet: Visitors::new(get!("StyleSheet", RULES), get!("StyleSheetExit", RULES)), + visit_rule: Visitors::new(get!("Rule", RULES), get!("RuleExit", RULES)), + rule_map: Visitors::new(map!("Rule", RULES), map!("RuleExit", RULES)), + visit_declaration: Visitors::new(get!("Declaration", PROPERTIES), get!("DeclarationExit", PROPERTIES)), + property_map: Visitors::new(map!("Declaration", PROPERTIES), map!("DeclarationExit", PROPERTIES)), visit_length: get!("Length", LENGTHS), visit_angle: get!("Angle", ANGLES), visit_ratio: get!("Ratio", RATIOS), visit_resolution: get!("Resolution", RESOLUTIONS), visit_time: get!("Time", TIMES), visit_color: get!("Color", COLORS), - visit_image: VisitorsRef::new(get!("Image", IMAGES), get!("ImageExit", IMAGES)), + visit_image: Visitors::new(get!("Image", IMAGES), get!("ImageExit", IMAGES)), visit_url: get!("Url", URLS), - visit_media_query: VisitorsRef::new( + visit_media_query: Visitors::new( get!("MediaQuery", MEDIA_QUERIES), get!("MediaQueryExit", MEDIA_QUERIES), ), - visit_supports_condition: VisitorsRef::new( + visit_supports_condition: Visitors::new( get!("SupportsCondition", SUPPORTS_CONDITIONS), get!("SupportsConditionExit", SUPPORTS_CONDITIONS), ), - visit_variable: VisitorsRef::new(get!("Variable", TOKENS), get!("VariableExit", TOKENS)), - visit_env: VisitorsRef::new( + visit_variable: Visitors::new(get!("Variable", TOKENS), get!("VariableExit", TOKENS)), + visit_env: Visitors::new( get!("EnvironmentVariable", TOKENS | MEDIA_QUERIES | ENVIRONMENT_VARIABLES), get!( "EnvironmentVariableExit", TOKENS | MEDIA_QUERIES | ENVIRONMENT_VARIABLES ), ), - env_map: VisitorsRef::new( + env_map: Visitors::new( map!("EnvironmentVariable", TOKENS | MEDIA_QUERIES | ENVIRONMENT_VARIABLES), map!( "EnvironmentVariableExit", @@ -241,11 +252,11 @@ impl JsVisitor { ), visit_custom_ident: get!("CustomIdent", CUSTOM_IDENTS), visit_dashed_ident: get!("DashedIdent", DASHED_IDENTS), - visit_function: VisitorsRef::new(get!("Function", TOKENS), get!("FunctionExit", TOKENS)), - function_map: VisitorsRef::new(map!("Function", TOKENS), map!("FunctionExit", TOKENS)), + visit_function: Visitors::new(get!("Function", TOKENS), get!("FunctionExit", TOKENS)), + function_map: Visitors::new(map!("Function", TOKENS), map!("FunctionExit", TOKENS)), visit_selector: get!("Selector", SELECTORS), - visit_token: VisitorsRef::new(get!("Token", TOKENS), None), - token_map: VisitorsRef::new(map!("Token", TOKENS), None), + visit_token: Visitors::new(get!("Token", TOKENS), None), + token_map: Visitors::new(map!("Token", TOKENS), None), types, } } @@ -261,7 +272,7 @@ impl<'i> Visitor<'i, AtRule<'i>> for JsVisitor { fn visit_stylesheet<'o>(&mut self, stylesheet: &mut StyleSheet<'i, 'o, AtRule<'i>>) -> Result<(), Self::Error> { if self.types.contains(VisitTypes::RULES) { let env = self.env; - let visit_stylesheet = self.visit_stylesheet.get::(&env); + let visit_stylesheet = self.visit_stylesheet.get(&env); if let Some(visit) = visit_stylesheet.for_stage(VisitStage::Enter) { call_visitor(&env, stylesheet, visit)? } @@ -284,8 +295,8 @@ impl<'i> Visitor<'i, AtRule<'i>> for JsVisitor { ) -> Result<(), Self::Error> { if self.types.contains(VisitTypes::RULES) { let env = self.env; - let rule_map = self.rule_map.get::(&env); - let visit_rule = self.visit_rule.get::(&env); + let rule_map = self.rule_map.get(&env); + let visit_rule = self.visit_rule.get(&env); visit_list( rules, @@ -319,7 +330,7 @@ impl<'i> Visitor<'i, AtRule<'i>> for JsVisitor { let name = v.name.as_ref(); if let Some(visit) = rule_map.custom(stage, "unknown", name) { let js_value = env.to_js_value(v)?; - let res = visit.call(None, &[js_value])?; + let res = visit.call(js_value)?; return env.from_js_value(res).map(serde_detach::detach); } else { "unknown" @@ -329,7 +340,7 @@ impl<'i> Visitor<'i, AtRule<'i>> for JsVisitor { let name = c.name.as_ref(); if let Some(visit) = rule_map.custom(stage, "custom", name) { let js_value = env.to_js_value(c)?; - let res = visit.call(None, &[js_value])?; + let res = visit.call(js_value)?; return env.from_js_value(res).map(serde_detach::detach); } else { "custom" @@ -340,7 +351,7 @@ impl<'i> Visitor<'i, AtRule<'i>> for JsVisitor { if let Some(visit) = rule_map.named(stage, name).as_ref().or(visit_rule.for_stage(stage)) { let js_value = env.to_js_value(value)?; - let res = visit.call(None, &[js_value])?; + let res = visit.call((js_value).into_vec(env.raw())?.into_unknown(&env)?)?; env.from_js_value(res).map(serde_detach::detach) } else { Ok(None) @@ -361,20 +372,17 @@ impl<'i> Visitor<'i, AtRule<'i>> for JsVisitor { ) -> Result<(), Self::Error> { if self.types.contains(VisitTypes::PROPERTIES) { let env = self.env; - let property_map = self.property_map.get::(&env); - let visit_declaration = self.visit_declaration.get::(&env); + let visit_declaration = self.visit_declaration.get(&env); visit_declaration_list( &env, &mut decls.important_declarations, &visit_declaration, - &property_map, |property| property.visit_children(self), )?; visit_declaration_list( &env, &mut decls.declarations, &visit_declaration, - &property_map, |property| property.visit_children(self), )?; Ok(()) @@ -423,13 +431,13 @@ impl<'i> Visitor<'i, AtRule<'i>> for JsVisitor { fn visit_media_list(&mut self, media: &mut lightningcss::media_query::MediaList<'i>) -> Result<(), Self::Error> { if self.types.contains(VisitTypes::MEDIA_QUERIES) { let env = self.env; - let visit_media_query = self.visit_media_query.get::(&env); + let visit_media_query = self.visit_media_query.get(&env); visit_list( &mut media.media_queries, |value, stage| { if let Some(visit) = visit_media_query.for_stage(stage) { let js_value = env.to_js_value(value)?; - let res = visit.call(None, &[js_value])?; + let res = visit.call(js_value)?; env.from_js_value(res).map(serde_detach::detach) } else { Ok(None) @@ -445,19 +453,19 @@ impl<'i> Visitor<'i, AtRule<'i>> for JsVisitor { fn visit_media_feature_value(&mut self, value: &mut MediaFeatureValue<'i>) -> Result<(), Self::Error> { if self.types.contains(VisitTypes::ENVIRONMENT_VARIABLES) && matches!(value, MediaFeatureValue::Env(_)) { - let env_map = self.env_map.get::(&self.env); - let visit_env = self.visit_env.get::(&self.env); + let env_map = self.env_map.get(&self.env); + let visit_env = self.visit_env.get(&self.env); let call = |stage: VisitStage, value: &mut MediaFeatureValue, env: &Env| -> napi::Result<()> { let env_var = if let MediaFeatureValue::Env(env) = value { env } else { return Ok(()); }; - let visit_type = env_map.named(stage, env_var.name.name()); + let visit_type = env_map.named(stage, env_var.name.name()); let visit = visit_env.for_stage(stage); let new_value: Option = if let Some(visit) = visit_type.as_ref().or(visit) { let js_value = env.to_js_value(env_var)?; - let res = visit.call(None, &[js_value])?; + let res = visit.call(js_value)?; env.from_js_value(res).map(serde_detach::detach)? } else { None @@ -520,11 +528,11 @@ impl<'i> Visitor<'i, AtRule<'i>> for JsVisitor { if let Some(visit) = self .visit_selector .as_ref() - .and_then(|v| self.env.get_reference_value_unchecked::(v).ok()) + .and_then(|v| v.get_value(&self.env).ok()) { map::<_, _, _, true>(&mut selectors.0, |value| { let js_value = self.env.to_js_value(value)?; - let res = visit.call(None, &[js_value])?; + let res = visit.call(js_value)?; self.env.from_js_value(res).map(serde_detach::detach) })?; } @@ -538,13 +546,13 @@ impl<'i> Visitor<'i, AtRule<'i>> for JsVisitor { ) -> Result<(), Self::Error> { if self.types.contains(VisitTypes::TOKENS) { let env = self.env; - let visit_token = self.visit_token.get::(&env); - let token_map = self.token_map.get::(&env); - let visit_function = self.visit_function.get::(&env); - let function_map = self.function_map.get::(&env); - let visit_variable = self.visit_variable.get::(&env); - let visit_env = self.visit_env.get::(&env); - let env_map = self.env_map.get::(&env); + let visit_token = self.visit_token.get(&env); + let token_map = self.token_map.get(&env); + let visit_function = self.visit_function.get(&env); + let function_map = self.function_map.get(&env); + let visit_variable = self.visit_variable.get(&env); + let visit_env = self.visit_env.get(&env); + let env_map = self.env_map.get(&env); visit_list( &mut tokens.0, @@ -587,7 +595,7 @@ impl<'i> Visitor<'i, AtRule<'i>> for JsVisitor { _ => unreachable!(), }; - let res = visit.call(None, &[js_value])?; + let res = visit.call(js_value)?; let res: Option = env.from_js_value(res).map(serde_detach::detach)?; Ok(res.map(|r| r.0)) } else { @@ -607,11 +615,11 @@ impl<'i> Visitor<'i, AtRule<'i>> for JsVisitor { fn visit>( env: &Env, value: &mut V, - visit: &Option>, + visit: &Option>, ) -> napi::Result<()> { if let Some(visit) = visit .as_ref() - .and_then(|v| env.get_reference_value_unchecked::(v).ok()) + .and_then(|v| v.get_value(env).ok()) { call_visitor(env, value, &visit)?; } @@ -625,7 +633,7 @@ fn call_visitor>( visit: &JsFunction, ) -> napi::Result<()> { let js_value = env.to_js_value(value)?; - let res = visit.call(None, &[js_value])?; + let res = visit.call(js_value)?; let new_value: Option = env.from_js_value(res).map(serde_detach::detach)?; match new_value { Some(new_value) => *value = new_value, @@ -639,29 +647,15 @@ fn visit_declaration_list<'i, C: FnMut(&mut Property<'i>) -> napi::Result<()>>( env: &Env, list: &mut Vec>, visit_declaration: &Visitors, - property_map: &Visitors, visit_children: C, ) -> napi::Result<()> { visit_list( list, |value, stage| { - // Use a specific property visitor if available, or fall back to Property visitor. - let visit = match value { - Property::Custom(v) => { - if let Some(visit) = property_map.custom(stage, "custom", v.name.as_ref()) { - let js_value = env.to_js_value(v)?; - let res = visit.call(None, &[js_value])?; - return env.from_js_value(res).map(serde_detach::detach); - } else { - None - } - } - _ => property_map.named(stage, value.property_id().name()), - }; - - if let Some(visit) = visit.as_ref().or(visit_declaration.for_stage(stage)) { + // Use the Declaration visitor if available. + if let Some(visit) = visit_declaration.for_stage(stage) { let js_value = env.to_js_value(value)?; - let res = visit.call(None, &[js_value])?; + let res = visit.call((js_value).into_vec(env.raw())?.into_unknown(&env)?)?; env.from_js_value(res).map(serde_detach::detach) } else { Ok(None) diff --git a/napi/src/utils.rs b/napi/src/utils.rs deleted file mode 100644 index 90ac1495..00000000 --- a/napi/src/utils.rs +++ /dev/null @@ -1,7 +0,0 @@ -use napi::{Error, JsObject, JsUnknown, Result}; - -// Workaround for https://github.com/napi-rs/napi-rs/issues/1641 -pub fn get_named_property>(obj: &JsObject, property: &str) -> Result { - let unknown = obj.get_named_property::(property)?; - T::try_from(unknown) -} diff --git a/node/Cargo.toml b/node/Cargo.toml index 2e809cfe..dad58c29 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -13,10 +13,10 @@ lightningcss-napi = { version = "0.4.8", path = "../napi", features = [ "bundler", "visitor", ] } -napi = { version = "2.15.4", default-features = false, features = [ +napi = { version = "3", default-features = false, features = [ "compat-mode", ] } -napi-derive = "2" +napi-derive = { version = "3", features = ["compat-mode"] } [target.'cfg(target_os = "macos")'.dependencies] jemallocator = { version = "0.3.2", features = ["disable_initial_exec_tls"] } diff --git a/node/src/lib.rs b/node/src/lib.rs index 82294412..d247910a 100644 --- a/node/src/lib.rs +++ b/node/src/lib.rs @@ -2,32 +2,34 @@ #[global_allocator] static GLOBAL: jemallocator::Jemalloc = jemallocator::Jemalloc; -use napi::{CallContext, JsObject, JsUnknown}; +#[cfg(not(target_arch = "wasm32"))] +use napi::bindgen_prelude::Object; +use napi::{CallContext, Unknown, bindgen_prelude::JsObjectValue}; use napi_derive::js_function; #[js_function(1)] -fn transform(ctx: CallContext) -> napi::Result { +fn transform(ctx: CallContext) -> napi::Result { lightningcss_napi::transform(ctx) } #[js_function(1)] -fn transform_style_attribute(ctx: CallContext) -> napi::Result { +fn transform_style_attribute(ctx: CallContext) -> napi::Result { lightningcss_napi::transform_style_attribute(ctx) } #[js_function(1)] -pub fn bundle(ctx: CallContext) -> napi::Result { +pub fn bundle(ctx: CallContext) -> napi::Result { lightningcss_napi::bundle(ctx) } #[cfg(not(target_arch = "wasm32"))] #[js_function(1)] -pub fn bundle_async(ctx: CallContext) -> napi::Result { +pub fn bundle_async(ctx: CallContext) -> napi::Result { lightningcss_napi::bundle_async(ctx) } -#[cfg_attr(not(target_arch = "wasm32"), napi_derive::module_exports)] -fn init(mut exports: JsObject) -> napi::Result<()> { +#[cfg_attr(not(target_arch = "wasm32"), napi_derive::napi(module_exports))] +fn init(mut exports: Object) -> napi::Result<()> { exports.create_named_method("transform", transform)?; exports.create_named_method("transformStyleAttribute", transform_style_attribute)?; exports.create_named_method("bundle", bundle)?; @@ -43,9 +45,9 @@ fn init(mut exports: JsObject) -> napi::Result<()> { #[no_mangle] pub fn register_module() { unsafe fn register(raw_env: napi::sys::napi_env, raw_exports: napi::sys::napi_value) -> napi::Result<()> { - use napi::{Env, JsObject, NapiValue}; + use napi::{Env, bindgen_prelude::Object, NapiValue}; - let exports = JsObject::from_raw_unchecked(raw_env, raw_exports); + let exports = Object::from_raw_unchecked(raw_env, raw_exports); init(exports) }