feat(napi): support musl linux
drop future executor due to mutithreads bug.
This commit is contained in:
parent
7958ed88a4
commit
28257b45c1
14 changed files with 106 additions and 309 deletions
3
.dockerignore
Normal file
3
.dockerignore
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
target
|
||||||
|
test_module/target
|
||||||
|
node_modules
|
27
.github/workflows/docker.yaml
vendored
Normal file
27
.github/workflows/docker.yaml
vendored
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
name: Docker nightly build
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 1 * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build_image:
|
||||||
|
name: Build rust-nodejs-alpine:lts
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Log in to registry
|
||||||
|
uses: actions/docker/login@master
|
||||||
|
env:
|
||||||
|
DOCKER_REGISTRY_URL: docker.pkg.github.com
|
||||||
|
DOCKER_USERNAME: ${{ github.actor }}
|
||||||
|
DOCKER_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Build docker image
|
||||||
|
run: |
|
||||||
|
docker build . -f Dockerfile.alpine --pull --no-cache -t docker.pkg.github.com/napi-rs/napi-rs/rust-nodejs-alpine:lts
|
||||||
|
|
||||||
|
- name: Push docker image
|
||||||
|
run: docker push docker.pkg.github.com/napi-rs/napi-rs/rust-nodejs-alpine:lts
|
45
.github/workflows/linux-musl.yaml
vendored
Normal file
45
.github/workflows/linux-musl.yaml
vendored
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
name: Musl
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: stable - x86_64-unknown-linux-musl - node@${{ matrix.node }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
node: ['10', '12', '13', '14']
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Log in to registry
|
||||||
|
run: |
|
||||||
|
docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD $DOCKER_REGISTRY_URL
|
||||||
|
env:
|
||||||
|
DOCKER_REGISTRY_URL: docker.pkg.github.com
|
||||||
|
DOCKER_USERNAME: ${{ github.actor }}
|
||||||
|
DOCKER_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Pull docker image
|
||||||
|
run: |
|
||||||
|
docker pull docker.pkg.github.com/napi-rs/napi-rs/rust-nodejs-alpine:lts
|
||||||
|
docker tag docker.pkg.github.com/napi-rs/napi-rs/rust-nodejs-alpine:lts builder
|
||||||
|
|
||||||
|
- name: Run check
|
||||||
|
run: |
|
||||||
|
docker run --rm -v $(pwd)/.cargo:/root/.cargo -v $(pwd):/napi-rs -w /napi-rs builder cargo check --all --bins --examples --tests -vvv
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: |
|
||||||
|
docker run --rm -v $(pwd)/.cargo:/root/.cargo -v $(pwd):/napi-rs -w /napi-rs builder cargo test -p napi-rs --lib -- --nocapture
|
||||||
|
|
||||||
|
- name: Build native module
|
||||||
|
run: |
|
||||||
|
docker run --rm -v $(pwd)/.cargo:/root/.cargo -v $(pwd):/napi-rs -w /napi-rs builder sh -c "yarn && cd test_module && yarn build"
|
||||||
|
env:
|
||||||
|
RUST_BACKTRACE: 1
|
||||||
|
|
||||||
|
- name: Fuzzy
|
||||||
|
run: docker run --rm -v $(pwd):/napi-rs -w /napi-rs/test_module node:${{ matrix.node }}-alpine node fuzzy.js
|
15
.github/workflows/linux.yaml
vendored
15
.github/workflows/linux.yaml
vendored
|
@ -8,11 +8,8 @@ jobs:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
node: ['10', '12', '13', '14']
|
node: ['10', '12', '13', '14']
|
||||||
version:
|
|
||||||
- stable
|
|
||||||
- nightly
|
|
||||||
|
|
||||||
name: ${{ matrix.version }} - x86_64-unknown-linux-gnu - node@${{ matrix.node }}
|
name: stable - x86_64-unknown-linux-gnu - node@${{ matrix.node }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
@ -23,10 +20,10 @@ jobs:
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node }}
|
node-version: ${{ matrix.node }}
|
||||||
|
|
||||||
- name: Install ${{ matrix.version }}
|
- name: Install stable
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: ${{ matrix.version }}-x86_64-unknown-linux-gnu
|
toolchain: stable-x86_64-unknown-linux-gnu
|
||||||
profile: minimal
|
profile: minimal
|
||||||
override: true
|
override: true
|
||||||
|
|
||||||
|
@ -38,17 +35,17 @@ jobs:
|
||||||
uses: actions/cache@v1
|
uses: actions/cache@v1
|
||||||
with:
|
with:
|
||||||
path: ~/.cargo/registry
|
path: ~/.cargo/registry
|
||||||
key: ${{ matrix.version }}-x86_64-unknown-linux-gnu-cargo-registry-trimmed-${{ hashFiles('**/Cargo.lock') }}
|
key: stable-x86_64-unknown-linux-gnu-cargo-registry-trimmed-${{ hashFiles('**/Cargo.lock') }}
|
||||||
- name: Cache cargo index
|
- name: Cache cargo index
|
||||||
uses: actions/cache@v1
|
uses: actions/cache@v1
|
||||||
with:
|
with:
|
||||||
path: ~/.cargo/git
|
path: ~/.cargo/git
|
||||||
key: ${{ matrix.version }}-x86_64-unknown-linux-gnu-cargo-index-trimmed-${{ hashFiles('**/Cargo.lock') }}
|
key: stable-x86_64-unknown-linux-gnu-cargo-index-trimmed-${{ hashFiles('**/Cargo.lock') }}
|
||||||
- name: Cache cargo build
|
- name: Cache cargo build
|
||||||
uses: actions/cache@v1
|
uses: actions/cache@v1
|
||||||
with:
|
with:
|
||||||
path: target
|
path: target
|
||||||
key: ${{ matrix.version }}-x86_64-unknown-linux-gnu-cargo-build-trimmed-${{ hashFiles('**/Cargo.lock') }}
|
key: stable-x86_64-unknown-linux-gnu-cargo-build-trimmed-${{ hashFiles('**/Cargo.lock') }}
|
||||||
|
|
||||||
- name: Check build
|
- name: Check build
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
|
|
15
.github/workflows/macos.yaml
vendored
15
.github/workflows/macos.yaml
vendored
|
@ -8,11 +8,8 @@ jobs:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
node: ['10', '12', '13', '14']
|
node: ['10', '12', '13', '14']
|
||||||
version:
|
|
||||||
- stable
|
|
||||||
- nightly
|
|
||||||
|
|
||||||
name: ${{ matrix.version }} - x86_64-apple-darwin - node@${{ matrix.node }}
|
name: stable - x86_64-apple-darwin - node@${{ matrix.node }}
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
@ -23,10 +20,10 @@ jobs:
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node }}
|
node-version: ${{ matrix.node }}
|
||||||
|
|
||||||
- name: Install ${{ matrix.version }}
|
- name: Install stable
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: ${{ matrix.version }}-x86_64-apple-darwin
|
toolchain: stable-x86_64-apple-darwin
|
||||||
profile: minimal
|
profile: minimal
|
||||||
override: true
|
override: true
|
||||||
|
|
||||||
|
@ -38,17 +35,17 @@ jobs:
|
||||||
uses: actions/cache@v1
|
uses: actions/cache@v1
|
||||||
with:
|
with:
|
||||||
path: ~/.cargo/registry
|
path: ~/.cargo/registry
|
||||||
key: ${{ matrix.version }}-x86_64-apple-darwin-cargo-registry-trimmed-${{ hashFiles('**/Cargo.lock') }}
|
key: stable-x86_64-apple-darwin-cargo-registry-trimmed-${{ hashFiles('**/Cargo.lock') }}
|
||||||
- name: Cache cargo index
|
- name: Cache cargo index
|
||||||
uses: actions/cache@v1
|
uses: actions/cache@v1
|
||||||
with:
|
with:
|
||||||
path: ~/.cargo/git
|
path: ~/.cargo/git
|
||||||
key: ${{ matrix.version }}-x86_64-apple-darwin-cargo-index-trimmed-${{ hashFiles('**/Cargo.lock') }}
|
key: stable-x86_64-apple-darwin-cargo-index-trimmed-${{ hashFiles('**/Cargo.lock') }}
|
||||||
- name: Cache cargo build
|
- name: Cache cargo build
|
||||||
uses: actions/cache@v1
|
uses: actions/cache@v1
|
||||||
with:
|
with:
|
||||||
path: target
|
path: target
|
||||||
key: ${{ matrix.version }}-x86_64-apple-darwin-cargo-build-trimmed-${{ hashFiles('**/Cargo.lock') }}
|
key: stable-x86_64-apple-darwin-cargo-build-trimmed-${{ hashFiles('**/Cargo.lock') }}
|
||||||
|
|
||||||
- name: Check build
|
- name: Check build
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
|
|
15
.github/workflows/windows.yaml
vendored
15
.github/workflows/windows.yaml
vendored
|
@ -8,13 +8,10 @@ jobs:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
node: ['10', '12', '13', '14']
|
node: ['10', '12', '13', '14']
|
||||||
version:
|
|
||||||
- stable
|
|
||||||
- nightly
|
|
||||||
target:
|
target:
|
||||||
- x86_64-pc-windows-msvc
|
- x86_64-pc-windows-msvc
|
||||||
|
|
||||||
name: ${{ matrix.version }} - ${{ matrix.target }} - node@${{ matrix.node }}
|
name: stable - ${{ matrix.target }} - node@${{ matrix.node }}
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
@ -24,10 +21,10 @@ jobs:
|
||||||
uses: actions/setup-node@v1
|
uses: actions/setup-node@v1
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node }}
|
node-version: ${{ matrix.node }}
|
||||||
- name: Install ${{ matrix.version }}
|
- name: Install stable
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: ${{ matrix.version }}-${{ matrix.target }}
|
toolchain: stable-${{ matrix.target }}
|
||||||
profile: minimal
|
profile: minimal
|
||||||
override: true
|
override: true
|
||||||
- name: Install llvm
|
- name: Install llvm
|
||||||
|
@ -44,17 +41,17 @@ jobs:
|
||||||
uses: actions/cache@v1
|
uses: actions/cache@v1
|
||||||
with:
|
with:
|
||||||
path: ~/.cargo/registry
|
path: ~/.cargo/registry
|
||||||
key: ${{ matrix.version }}-${{ matrix.target }}-cargo-registry-trimmed-${{ hashFiles('**/Cargo.lock') }}
|
key: stable-${{ matrix.target }}-cargo-registry-trimmed-${{ hashFiles('**/Cargo.lock') }}
|
||||||
- name: Cache cargo index
|
- name: Cache cargo index
|
||||||
uses: actions/cache@v1
|
uses: actions/cache@v1
|
||||||
with:
|
with:
|
||||||
path: ~/.cargo/git
|
path: ~/.cargo/git
|
||||||
key: ${{ matrix.version }}-${{ matrix.target }}-cargo-index-trimmed-${{ hashFiles('**/Cargo.lock') }}
|
key: stable-${{ matrix.target }}-cargo-index-trimmed-${{ hashFiles('**/Cargo.lock') }}
|
||||||
- name: Cache cargo build
|
- name: Cache cargo build
|
||||||
uses: actions/cache@v1
|
uses: actions/cache@v1
|
||||||
with:
|
with:
|
||||||
path: target
|
path: target
|
||||||
key: ${{ matrix.version }}-${{ matrix.target }}-cargo-build-trimmed-${{ hashFiles('**/Cargo.lock') }}
|
key: stable-${{ matrix.target }}-cargo-build-trimmed-${{ hashFiles('**/Cargo.lock') }}
|
||||||
|
|
||||||
- name: Check build
|
- name: Check build
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
|
|
13
Dockerfile.alpine
Normal file
13
Dockerfile.alpine
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
FROM rust:alpine
|
||||||
|
|
||||||
|
ENV RUSTFLAGS="-C target-feature=-crt-static"
|
||||||
|
|
||||||
|
RUN sed -i -e 's/v[[:digit:]]\..*\//edge\//g' /etc/apk/repositories && \
|
||||||
|
apk update && \
|
||||||
|
apk add nodejs yarn clang musl-dev llvm-dev curl && \
|
||||||
|
export NODE_VERSION=$(node -e "console.log(process.version)") && \
|
||||||
|
curl -fsSLO $(node -e "console.log(process.release.headersUrl)") && \
|
||||||
|
tar -xf "node-$NODE_VERSION-headers.tar.gz" && \
|
||||||
|
mv "node-$NODE_VERSION/include/node" include && \
|
||||||
|
rm -rf "node-$NODE_VERSION" && \
|
||||||
|
rm "node-$NODE_VERSION-headers.tar.gz"
|
|
@ -9,9 +9,6 @@ repository = "https://github.com/Brooooooklyn/napi-rs"
|
||||||
keywords = ["NodeJS", "FFI", "NAPI", "n-api"]
|
keywords = ["NodeJS", "FFI", "NAPI", "n-api"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
futures = { version = "0.3", features = ["default", "thread-pool"] }
|
|
||||||
|
|
||||||
[target.'cfg(windows)'.build-dependencies]
|
[target.'cfg(windows)'.build-dependencies]
|
||||||
flate2 = "1.0"
|
flate2 = "1.0"
|
||||||
reqwest = { version = "0.10", features = ["native-tls", "blocking"] }
|
reqwest = { version = "0.10", features = ["native-tls", "blocking"] }
|
||||||
|
|
|
@ -1,116 +0,0 @@
|
||||||
extern crate alloc;
|
|
||||||
|
|
||||||
use alloc::alloc::{alloc, alloc_zeroed, Layout};
|
|
||||||
use futures::future::LocalBoxFuture;
|
|
||||||
use futures::task::{waker, ArcWake, Context, Poll};
|
|
||||||
use std::future::Future;
|
|
||||||
use std::os::raw::c_void;
|
|
||||||
use std::pin::Pin;
|
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use crate::{sys, Error, Result, Status};
|
|
||||||
|
|
||||||
struct Task<'a> {
|
|
||||||
future: LocalBoxFuture<'a, ()>,
|
|
||||||
context: Context<'a>,
|
|
||||||
is_polling: AtomicBool,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct UvWaker(*mut sys::uv_async_t);
|
|
||||||
|
|
||||||
unsafe impl Send for UvWaker {}
|
|
||||||
unsafe impl Sync for UvWaker {}
|
|
||||||
|
|
||||||
impl UvWaker {
|
|
||||||
fn new(event_loop: *mut sys::uv_loop_s) -> Result<UvWaker> {
|
|
||||||
let uv_async_t = unsafe {
|
|
||||||
let layout = Layout::new::<sys::uv_async_t>();
|
|
||||||
debug_assert!(layout.size() != 0, "uv_async_t alloc size should not be 0");
|
|
||||||
if cfg!(windows) {
|
|
||||||
alloc_zeroed(layout) as *mut sys::uv_async_t
|
|
||||||
} else {
|
|
||||||
alloc(layout) as *mut sys::uv_async_t
|
|
||||||
}
|
|
||||||
};
|
|
||||||
unsafe {
|
|
||||||
let status = sys::uv_async_init(event_loop, uv_async_t, Some(poll_future));
|
|
||||||
if status != 0 {
|
|
||||||
return Err(Error {
|
|
||||||
status: Status::Unknown,
|
|
||||||
reason: Some("Non-zero status returned from uv_async_init".to_owned()),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Ok(UvWaker(uv_async_t))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn assign_task(&self, mut task: Task) {
|
|
||||||
if !task.poll_future() {
|
|
||||||
task.is_polling.store(false, Ordering::Relaxed);
|
|
||||||
let arc_task = Arc::new(task);
|
|
||||||
unsafe {
|
|
||||||
sys::uv_handle_set_data(
|
|
||||||
self.0 as *mut sys::uv_handle_t,
|
|
||||||
Arc::into_raw(arc_task) as *mut c_void,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
unsafe { sys::uv_close(self.0 as *mut sys::uv_handle_t, None) };
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ArcWake for UvWaker {
|
|
||||||
fn wake_by_ref(arc_self: &Arc<Self>) {
|
|
||||||
let status = unsafe { sys::uv_async_send(arc_self.0) };
|
|
||||||
assert!(status == 0, "wake_uv_async_by_ref failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn execute(event_loop: *mut sys::uv_loop_s, future: LocalBoxFuture<()>) -> Result<()> {
|
|
||||||
let uv_waker = UvWaker::new(event_loop)?;
|
|
||||||
let arc_waker = Arc::new(uv_waker);
|
|
||||||
let waker_to_poll = Arc::clone(&arc_waker);
|
|
||||||
let waker = waker(arc_waker);
|
|
||||||
let context = Context::from_waker(&waker);
|
|
||||||
let task = Task {
|
|
||||||
future,
|
|
||||||
context,
|
|
||||||
is_polling: AtomicBool::from(false),
|
|
||||||
};
|
|
||||||
waker_to_poll.assign_task(task);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Task<'a> {
|
|
||||||
fn poll_future(&mut self) -> bool {
|
|
||||||
if self.is_polling.load(Ordering::Relaxed) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
self.is_polling.store(true, Ordering::Relaxed);
|
|
||||||
let mut pinned = Pin::new(&mut self.future);
|
|
||||||
let fut_mut = pinned.as_mut();
|
|
||||||
match fut_mut.poll(&mut self.context) {
|
|
||||||
Poll::Ready(_) => true,
|
|
||||||
Poll::Pending => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe extern "C" fn poll_future(handle: *mut sys::uv_async_t) {
|
|
||||||
let data_ptr = sys::uv_handle_get_data(handle as *mut sys::uv_handle_t) as *mut Task;
|
|
||||||
let mut task = Arc::from_raw(data_ptr);
|
|
||||||
if let Some(mut_task) = Arc::get_mut(&mut task) {
|
|
||||||
if mut_task.poll_future() {
|
|
||||||
sys::uv_close(handle as *mut sys::uv_handle_t, None);
|
|
||||||
} else {
|
|
||||||
mut_task.is_polling.store(false, Ordering::Relaxed);
|
|
||||||
Arc::into_raw(task);
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
Arc::into_raw(task);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +1,5 @@
|
||||||
use async_work::AsyncWork;
|
use async_work::AsyncWork;
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
use futures::prelude::*;
|
|
||||||
use std::any::TypeId;
|
use std::any::TypeId;
|
||||||
use std::convert::{TryFrom, TryInto};
|
use std::convert::{TryFrom, TryInto};
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
|
@ -15,8 +14,6 @@ use std::string::String as RustString;
|
||||||
|
|
||||||
mod async_work;
|
mod async_work;
|
||||||
mod call_context;
|
mod call_context;
|
||||||
mod executor;
|
|
||||||
mod promise;
|
|
||||||
pub mod sys;
|
pub mod sys;
|
||||||
mod task;
|
mod task;
|
||||||
mod version;
|
mod version;
|
||||||
|
@ -549,48 +546,6 @@ impl Env {
|
||||||
Ok(Value::from_raw_value(self, result, Object))
|
Ok(Value::from_raw_value(self, result, Object))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn execute<
|
|
||||||
T: 'static,
|
|
||||||
V: 'static + ValueType,
|
|
||||||
F: 'static + Future<Output = Result<T>>,
|
|
||||||
R: 'static + FnOnce(&mut Env, T) -> Result<Value<V>>,
|
|
||||||
>(
|
|
||||||
&self,
|
|
||||||
deferred: F,
|
|
||||||
resolver: R,
|
|
||||||
) -> Result<Value<Object>> {
|
|
||||||
let mut raw_promise = ptr::null_mut();
|
|
||||||
let mut raw_deferred = ptr::null_mut();
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
let status = sys::napi_create_promise(self.0, &mut raw_deferred, &mut raw_promise);
|
|
||||||
check_status(status)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let event_loop = unsafe { sys::uv_default_loop() };
|
|
||||||
let raw_env = self.0;
|
|
||||||
let future_to_execute =
|
|
||||||
promise::resolve(self.0, deferred, resolver, raw_deferred).map(move |v| match v {
|
|
||||||
Ok(value) => value,
|
|
||||||
Err(e) => {
|
|
||||||
let cloned_error = e.clone();
|
|
||||||
unsafe {
|
|
||||||
sys::napi_throw_error(
|
|
||||||
raw_env,
|
|
||||||
ptr::null(),
|
|
||||||
e.reason.unwrap_or(format!("{:?}", e.status)).as_ptr() as *const _,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
eprintln!("{:?}", &cloned_error);
|
|
||||||
panic!(cloned_error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
executor::execute(event_loop, Box::pin(future_to_execute))?;
|
|
||||||
|
|
||||||
Ok(Value::from_raw_value(self, raw_promise, Object))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn spawn<T: 'static + Task>(&self, task: T) -> Result<Value<Object>> {
|
pub fn spawn<T: 'static + Task>(&self, task: T) -> Result<Value<Object>> {
|
||||||
let mut raw_promise = ptr::null_mut();
|
let mut raw_promise = ptr::null_mut();
|
||||||
let mut raw_deferred = ptr::null_mut();
|
let mut raw_deferred = ptr::null_mut();
|
||||||
|
|
|
@ -1,65 +0,0 @@
|
||||||
use futures::prelude::*;
|
|
||||||
use std::os::raw::c_char;
|
|
||||||
use std::ptr;
|
|
||||||
|
|
||||||
use crate::{check_status, sys, Env, Result, Value, ValueType};
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub async fn resolve<
|
|
||||||
T,
|
|
||||||
V: ValueType,
|
|
||||||
R: FnOnce(&mut Env, T) -> Result<Value<V>>,
|
|
||||||
F: Future<Output = Result<T>>,
|
|
||||||
>(
|
|
||||||
env: sys::napi_env,
|
|
||||||
fut: F,
|
|
||||||
resolver: R,
|
|
||||||
raw_deferred: sys::napi_deferred,
|
|
||||||
) -> Result<()> {
|
|
||||||
let mut raw_resource = ptr::null_mut();
|
|
||||||
let status = unsafe { sys::napi_create_object(env, &mut raw_resource) };
|
|
||||||
check_status(status)?;
|
|
||||||
let mut raw_name = ptr::null_mut();
|
|
||||||
let s = "napi_async_context";
|
|
||||||
let status = unsafe {
|
|
||||||
sys::napi_create_string_utf8(
|
|
||||||
env,
|
|
||||||
s.as_ptr() as *const c_char,
|
|
||||||
s.len() as u64,
|
|
||||||
&mut raw_name,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
check_status(status)?;
|
|
||||||
let mut raw_context = ptr::null_mut();
|
|
||||||
unsafe {
|
|
||||||
let status = sys::napi_async_init(env, raw_resource, raw_name, &mut raw_context);
|
|
||||||
check_status(status)?;
|
|
||||||
}
|
|
||||||
let mut handle_scope = ptr::null_mut();
|
|
||||||
match fut.await {
|
|
||||||
Ok(v) => unsafe {
|
|
||||||
check_status(sys::napi_open_handle_scope(env, &mut handle_scope))?;
|
|
||||||
let mut tmp_env = Env::from_raw(env);
|
|
||||||
let js_value = resolver(&mut tmp_env, v)?;
|
|
||||||
check_status(sys::napi_resolve_deferred(
|
|
||||||
env,
|
|
||||||
raw_deferred,
|
|
||||||
js_value.raw_value,
|
|
||||||
))?;
|
|
||||||
check_status(sys::napi_close_handle_scope(env, handle_scope))?;
|
|
||||||
},
|
|
||||||
Err(e) => unsafe {
|
|
||||||
check_status(sys::napi_open_handle_scope(env, &mut handle_scope))?;
|
|
||||||
check_status(sys::napi_reject_deferred(
|
|
||||||
env,
|
|
||||||
raw_deferred,
|
|
||||||
Env::from_raw(env)
|
|
||||||
.create_error(e)
|
|
||||||
.map(|e| e.into_raw())
|
|
||||||
.unwrap_or(ptr::null_mut()),
|
|
||||||
))?;
|
|
||||||
check_status(sys::napi_close_handle_scope(env, handle_scope))?;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
Ok(())
|
|
||||||
}
|
|
|
@ -8,7 +8,6 @@ edition = "2018"
|
||||||
crate-type = ["cdylib"]
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
futures = "0.3"
|
|
||||||
napi-rs = { path = "../napi" }
|
napi-rs = { path = "../napi" }
|
||||||
napi-rs-derive = { path = "../napi-derive" }
|
napi-rs-derive = { path = "../napi-derive" }
|
||||||
|
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
const testModule = require('./index.node')
|
|
||||||
|
|
||||||
function testSpawn() {
|
|
||||||
console.log('=== Test spawning a future on libuv event loop')
|
|
||||||
return testModule.testSpawn()
|
|
||||||
}
|
|
||||||
|
|
||||||
function testThrow() {
|
|
||||||
console.log('=== Test throwing from Rust')
|
|
||||||
try {
|
|
||||||
testModule.testThrow()
|
|
||||||
console.log('Expected function to throw an error')
|
|
||||||
process.exit(1)
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
testSpawn()
|
|
||||||
.then((value) => {
|
|
||||||
console.info(`${value} from napi`)
|
|
||||||
testThrow()
|
|
||||||
})
|
|
||||||
.catch((e) => {
|
|
||||||
console.error(e)
|
|
||||||
process.exit(1)
|
|
||||||
})
|
|
|
@ -3,15 +3,12 @@ extern crate napi_rs as napi;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate napi_rs_derive;
|
extern crate napi_rs_derive;
|
||||||
|
|
||||||
extern crate futures;
|
|
||||||
|
|
||||||
use napi::{Any, CallContext, Env, Error, Number, Object, Result, Status, Task, Value};
|
use napi::{Any, CallContext, Env, Error, Number, Object, Result, Status, Task, Value};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
|
||||||
register_module!(test_module, init);
|
register_module!(test_module, init);
|
||||||
|
|
||||||
fn init(env: &Env, exports: &mut Value<Object>) -> Result<()> {
|
fn init(env: &Env, exports: &mut Value<Object>) -> Result<()> {
|
||||||
exports.set_named_property("testSpawn", env.create_function("testSpawn", test_spawn)?)?;
|
|
||||||
exports.set_named_property("testThrow", env.create_function("testThrow", test_throw)?)?;
|
exports.set_named_property("testThrow", env.create_function("testThrow", test_throw)?)?;
|
||||||
exports.set_named_property(
|
exports.set_named_property(
|
||||||
"testSpawnThread",
|
"testSpawnThread",
|
||||||
|
@ -20,29 +17,6 @@ fn init(env: &Env, exports: &mut Value<Object>) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[js_function]
|
|
||||||
fn test_spawn(ctx: CallContext) -> Result<Value<Object>> {
|
|
||||||
use futures::executor::ThreadPool;
|
|
||||||
use futures::StreamExt;
|
|
||||||
let env = ctx.env;
|
|
||||||
let pool = ThreadPool::new().expect("Failed to build pool");
|
|
||||||
let (tx, rx) = futures::channel::mpsc::unbounded::<i32>();
|
|
||||||
let fut_values = async move {
|
|
||||||
let fut_tx_result = async move {
|
|
||||||
(0..200).for_each(|v| {
|
|
||||||
tx.unbounded_send(v).expect("Failed to send");
|
|
||||||
})
|
|
||||||
};
|
|
||||||
pool.spawn_ok(fut_tx_result);
|
|
||||||
let fut = rx.map(|v| v * 2).collect::<Vec<i32>>();
|
|
||||||
let results = fut.await;
|
|
||||||
println!("Collected result lenght {}", results.len());
|
|
||||||
Ok(results.len() as u32)
|
|
||||||
};
|
|
||||||
|
|
||||||
env.execute(fut_values, |&mut env, len| env.create_uint32(len))
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ComputeFib {
|
struct ComputeFib {
|
||||||
n: u32,
|
n: u32,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue