Compare commits
412 Commits
kv/task-re
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f3a96aaa7d | ||
|
|
e0c25bfd75 | ||
|
|
c81d98f195 | ||
|
|
d401a32b78 | ||
|
|
d69768f567 | ||
|
|
2f93620146 | ||
|
|
8814886b41 | ||
|
|
e2cc8cc81d | ||
|
|
5c308aec22 | ||
|
|
d9eac77765 | ||
|
|
73bde85776 | ||
|
|
8758b7f416 | ||
|
|
73390414ee | ||
|
|
fc5a214389 | ||
|
|
c5c277e98b | ||
|
|
264a6a4ce0 | ||
|
|
0df7033978 | ||
|
|
3f6804c79f | ||
|
|
1e8d6261a4 | ||
|
|
56834b5afc | ||
|
|
b64f9203ab | ||
|
|
5b20370bee | ||
|
|
acd5ba6e2a | ||
|
|
d473ead705 | ||
|
|
01fbf284a4 | ||
|
|
ec3e057ec6 | ||
|
|
5fe99a8941 | ||
|
|
0ab3b6ee2e | ||
|
|
2f2bfca92a | ||
|
|
378dcc8e8a | ||
|
|
165dffdf4a | ||
|
|
77f2ac06de | ||
|
|
14bc6072ec | ||
|
|
a20636e548 | ||
|
|
0e259239d3 | ||
|
|
fbd09f0bff | ||
|
|
d7ac291d97 | ||
|
|
1e9bedb2d7 | ||
|
|
859d531fe8 | ||
|
|
671add6f37 | ||
|
|
0ab1a9d52f | ||
|
|
d3a296928f | ||
|
|
ad209e30da | ||
|
|
f4cd384ed5 | ||
|
|
be85d188fc | ||
|
|
830836167e | ||
|
|
50cb290278 | ||
|
|
3189ee00c6 | ||
|
|
e302ab9e31 | ||
|
|
17a0ea921c | ||
|
|
b8c8c2a1ae | ||
|
|
3a16627093 | ||
|
|
5078b1714f | ||
|
|
dd3ada4944 | ||
|
|
c2667bde11 | ||
|
|
54c35c52b5 | ||
|
|
01fe92123c | ||
|
|
ed3bb5392e | ||
|
|
687fd06042 | ||
|
|
534c49575a | ||
|
|
50827bee3d | ||
|
|
0e270d1c7c | ||
|
|
b7c26755c1 | ||
|
|
03c7e9e425 | ||
|
|
e860829dac | ||
|
|
f4ec6eaa29 | ||
|
|
96ff123914 | ||
|
|
3792dfd5c6 | ||
|
|
d5bfee3dac | ||
|
|
e6e92cf431 | ||
|
|
bf32f66e95 | ||
|
|
4c224560b6 | ||
|
|
194945ebc6 | ||
|
|
3ab690e8f8 | ||
|
|
b10a779daa | ||
|
|
ccbc5916fe | ||
|
|
64ee1659c2 | ||
|
|
b730df7fa5 | ||
|
|
bd795eabae | ||
|
|
111d2ac73c | ||
|
|
397c734839 | ||
|
|
2918268580 | ||
|
|
bd69a89cda | ||
|
|
5d1d659f1a | ||
|
|
56b3715d7b | ||
|
|
fdb2a48a44 | ||
|
|
188c8d1852 | ||
|
|
c0d72cba94 | ||
|
|
0f7572ab00 | ||
|
|
98a8435062 | ||
|
|
553650ada6 | ||
|
|
f467acf8ff | ||
|
|
f35724bdfe | ||
|
|
3486ff34fe | ||
|
|
b0ff15ef97 | ||
|
|
446b60cdec | ||
|
|
3e76b0196d | ||
|
|
691a66f809 | ||
|
|
6165246692 | ||
|
|
272fe0d209 | ||
|
|
e9a82cb9c2 | ||
|
|
af4a264f77 | ||
|
|
208346f37b | ||
|
|
993d106e30 | ||
|
|
20727befc1 | ||
|
|
8400efa8ae | ||
|
|
6b21eb10cb | ||
|
|
9d975415da | ||
|
|
7b136788fc | ||
|
|
7c3c97b2f7 | ||
|
|
ddcbcbc657 | ||
|
|
e8803c6b36 | ||
|
|
7840161021 | ||
|
|
2e7a34a071 | ||
|
|
d79f9eebb1 | ||
|
|
70fe6e4504 | ||
|
|
f7ee6b6d95 | ||
|
|
73bbe423ff | ||
|
|
d7f1c7f3fd | ||
|
|
01c0526a3b | ||
|
|
96f3f8672a | ||
|
|
fe9e5882ec | ||
|
|
5cffd02772 | ||
|
|
e548f23b74 | ||
|
|
e40c6125b6 | ||
|
|
6e2557c4aa | ||
|
|
1a2c1a59bc | ||
|
|
1a4cecf9b0 | ||
|
|
ff0593b823 | ||
|
|
19e2c4a452 | ||
|
|
375dc4a396 | ||
|
|
25a4dd3619 | ||
|
|
7cb91d9314 | ||
|
|
af6506ae8e | ||
|
|
077f9e5afb | ||
|
|
7cae7c774e | ||
|
|
4fda49d283 | ||
|
|
eabe09026c | ||
|
|
c6768569ee | ||
|
|
d775895e21 | ||
|
|
10b84c773e | ||
|
|
8af9d22508 | ||
|
|
22b3196442 | ||
|
|
0a35c58e96 | ||
|
|
ea15e232b9 | ||
|
|
ace68bdd55 | ||
|
|
d566f83de4 | ||
|
|
1e3be80740 | ||
|
|
6e0b62750a | ||
|
|
c59f20b123 | ||
|
|
7a76945fea | ||
|
|
5adcdba556 | ||
|
|
5c908229ac | ||
|
|
22a7ea90a5 | ||
|
|
6a375cb6af | ||
|
|
1cce66bbd9 | ||
|
|
cd460af96b | ||
|
|
7a5ae29f75 | ||
|
|
0426692743 | ||
|
|
7105a63ad6 | ||
|
|
3799bfc8db | ||
|
|
ea1011f8f3 | ||
|
|
d8d4032e6b | ||
|
|
e46340bd55 | ||
|
|
9774b95145 | ||
|
|
49fd8b308f | ||
|
|
a68d5fc8bb | ||
|
|
c0937e36c9 | ||
|
|
aae89f36d0 | ||
|
|
df9f5cbba9 | ||
|
|
75457c97e3 | ||
|
|
f64543a2bd | ||
|
|
0734bf4a07 | ||
|
|
6cf59213fe | ||
|
|
94bb1cd933 | ||
|
|
999a4bb7ea | ||
|
|
4730ab7166 | ||
|
|
f98dec2679 | ||
|
|
39a6c4fbdc | ||
|
|
0013378993 | ||
|
|
77408d3063 | ||
|
|
f45f71dbdd | ||
|
|
c50b6bf6b4 | ||
|
|
b44a3a59e8 | ||
|
|
eb4356209d | ||
|
|
a68f115edb | ||
|
|
0b51e17183 | ||
|
|
bd74a239cf | ||
|
|
c1bdfd1bdf | ||
|
|
02975d0fdc | ||
|
|
1be0a598f7 | ||
|
|
f21eecdb2c | ||
|
|
ea6e96bde4 | ||
|
|
b3a38869ca | ||
|
|
096104084b | ||
|
|
585bd33f1c | ||
|
|
f4871dbc10 | ||
|
|
5f6481a532 | ||
|
|
ccd508dd48 | ||
|
|
1c0a5406f0 | ||
|
|
0900dd2a50 | ||
|
|
7422e60f66 | ||
|
|
84c2f518da | ||
|
|
28ae751606 | ||
|
|
cffe3cfc23 | ||
|
|
ca6103d0fc | ||
|
|
f04c41761e | ||
|
|
efeff8f7ae | ||
|
|
68f136ec28 | ||
|
|
37d237a9ec | ||
|
|
8aec5b0074 | ||
|
|
5c3253d22f | ||
|
|
6a3848bbd7 | ||
|
|
83a54f2702 | ||
|
|
15d881b1cc | ||
|
|
cf4b54e9a9 | ||
|
|
e91a284c82 | ||
|
|
8142074f07 | ||
|
|
35f5a42002 | ||
|
|
c312a0a0d7 | ||
|
|
c1eaaf0d77 | ||
|
|
11cd59dc69 | ||
|
|
99260dc449 | ||
|
|
1f217f56cb | ||
|
|
a89ea8ca40 | ||
|
|
4a1bfa1a15 | ||
|
|
7a1eff0ebe | ||
|
|
3ae3decff5 | ||
|
|
878a47bab9 | ||
|
|
22a03bf5f5 | ||
|
|
cc8daf27bc | ||
|
|
ada4803f46 | ||
|
|
c0b2a85334 | ||
|
|
7b095648a0 | ||
|
|
40a8aebdc3 | ||
|
|
299a206506 | ||
|
|
0afefdd5fb | ||
|
|
32f3276ded | ||
|
|
e5b8154255 | ||
|
|
17a186d0eb | ||
|
|
f6a71f2ed6 | ||
|
|
bd36672e54 | ||
|
|
e285029e24 | ||
|
|
a1770816bc | ||
|
|
da1dacfe24 | ||
|
|
c143cc64a5 | ||
|
|
637d53504d | ||
|
|
af7d84582f | ||
|
|
6c445cdbd1 | ||
|
|
336b65b031 | ||
|
|
f7c65e9e28 | ||
|
|
68e17d9ad9 | ||
|
|
28acc76375 | ||
|
|
828d28596a | ||
|
|
dc81562076 | ||
|
|
a5f045755f | ||
|
|
abdff5dfaa | ||
|
|
d69d80c626 | ||
|
|
3b12f9c50b | ||
|
|
614b6730a3 | ||
|
|
882fd14a4c | ||
|
|
5ffa2d2821 | ||
|
|
0fc614ff84 | ||
|
|
8d1f0029d1 | ||
|
|
b8259eb9d4 | ||
|
|
412b6577a4 | ||
|
|
e7837852f0 | ||
|
|
558c3d1f14 | ||
|
|
151137363c | ||
|
|
e80c8c1933 | ||
|
|
468d425ac8 | ||
|
|
3e9865139e | ||
|
|
65681d2769 | ||
|
|
f0f8e6b1f8 | ||
|
|
b17c2fbd6c | ||
|
|
6456bcd725 | ||
|
|
2574b2dbda | ||
|
|
2c8fd5ed12 | ||
|
|
59e48eab9a | ||
|
|
3383d61bba | ||
|
|
bc0f181d53 | ||
|
|
ff4b67b853 | ||
|
|
cd8f80ad97 | ||
|
|
04b3bdb322 | ||
|
|
87a8d6493a | ||
|
|
049c93e781 | ||
|
|
cb826b7cb6 | ||
|
|
df1a598299 | ||
|
|
8b0bf9ce30 | ||
|
|
3c1de72890 | ||
|
|
69c75cecf3 | ||
|
|
4dcd9ead0a | ||
|
|
9293903e9f | ||
|
|
9661293f4d | ||
|
|
59693f845c | ||
|
|
6fdfd366c7 | ||
|
|
d2bc5f504c | ||
|
|
5f53d9caf6 | ||
|
|
0aec7dba72 | ||
|
|
603b55b30b | ||
|
|
6a5bb0e4c1 | ||
|
|
46e365c67e | ||
|
|
e315310cca | ||
|
|
31aa1cfaf0 | ||
|
|
471d66c38f | ||
|
|
391abad782 | ||
|
|
f70f4b825b | ||
|
|
f91b12baf5 | ||
|
|
354fe43e4a | ||
|
|
c5527f0d27 | ||
|
|
43e2030140 | ||
|
|
29fa5d4b4c | ||
|
|
160b28c9d1 | ||
|
|
9a247e11fe | ||
|
|
0bddba6102 | ||
|
|
0894971b17 | ||
|
|
32f69bcb15 | ||
|
|
c8a777e20b | ||
|
|
343c05f1fa | ||
|
|
2fd4e654b8 | ||
|
|
44c8d01550 | ||
|
|
5a63267ee8 | ||
|
|
3888b0f3da | ||
|
|
f305e92feb | ||
|
|
a39442ad91 | ||
|
|
c86998ed43 | ||
|
|
1c6de72064 | ||
|
|
6f9ffa9b5f | ||
|
|
9eb3ca6bd3 | ||
|
|
cd39666dc3 | ||
|
|
3067a25dd4 | ||
|
|
5e0a4e1919 | ||
|
|
7f0a04c7c7 | ||
|
|
b5f84f4895 | ||
|
|
a9f9d640ea | ||
|
|
0491055f77 | ||
|
|
539465703d | ||
|
|
068ba22531 | ||
|
|
c64a39a05d | ||
|
|
2ef84d29a9 | ||
|
|
0b5a5ea29f | ||
|
|
01bb2c78d9 | ||
|
|
e681947af6 | ||
|
|
69299bb154 | ||
|
|
6891109f1c | ||
|
|
9ba0fe3180 | ||
|
|
3aacc3a617 | ||
|
|
c9158d70d8 | ||
|
|
9e1a4c4b22 | ||
|
|
7e1ca41633 | ||
|
|
a03b27b095 | ||
|
|
35a8858e5c | ||
|
|
ef349bb8b8 | ||
|
|
93e564d013 | ||
|
|
b4bdf87d0b | ||
|
|
c3eb47dfdc | ||
|
|
bd2479cd4b | ||
|
|
a3503ee824 | ||
|
|
48e7a40398 | ||
|
|
d8c6775838 | ||
|
|
fa4812e439 | ||
|
|
63c059f53a | ||
|
|
f899e21c0a | ||
|
|
bc185ac13e | ||
|
|
9c1f0ce2bc | ||
|
|
1c4381017d | ||
|
|
861b1ed458 | ||
|
|
a8d9208673 | ||
|
|
1319098e99 | ||
|
|
cb2ed3da80 | ||
|
|
4aa564d590 | ||
|
|
e8a53f44e9 | ||
|
|
cda549d06c | ||
|
|
ac9215e146 | ||
|
|
2626dd12a1 | ||
|
|
3afc01d7d6 | ||
|
|
03b4308217 | ||
|
|
9b196a0a56 | ||
|
|
b65531b38b | ||
|
|
ad8f98b5a8 | ||
|
|
557fc3c5ad | ||
|
|
0e55bb7468 | ||
|
|
6c1bc68508 | ||
|
|
f3294d1b2e | ||
|
|
463e0d8dc2 | ||
|
|
17b905b5f6 | ||
|
|
457068a561 | ||
|
|
abd322ed8d | ||
|
|
35c8b60a18 | ||
|
|
0a40f6abb0 | ||
|
|
7213332d72 | ||
|
|
e31c16cf5b | ||
|
|
528124767c | ||
|
|
a488204d10 | ||
|
|
d25fe613a0 | ||
|
|
d9e33245ab | ||
|
|
3b4de37674 | ||
|
|
b7e52e134e | ||
|
|
07384320cd | ||
|
|
f4adc5b613 | ||
|
|
10495c4ac2 | ||
|
|
1835acf0dd | ||
|
|
440e5f9149 | ||
|
|
546f2ce76d | ||
|
|
8d00d716c0 | ||
|
|
dfebfc61b2 | ||
|
|
a0ec71b633 | ||
|
|
f61b739aff | ||
|
|
98462ae56d | ||
|
|
cfc894015b | ||
|
|
6d5c32a8ea | ||
|
|
1ac73a640b |
6
.cargo/config.toml
Normal file
6
.cargo/config.toml
Normal file
@ -0,0 +1,6 @@
|
||||
[alias]
|
||||
# Neon defines mutually exclusive feature flags which prevents using `cargo clippy --all-features`
|
||||
# The following aliases simplify linting the entire workspace
|
||||
clippy-legacy = "clippy --all-targets --no-default-features -p neon -p neon-runtime -p neon-build -p neon-macros -p tests -p static_tests --features event-handler-api,proc-macros,try-catch-api,legacy-runtime -- -A clippy::missing_safety_doc"
|
||||
clippy-napi = "clippy --all-targets --no-default-features -p neon -p neon-runtime -p neon-build -p neon-macros -p electron-tests -p napi-tests --features proc-macros,try-catch-api,napi-experimental -- -A clippy::missing_safety_doc"
|
||||
neon-test = "test --no-default-features --features napi-experimental"
|
||||
39
.github/workflows/lint.yml
vendored
Normal file
39
.github/workflows/lint.yml
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
name: Lints
|
||||
|
||||
on:
|
||||
push:
|
||||
# Prevent duplicate runs of this workflow on our own internal PRs.
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [14.x]
|
||||
rust-toolchain: [nightly]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Rust ${{ matrix.rust-toolchain }}
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: ${{ matrix.rust-toolchain }}
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: install build-essential
|
||||
run: sudo apt-get install -y build-essential
|
||||
- name: Formatting
|
||||
run: cargo fmt --all -- --check
|
||||
- name: Clippy (N-API)
|
||||
run: cargo clippy-napi
|
||||
- name: Clippy (Legacy)
|
||||
run: cargo clippy-legacy
|
||||
38
.github/workflows/linux.yml
vendored
Normal file
38
.github/workflows/linux.yml
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
name: Test on Linux
|
||||
|
||||
on:
|
||||
push:
|
||||
# Prevent duplicate runs of this workflow on our own internal PRs.
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x, 14.x, 16.x]
|
||||
rust-toolchain: [stable, beta, nightly]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Rust ${{ matrix.rust-toolchain }}
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: ${{ matrix.rust-toolchain }}
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: install build-essential
|
||||
run: sudo apt-get install -y build-essential
|
||||
- name: run cargo test
|
||||
run: xvfb-run --auto-servernum cargo neon-test -- --nocapture
|
||||
- name: run CLI test
|
||||
working-directory: ./create-neon
|
||||
run: npm test
|
||||
40
.github/workflows/macos.yml
vendored
Normal file
40
.github/workflows/macos.yml
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
name: Test on MacOS
|
||||
|
||||
on:
|
||||
push:
|
||||
# Prevent duplicate runs of this workflow on our own internal PRs.
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: macos-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x, 14.x, 16.x]
|
||||
rust-toolchain: [stable, beta, nightly]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Rust ${{ matrix.rust-toolchain }}
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: ${{ matrix.rust-toolchain }}
|
||||
target: x86_64-apple-darwin
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
# - name: update node-gyp to latest
|
||||
# # https://github.com/nodejs/node-gyp/issues/1933#issuecomment-586915535
|
||||
# run: npm install -g node-gyp@latest
|
||||
- name: run cargo test
|
||||
run: cargo neon-test
|
||||
- name: run CLI test
|
||||
working-directory: ./create-neon
|
||||
run: npm test
|
||||
51
.github/workflows/windows.yml
vendored
Normal file
51
.github/workflows/windows.yml
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
name: Test on Windows
|
||||
|
||||
on:
|
||||
push:
|
||||
# Prevent duplicate runs of this workflow on our own internal PRs.
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: windows-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x, 14.x, 16.x]
|
||||
rust-toolchain: [stable, beta, nightly]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Rust ${{ matrix.rust-toolchain }}
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: ${{ matrix.rust-toolchain }}
|
||||
target: x86_64-pc-windows-msvc
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Use npm v6
|
||||
if: ${{ matrix.node-version == '16.x' }}
|
||||
run: npm install -g npm@6
|
||||
- name: Install libclang
|
||||
uses: KyleMayes/install-llvm-action@01144dc97b1e2693196c3056414a44f15180648b
|
||||
with:
|
||||
version: "10"
|
||||
directory: ${{ runner.temp }}/llvm
|
||||
# - name: update node-gyp to latest
|
||||
# # https://github.com/nodejs/node-gyp/issues/1933#issuecomment-586915535
|
||||
# run: npm install -g node-gyp@latest
|
||||
- run: npm config set msvs_version 2019
|
||||
- name: run cargo test
|
||||
run: cargo neon-test
|
||||
env:
|
||||
LIBCLANG_PATH: ${{ runner.temp }}/llvm/bin
|
||||
- name: run CLI test
|
||||
working-directory: ./create-neon
|
||||
run: npm test
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@ -7,6 +7,9 @@ Cargo.lock
|
||||
**/index.node
|
||||
**/artifacts.json
|
||||
cli/lib
|
||||
create-neon/dist
|
||||
create-neon/create-neon-test-project
|
||||
create-neon/create-neon-manual-test-project
|
||||
test/cli/lib
|
||||
npm-debug.log
|
||||
rls*.log
|
||||
|
||||
62
.travis.yml
62
.travis.yml
@ -1,62 +0,0 @@
|
||||
language: rust
|
||||
dist: trusty
|
||||
|
||||
rust:
|
||||
- stable
|
||||
- beta
|
||||
- nightly
|
||||
|
||||
matrix:
|
||||
exclude:
|
||||
- env: TRAVIS_NODE_VERSION="8"
|
||||
rust: beta
|
||||
- env: TRAVIS_NODE_VERSION="8"
|
||||
rust: nightly
|
||||
|
||||
env:
|
||||
matrix:
|
||||
- TRAVIS_NODE_VERSION="12"
|
||||
- TRAVIS_NODE_VERSION="10"
|
||||
- TRAVIS_NODE_VERSION="8"
|
||||
global:
|
||||
- secure: mO6uooJGRkDISBZbTq0zvjOfjQ6BeclkxVZN3XWaXrZ/4KjPi7/fRzkm9c8brPe7LWnD4bQ9Bhp7/I6+SVRlvw+uGXNhBiiIyl95jp9s9mOEN+8V7TyShIHEYjbVJf/EGiv5Rz7ni9cNG6iBHcxy5ehycodPtVdAn/VKw31Og/JNWFTu6OzaDZL6gsFIk7VEnHUHgGtl4/iPPdPgAN18oxWbf0CjaknFxXaQiwJXuevd+fuZU16HygBn2Kmj7gqbAKyG8T6wJ1LAQpTkIduXAcgW/PJnj+Stzu48GRVoWoqMQ9Ksk2oSX70fxksC3U3SH4tIQW1+68fXZz4Y0I6b7LkwxovRxkcE4rgoU15xxJuMjxXlQ/csupwhpnBdHhh+Fmjsr0n5KFFLCI7m04ZqAn7+xx9g2NhyuPmO7/ETW24XV9fRy7IywcqR8UgLmftI36r0nV5iO500t4o13DJ0hBTIUgX6KVenbr7v68WO+M/XSRU81RPGjQKsAFM60EpCtn36uCLAZbKyxQi1kYk6UFJLfb/bfrvSS6dzUQ7fEcNRekLMn8Fo4CKAmYCJ70tvhyx/EN0HrIpCfIYedMTLYf11ZQ/bKWcHE4GzU77cRgNwBYLsY6tFjchFukyK14F6jWgpqF81g0yzG0pRJRxZqrtwEI63Db/eLidGctmcEyQ=
|
||||
|
||||
before_install:
|
||||
- source $HOME/.nvm/nvm.sh
|
||||
- nvm install ${TRAVIS_NODE_VERSION}
|
||||
- nvm use ${TRAVIS_NODE_VERSION}
|
||||
- node -v
|
||||
- npm -v
|
||||
|
||||
# Required for electron tests
|
||||
before_script:
|
||||
- "export DISPLAY=:99.0"
|
||||
- "sh -e /etc/init.d/xvfb start"
|
||||
- sleep 3 # give xvfb some time to start
|
||||
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-4.8
|
||||
|
||||
script:
|
||||
- cargo test --release -- --nocapture
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- stage: docs
|
||||
before_install: skip
|
||||
before_script:
|
||||
- export PATH=$HOME/.local/bin:$PATH
|
||||
- pip install ghp-import --user $(whoami)
|
||||
script: |
|
||||
if [[ $TRAVIS_BRANCH=master && $TRAVIS_PULL_REQUEST=false && $TRAVIS_COMMIT_MESSAGE =~ %travis:docs ]]; then
|
||||
echo "Generating API docs..." &&
|
||||
cargo doc &&
|
||||
echo "<meta http-equiv=refresh content=0;url=neon/index.html>" > target/doc/index.html &&
|
||||
echo "Deploying API docs..." &&
|
||||
ghp-import -n target/doc &&
|
||||
git push -fq https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages
|
||||
fi
|
||||
14
AUTHORS.md
14
AUTHORS.md
@ -5,23 +5,32 @@ Neon owes its existence to the contributions of these fine people.
|
||||
* [Reza Akhavan](https://github.com/jedireza)
|
||||
* [Nerijus Arlauskas](https://github.com/Nercury)
|
||||
* [Igor Artamonov](https://github.com/splix)
|
||||
* [Peter Atashian](https://github.com/retep998)
|
||||
* [David Baker](https://github.com/dbkr)
|
||||
* [Sean Billig](https://github.com/sbillig)
|
||||
* [Tim Blair](https://github.com/tblair)
|
||||
* [Max Brunsfeld](https://github.com/maxbrunsfeld)
|
||||
* [Dale Bustad](https://github.com/divmain)
|
||||
* [Eduard-Mihai Burtescu](https://github.com/eddyb)
|
||||
* [Gabriel Castro](https://github.com/GabrielCastro)
|
||||
* [Lin Clark](https://github.com/linclark)
|
||||
* [Nathaniel Daniel](https://github.com/adumbidiot)
|
||||
* [Joey Ezechiëls](https://github.com/jjpe)
|
||||
* [Cory Forsyth](https://github.com/bantic)
|
||||
* [Olivier Goffart](https://github.com/ogoffart)
|
||||
* [Dave Herman](https://github.com/dherman)
|
||||
* [Himself65](https://github.com/Himself65)
|
||||
* [Maciej Hirsz](https://github.com/maciejhirsz)
|
||||
* [Amal Hussein](https://github.com/nomadtechie)
|
||||
* [Usagi Ito](https://github.com/usagi)
|
||||
* [Jeroen (jrd-rocks)](https://github.com/jrd-rocks)
|
||||
* [Keegan (mhsjlw)](https://github.com/mhsjlw)
|
||||
* [Florian Keller](https://github.com/ffflorian)
|
||||
* [Aleksey Kladov](https://github.com/matklad)
|
||||
* [Adam Kloboucnik](https://github.com/akloboucnik)
|
||||
* [Renée Kooi](https://github.com/goto-bus-stop)
|
||||
* [Anton Lazarev](https://github.com/antonok-edm)
|
||||
* [Simon Liang](https://github.com/lhr0909)
|
||||
* [Terence Lee](https://github.com/hone)
|
||||
* [Milan Loveless](https://github.com/MilanLoveless)
|
||||
* [Darin Morrison](https://github.com/freebroccolo)
|
||||
@ -31,9 +40,11 @@ Neon owes its existence to the contributions of these fine people.
|
||||
* [Robbie Pitts](https://github.com/robbiepitts)
|
||||
* [Thiago Pontes](https://github.com/thiagopnts)
|
||||
* [Sean Prashad](https://github.com/SeanPrashad)
|
||||
* [Jordan Rose](https://github.com/jrose-signal)
|
||||
* [Antonio Scandurra](https://github.com/as-cii)
|
||||
* [Edward Shaw](https://github.com/EdShaw)
|
||||
* [Nathan Sobo](https://github.com/nathansobo)
|
||||
* [André Staltz](https://github.com/staltz)
|
||||
* [Ingvar Stepanyan](https://github.com/RReverser)
|
||||
* [stoically](https://github.com/stoically)
|
||||
* [Andrew Stucki](https://github.com/andrewstucki)
|
||||
@ -41,8 +52,11 @@ Neon owes its existence to the contributions of these fine people.
|
||||
* [A2ZH (theJian)](https://github.com/theJian)
|
||||
* [Corbin Uselton](https://github.com/corbinu)
|
||||
* [K.J. Valencik](https://github.com/kjvalencik)
|
||||
* [Velithris](https://github.com/Zireael-N)
|
||||
* [Roberto Vidal](https://github.com/jrvidal)
|
||||
* [Georg Vienna](https://github.com/geovie)
|
||||
* [Daijiro Wachi](https://github.com/watilde)
|
||||
* [Chi Wang](https://github.com/patr0nus)
|
||||
* [wangcong](https://github.com/king6cong)
|
||||
* [Amila Welihinda](https://github.com/amilajack)
|
||||
* [Felix Yan](https://github.com/felixonmars)
|
||||
|
||||
@ -18,7 +18,7 @@ we encourage you to [submit an RFC](https://github.com/neon-bindings/rfcs)!
|
||||
|
||||
The [RFC process](https://github.com/neon-bindings/rfcs#the-process) has a little more overhead than
|
||||
filing an issue, but it's for the goal of allowing the Neon community to have a chance to vet
|
||||
design ideas and reach consensus. And even at that, we've deliberately kept the [RFC template](https://github.com/neon-bindings/rfcs/blob/master/0000-template.md)
|
||||
design ideas and reach consensus. And even at that, we've deliberately kept the [RFC template](https://github.com/neon-bindings/rfcs/blob/main/0000-template.md)
|
||||
simple and open-ended.
|
||||
|
||||
### Good first bugs
|
||||
@ -41,4 +41,4 @@ Unless you explicitly state otherwise, any contribution intentionally submitted
|
||||
|
||||
## Communication
|
||||
|
||||
* Slack: http://neon-community.slack.com -- get an invite from [the Slackin app](http://neon-community-slackin.herokuapp.com)
|
||||
* Slack: <https://rust-bindings.slack.com> -- get an invite from [the Slackin app](https://rust-bindings-slackin.herokuapp.com)
|
||||
|
||||
52
Cargo.toml
52
Cargo.toml
@ -1,28 +1,32 @@
|
||||
[package]
|
||||
name = "neon"
|
||||
version = "0.4.0"
|
||||
version = "0.8.2"
|
||||
authors = ["Dave Herman <david.herman@gmail.com>"]
|
||||
description = "A safe abstraction layer for Node.js."
|
||||
readme = "README.md"
|
||||
documentation = "https://api.neon-bindings.com/neon/index.html"
|
||||
homepage = "https://www.neon-bindings.com"
|
||||
repository = "https://github.com/neon-bindings/neon"
|
||||
license = "MIT/Apache-2.0"
|
||||
exclude = ["neon.jpg"]
|
||||
exclude = ["neon.jpg", "doc/**/*"]
|
||||
build = "build.rs"
|
||||
edition = "2018"
|
||||
|
||||
[build-dependencies]
|
||||
neon-build = { version = "=0.4.0", path = "crates/neon-build" }
|
||||
neon-build = { version = "=0.8.2", path = "crates/neon-build" }
|
||||
|
||||
[dev-dependencies]
|
||||
lazy_static = "1.4.0"
|
||||
rustversion = "0.1.4"
|
||||
semver = "0.9"
|
||||
psd = "0.1.9" # used for a doc example
|
||||
failure = "0.1.5" # used for a doc example
|
||||
|
||||
[dependencies]
|
||||
cslice = "0.2"
|
||||
semver = "0.9.0"
|
||||
neon-runtime = { version = "=0.4.0", path = "crates/neon-runtime" }
|
||||
smallvec = "1.4.2"
|
||||
neon-runtime = { version = "=0.8.2", path = "crates/neon-runtime" }
|
||||
neon-macros = { version = "=0.8.2", path = "crates/neon-macros", optional = true }
|
||||
|
||||
[features]
|
||||
default = ["legacy-runtime"]
|
||||
@ -41,23 +45,47 @@ default-panic-hook = []
|
||||
# enabled by default.
|
||||
legacy-runtime = ["neon-runtime/neon-sys", "neon-build/neon-sys"]
|
||||
|
||||
# Feature flag to enable the experimental N-API runtime. For now, this feature
|
||||
# is disabled by default.
|
||||
napi-runtime = ["neon-runtime/nodejs-sys"]
|
||||
# Default N-API version. Prefer to select a minimum required version.
|
||||
napi-runtime = ["napi-6"]
|
||||
|
||||
# Feature flag to disable external dependencies on docs build
|
||||
# Select the N-API version
|
||||
# Feature flags to enable the experimental N-API runtime. For now, this feature
|
||||
# is disabled by default.
|
||||
# The Node N-API documentation specifies N-API and Node version requirements
|
||||
# https://nodejs.org/api/n-api.html
|
||||
napi-1 = ["proc-macros", "neon-macros/napi", "neon-runtime/napi"]
|
||||
napi-2 = ["napi-1", "neon-runtime/napi-2"]
|
||||
napi-3 = ["napi-2", "neon-runtime/napi-3"]
|
||||
napi-4 = ["napi-3", "neon-runtime/napi-4"]
|
||||
napi-5 = ["napi-4", "neon-runtime/napi-5"]
|
||||
napi-6 = ["napi-5", "neon-runtime/napi-6"]
|
||||
napi-latest = ["napi-6"]
|
||||
napi-experimental = ["napi-6", "neon-runtime/napi-experimental"]
|
||||
|
||||
# Feature flag to disable external dependencies on docs build
|
||||
docs-only = ["neon-runtime/docs-only"]
|
||||
|
||||
# Feature flag to enable the try_catch API of RFC 29.
|
||||
try-catch-api = []
|
||||
|
||||
# Feature flag to enable the `EventQueue` API of RFC 33.
|
||||
# https://github.com/neon-bindings/rfcs/pull/32
|
||||
event-queue-api = []
|
||||
|
||||
# Feature flag to include procedural macros
|
||||
proc-macros = ["neon-macros"]
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["docs-only"]
|
||||
features = ["docs-only", "event-handler-api", "proc-macros", "try-catch-api"]
|
||||
|
||||
[workspace]
|
||||
members = [
|
||||
"crates/neon-build",
|
||||
"crates/neon-macros",
|
||||
"crates/neon-runtime",
|
||||
"crates/neon-sys",
|
||||
"test/static",
|
||||
"test/electron/native",
|
||||
"test/electron",
|
||||
"test/dynamic/native",
|
||||
"test/napi/native"
|
||||
"test/napi"
|
||||
]
|
||||
|
||||
@ -1,14 +1,320 @@
|
||||
# [WIP] N-API Migration Guide
|
||||
# N-API Migration Guide
|
||||
|
||||
## Context
|
||||
## What is this about?
|
||||
|
||||
Since v10, Node.js supports an improved API for building native modules, known as [N-API](https://nodejs.org/api/n-api.html). N-API offers a clearer, more complete, and more stable API layer for writing Node.js plugins than previous Node versions did.
|
||||
|
||||
The Neon community has been [hard at work](https://github.com/neon-bindings/neon/issues/444) porting the library to a new backend based on N-API.
|
||||
|
||||
### Why N-API?
|
||||
|
||||
Some key benefits of the new backend include:
|
||||
- Compiled Neon modules will work in all versions of Node _without needing to be recompiled_, guaranteed!
|
||||
- You can precompile Neon-based libraries to be completely transparent to downstream consumers.
|
||||
- The build process is streamlined, making Neon apps more reliable and easier to debug.
|
||||
- The stability guarantees of N-API allow us to avoid risk of incompatible changes to future releases of Neon.
|
||||
|
||||
### What does this mean for me?
|
||||
|
||||
Porting Neon to N-API has been mostly transparent, but it has required a few backwards-incompatible changes. This guide provides instructions on how to migrate existing apps to the new N-API backend.
|
||||
|
||||
Fortunately, the guaranteed stability of N-API means that once Neon users do this migration, we have increased confidence in the stability of Neon. We expect this to be the **last major breaking change before reaching Neon 1.0.**
|
||||
|
||||
If you have any trouble porting, **please reach out to us** with a Neon issue or on the community Slack! We want to help everyone upgrade as smoothly and seamlessly as possible.
|
||||
|
||||
|
||||
## Getting started
|
||||
|
||||
### Supported Node versions
|
||||
|
||||
The N-API backend of Neon requires a minimum Node version of 10.0.
|
||||
|
||||
### Enabling the N-API backend
|
||||
|
||||
To enable the N-API backend, you need to:
|
||||
|
||||
1. Remove `build.rs` from the project directory and `build = "build.rs"` from the `Cargo.toml`. The N-API backend does not require a Cargo build script.
|
||||
2. Disable the default features (for now, the default features select the legacy backend) by setting `default-features = false`; and
|
||||
3. Enable the appropriate feature flag in your `Cargo.toml` to select the N-API version you need support for (each N-API version N uses the feature flag `"napi-N"`, for example `"napi-4"` for N-API version 4).
|
||||
|
||||
As a rule, you should choose the **oldest version of N-API that has the APIs you need.** (We will be adding N-API version requirements to the Neon API docs to make this clearer in the future.) You can consult the [official N-API feature matrix](https://nodejs.org/api/n-api.html#n_api_node_api_version_matrix) to see which N-API versions come with various versions of Node.
|
||||
|
||||
```toml
|
||||
[dependencies.neon]
|
||||
version = "0.8.2"
|
||||
default-features = false
|
||||
features = ["napi-4"]
|
||||
```
|
||||
|
||||
|
||||
## Minor API changes
|
||||
|
||||
### Context
|
||||
|
||||
Many methods that previously did not require context (e.g., `JsString::size`) now require a context. In many cases, this means adding an additional argument or using a convenience method on the `Context` trait.
|
||||
|
||||
### Impacted methods
|
||||
#### Affected methods
|
||||
|
||||
##### Handle
|
||||
|
||||
* `Handle`
|
||||
- `is_a`
|
||||
- `downcast`
|
||||
|
||||
`Handle::downcast` also requires a second type argument for the context type. This can usually be inferred, so you can typically use `_`.
|
||||
|
||||
**Before:**
|
||||
```rust
|
||||
value.downcast::<JsNumber>()
|
||||
```
|
||||
|
||||
**After:**
|
||||
|
||||
```rust
|
||||
value.downcast::<JsNumber, _>(&mut cx)
|
||||
```
|
||||
|
||||
##### Primitive types
|
||||
|
||||
* `JsBoolean`
|
||||
- `value`
|
||||
* `JsNull`
|
||||
- `new`
|
||||
* `JsString`
|
||||
- `size`
|
||||
- `value`
|
||||
* `JsNumber`
|
||||
- `value`
|
||||
* `JsUndefined`
|
||||
- `new`
|
||||
|
||||
##### Object APIs
|
||||
|
||||
* `PropertyKey`
|
||||
- `get_from`
|
||||
- `set_from`
|
||||
|
||||
### Handle equality
|
||||
|
||||
Handles no longer implement `Eq` or `PartialEq`, which had underspecified behavior. Use `Value::strict_equals` instead to invoke the behavior of JavaScript's `===` operator.
|
||||
|
||||
## Major API changes
|
||||
|
||||
The N-API backend introduces two categories of significant change:
|
||||
|
||||
1. Embedding Rust data, which is no longer done through the awkward and complex `declare_types!` (i.e. classes) macro, but through a simpler primitive: the `JsBox` API.
|
||||
2. Concurrency, which is offered through the Event Queue API instead of the Task API or Event Handlers, both of which are deprecated and removed in the N-API backend.
|
||||
|
||||
### Embedding Rust data
|
||||
|
||||
The `declare_types!` macro is deprecated and replaced by the `JsBox` type.
|
||||
|
||||
_Rationale:_ The `declare_types!` macro provides a syntax for defining classes, but requires substantial boilerplate and is unergonomic for simple cases and tends to interact poorly with IDEs. It's also not flexible enough to express the full range of JavaScript classes syntax and semantics. With the `JsBox` type, it's easy to embed Rust data in JavaScript objects, which can then be nested inside of more feature-rich classes defined in pure JavaScript (or TypeScript).
|
||||
|
||||
**Before:**
|
||||
|
||||
```rust
|
||||
struct User {
|
||||
first_name: String,
|
||||
last_name: String,
|
||||
}
|
||||
|
||||
impl User {
|
||||
fn full_name(&self) -> String {
|
||||
format!("{} {}", self.first_name, self.last_name)
|
||||
}
|
||||
}
|
||||
|
||||
declare_types! {
|
||||
class JsUser for User {
|
||||
init(mut cx) {
|
||||
let first_name = cx.argument::<JsString>(0)?;
|
||||
let last_name = cx.argument::<JsString>(1)?;
|
||||
Ok(User { first_name, last_name })
|
||||
}
|
||||
|
||||
method full_name(mut cx) {
|
||||
let this = cx.this();
|
||||
let guard = cx.lock();
|
||||
let user = this.borrow(&guard);
|
||||
let full_name = user.full_name();
|
||||
Ok(cx.string(full_name).upcast())
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**After:**
|
||||
|
||||
On the Rust side, the wrapped type must implement the `Finalize` trait, but this comes with a default implementation so it can be implemented with an empty `impl` block:
|
||||
|
||||
```rust
|
||||
struct User {
|
||||
first_name: String,
|
||||
last_name: String,
|
||||
}
|
||||
|
||||
impl Finalize for User { }
|
||||
```
|
||||
|
||||
The type can then be exposed to JavaScript with simple functions that wrap `User` in a `JsBox`:
|
||||
|
||||
```rust
|
||||
fn create_user(mut cx: FunctionContext) -> JsResult<JsBox<User>> {
|
||||
let first_name = cx.argument::<JsString>(0)?.value(&mut cx);
|
||||
let last_name = cx.argument::<JsString>(1)?.value(&mut cx);
|
||||
Ok(cx.boxed(User { first_name, last_name }))
|
||||
}
|
||||
|
||||
fn user_full_name(mut cx: FunctionContext) -> JsResult<JsString> {
|
||||
let user = cx.argument::<JsBox<User>>(0)?;
|
||||
let full_name = user.full_name();
|
||||
Ok(cx.string(full_name))
|
||||
}
|
||||
```
|
||||
|
||||
Finally, you can provide an idiomatic JavaScript interface to the type by wrapping the boxed type in a class:
|
||||
|
||||
```js
|
||||
class User {
|
||||
constructor(firstName, lastName) {
|
||||
this.boxed = addon.createUser(firstName, lastName);
|
||||
}
|
||||
|
||||
fullName() {
|
||||
return addon.userFullName(this.boxed);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Concurrency
|
||||
|
||||
The supported mechanism for concurrency is the Event Queue API (`neon::event::EventQueue`). This feature has not yet stabilized, so to use this API, you'll also need to enable the `"event-queue-api"` feature flag as well:
|
||||
|
||||
```toml
|
||||
[dependencies.neon]
|
||||
version = "0.8.1"
|
||||
default-features = false
|
||||
features = ["napi-4", "event-queue-api"]
|
||||
```
|
||||
|
||||
#### Deprecated: Task API
|
||||
|
||||
The Task API (`neon::task`) is deprecated, and should in most cases be translated to using the Event Queue API.
|
||||
|
||||
_Rationale:_ The Task API was built on top of the low-level libuv thread pool, which manages the concurrency of the Node.js system internals and should rarely be exposed to user-level programs. For most use cases, Neon users took advantage of this API as the only way to implement background, asynchronous computations. The Event Queue API is a more general-purpose, convenient, and safe way of achieving that purpose.
|
||||
|
||||
That said, **if you believe you need access to the libuv thread pool, please [file an issue in the Neon repository](https://github.com/neon-bindings/neon/issues) with a description of your use case to let us know about it.** We don't believe this is commonly needed, but we don't want to leave you stuck!
|
||||
|
||||
**Before:**
|
||||
|
||||
With the `Task` API it was possible to define background computations off the main JavaScript thread, but these could only be run within the libuv thread pool--which runs all the system logic for the internals of Node.js. This gave Neon programmers a real power but forced them to contend with Node.js system tasks.
|
||||
|
||||
```rust
|
||||
impl Task for MyTask {
|
||||
type Output = i32;
|
||||
type Error = String;
|
||||
type JsEvent = JsNumber;
|
||||
|
||||
fn perform(&self) -> Result<Self::Output, Self::Error> {
|
||||
// compute the result...
|
||||
}
|
||||
|
||||
fn complete(self, mut cx: TaskContext, result: Result<Self::Output, Self::Error>) -> JsResult<Self::JsEvent> {
|
||||
match result {
|
||||
Ok(n) => {
|
||||
Ok(cx.number(n))
|
||||
}
|
||||
Err(s) => {
|
||||
cx.throw_error(s)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start_task(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
||||
let callback = cx.argument::<JsFunction>(0)?;
|
||||
MyTask.schedule(callback);
|
||||
Ok(cx.undefined())
|
||||
}
|
||||
```
|
||||
|
||||
**After:**
|
||||
|
||||
With the N-API backend, Neon programmers can use their own native threads and avoid competing with the Node.js system internals. This also brings some convenience since it doesn't require defining any custom trait implementations.
|
||||
|
||||
```rust
|
||||
pub fn start_task(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
||||
let callback = cx.argument::<JsFunction>(0)?.root(&mut cx);
|
||||
let queue = cx.queue();
|
||||
|
||||
std::thread::spawn(move || {
|
||||
let result = // compute the result...
|
||||
queue.send(move |mut cx| {
|
||||
let callback = callback.into_inner(&mut cx);
|
||||
let this = cx.undefined();
|
||||
let args = match result {
|
||||
Ok(n) => vec![
|
||||
cx.null().upcast::<JsValue>(),
|
||||
cx.number(result).upcast()
|
||||
],
|
||||
Err(msg) => vec![
|
||||
cx.error(msg).upcast()
|
||||
]
|
||||
};
|
||||
callback.call(&mut cx, this, args)?;
|
||||
Ok(())
|
||||
});
|
||||
});
|
||||
|
||||
Ok(cx.undefined())
|
||||
}
|
||||
```
|
||||
|
||||
#### Deprecated: Event Handler API
|
||||
|
||||
The Event Handler API (`neon::event::EventHandler`) is deprecated and should be replaced by the Event Queue API.
|
||||
|
||||
_Rationale_: The Event Handler API had multiple issues with safety, memory leaks, and ergonomics ([1](https://github.com/neon-bindings/neon/issues/551), [2](https://github.com/neon-bindings/rfcs/issues/31)).
|
||||
|
||||
**Before:**
|
||||
|
||||
```rust
|
||||
pub fn start_task(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
||||
let callback = cx.argument::<JsFunction>(0)?;
|
||||
let handler = EventHandler::new(callback);
|
||||
thread::spawn(move || {
|
||||
let result = // compute the result...
|
||||
handler.schedule(move |cx| {
|
||||
vec![cx.number(result).upcast()]
|
||||
});
|
||||
});
|
||||
Ok(cx.undefined())
|
||||
}
|
||||
```
|
||||
|
||||
**After:**
|
||||
|
||||
```rust
|
||||
pub fn start_task(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
||||
let callback = cx.argument::<JsFunction>(0)?.root(&mut cx);
|
||||
let queue = cx.queue();
|
||||
|
||||
std::thread::spawn(move || {
|
||||
let result = // compute the result...
|
||||
queue.send(move |mut cx| {
|
||||
let callback = callback.into_inner(&mut cx);
|
||||
let this = cx.undefined();
|
||||
let args = vec![
|
||||
cx.null().upcast::<JsValue>(),
|
||||
cx.number(result).upcast()
|
||||
];
|
||||
callback.call(&mut cx, this, args)?;
|
||||
Ok(())
|
||||
});
|
||||
});
|
||||
|
||||
Ok(cx.undefined())
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
28
README.md
28
README.md
@ -1,9 +1,10 @@
|
||||
<img src="neon.png" alt="neon" width="100%" />
|
||||
|
||||
[](https://travis-ci.org/neon-bindings/neon)
|
||||
[](https://ci.appveyor.com/project/dherman/neon/branch/master)
|
||||
[](https://crates.io/crates/neon)
|
||||
[](https://crates.io/crates/neon)
|
||||
[](https://www.npmjs.com/package/neon-cli)
|
||||
[](https://github.com/neon-bindings/neon/actions?query=workflow%3A%22Test+on+Linux%22)
|
||||
[](https://github.com/neon-bindings/neon/actions?query=workflow%3A%22Test+on+MacOS%22)
|
||||
[](https://github.com/neon-bindings/neon/actions?query=workflow%3A%22Test+on+Windows%22)
|
||||
|
||||
Rust bindings for writing safe and fast native Node.js modules.
|
||||
|
||||
@ -12,15 +13,22 @@ Rust bindings for writing safe and fast native Node.js modules.
|
||||
Once you have the [platform dependencies](https://neon-bindings.com/docs/getting-started#install-node-build-tools/) installed, getting started is as simple as:
|
||||
|
||||
```
|
||||
$ npm install -g neon-cli
|
||||
$ neon new my-project
|
||||
$ npm init neon my-project
|
||||
```
|
||||
|
||||
Then see the [Hello World guide](https://neon-bindings.com/docs/hello-world/) for writing your first Hello World in Neon!
|
||||
|
||||
_**Note:** This will create a new project with the `napi-backend` and some documentation may not be up to date._
|
||||
|
||||
# Docs
|
||||
|
||||
See our [Neon fundamentals docs](https://neon-bindings.com/docs/primitives) and our [API docs](https://neon-bindings.com/api/neon/).
|
||||
See our [Neon fundamentals docs](https://neon-bindings.com/docs/intro) and our [API docs](https://docs.rs/neon/latest/neon).
|
||||
|
||||
# N-API Migration Guide
|
||||
|
||||
We've ported Neon to a new backend based on [N-API](https://nodejs.org/api/n-api.html), which will be the basis for Neon 1.0.
|
||||
|
||||
**Read the new [migration guide](https://github.com/neon-bindings/neon/blob/main/MIGRATION_GUIDE.md)** to learn how to port your Neon projects to N-API!
|
||||
|
||||
# Platform Support
|
||||
|
||||
@ -32,11 +40,11 @@ See our [Neon fundamentals docs](https://neon-bindings.com/docs/primitives) and
|
||||
|
||||
### Node.js
|
||||
|
||||
| Node 8 | Node 10 | Node 12 |
|
||||
| ------ | ------- | ------- |
|
||||
| ✓ | ✓ | ✓ |
|
||||
| Node 12 | Node 14 | Node 16 |
|
||||
| ------- | ------- | ------- |
|
||||
| ✓ | ✓ | ✓ |
|
||||
|
||||
Support for [LTS versions of Node](https://github.com/nodejs/LTS#lts-schedule) and current are expected. If you're using a different version of Node and believe it should be supported, let us know.
|
||||
Support for [LTS versions of Node](https://github.com/nodejs/LTS#release-schedule) and current are expected. If you're using a different version of Node and believe it should be supported, let us know.
|
||||
|
||||
### Rust
|
||||
|
||||
|
||||
181
RELEASES.md
181
RELEASES.md
@ -1,8 +1,165 @@
|
||||
# Version 0.8.2
|
||||
|
||||
* More docs improvements
|
||||
* Added a deprecation warning to `neon new` (https://github.com/neon-bindings/neon/pull/722)
|
||||
|
||||
# Version 0.8.1
|
||||
|
||||
* Fix `legacy-backend` for Node 16 (https://github.com/neon-bindings/neon/pull/715)
|
||||
* Various docs improvements
|
||||
|
||||
# Version 0.8.0
|
||||
|
||||
## Fixes
|
||||
|
||||
* `as_slice` and `as_mut_slice` properly handle a `null` pointer from an empty buffer (https://github.com/neon-bindings/neon/pull/681)
|
||||
* Global drop queue added to avoid panics on N-API 6+ when dropping a `Root` (https://github.com/neon-bindings/neon/pull/700)
|
||||
|
||||
## Features
|
||||
|
||||
* Added `neon::reflect::eval` (https://github.com/neon-bindings/neon/pull/692)
|
||||
* Added `create-neon` for creating an N-API project (https://github.com/neon-bindings/neon/pull/690)
|
||||
* Added details to the `README.md` generated by `create-neon` (https://github.com/neon-bindings/neon/pull/697)
|
||||
|
||||
## Improvements
|
||||
|
||||
* Switched N-API tests to `cargo-cp-artifact` (https://github.com/neon-bindings/neon/pull/687)
|
||||
* Added `impl<T: Finalize> Finalize for Option<T>` (https://github.com/neon-bindings/neon/pull/680)
|
||||
* Added a N-API migration guide (https://github.com/neon-bindings/neon/pull/685)
|
||||
|
||||
## Housekeeping
|
||||
|
||||
* Lint fixes (https://github.com/neon-bindings/neon/pull/609)
|
||||
* Lint CI enforcement and `cargo fmt` (https://github.com/neon-bindings/neon/pull/698)
|
||||
|
||||
# Version 0.7.1
|
||||
|
||||
### Features
|
||||
|
||||
* Added `JsDate` to N-API backend (https://github.com/neon-bindings/neon/pull/639)
|
||||
* Implement `JsBuffer::unitialized` for N-API backend (https://github.com/neon-bindings/neon/pull/664)
|
||||
|
||||
### Fixes
|
||||
|
||||
* Do not panic if a `Root` is leaked after the event loop has stopped (https://github.com/neon-bindings/neon/pull/677)
|
||||
* Stubs for features that will not be implemented in the N-API backend are removed (https://github.com/neon-bindings/neon/pull/663)
|
||||
* Fix doc URL link (https://github.com/neon-bindings/neon/pull/663)
|
||||
|
||||
# Version 0.7.0
|
||||
|
||||
## N-API
|
||||
|
||||
### Version Selection
|
||||
|
||||
Neon supports a large number of different Node versions which may have different N-API requirements. Neon now supports selecting the minimum required N-API version required by a module. For example, for N-API Version 4:
|
||||
|
||||
```toml
|
||||
neon = { version = "0.7", default-features = false, features = ["napi-4"] }
|
||||
```
|
||||
|
||||
If the Neon module is loaded in an older version of Node that does not support that N-API version, a `panic` message will inform the user.
|
||||
|
||||
### Threadsafe Functions
|
||||
|
||||
A prerelease version of `EventQueue` for calling into the main JavaScript thread from Rust threads can be enabled with the `event-queue-api` feature flag. The API is considered unstable and may change in the future until the [RFC](https://github.com/neon-bindings/rfcs/pull/32) is merged.
|
||||
|
||||
# Version 0.6.0
|
||||
|
||||
The `cx.try_catch(..)` API has been updated to return `T: Sized` instead of `T: Value` (https://github.com/neon-bindings/neon/pull/631). This API is strictly more powerful and allows users to return both JavaScript and Rust values from `try_catch` closures.
|
||||
|
||||
## N-API
|
||||
|
||||
* N-API symbols are now loaded dynamically (https://github.com/neon-bindings/neon/pull/646)
|
||||
* Build process for N-API is greatly simplified by leveraging dynamic loading (https://github.com/neon-bindings/neon/pull/647)
|
||||
|
||||
# Version 0.5.3
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
Upgrade `node-gyp` (https://github.com/neon-bindings/neon/pull/623)
|
||||
* Fix Windows Node 15
|
||||
* Fix Apple M1
|
||||
|
||||
## Features
|
||||
|
||||
Added `neon::main` macro as a replacement for `register_module!` (https://github.com/neon-bindings/neon/pull/636)
|
||||
|
||||
## Known Issues
|
||||
|
||||
Builds occassionally fail with Windows, Node 15 and npm 7 (https://github.com/neon-bindings/neon/issues/642)
|
||||
|
||||
# Version 0.5.2
|
||||
|
||||
## CLI
|
||||
|
||||
Added support for [additional arguments](https://github.com/neon-bindings/neon/pull/633) passed to `cargo build`. Resolves https://github.com/neon-bindings/neon/issues/471.
|
||||
|
||||
```sh
|
||||
neon build --release -- --features awesome
|
||||
```
|
||||
|
||||
## N-API
|
||||
|
||||
* Improved [arguments performance](https://github.com/neon-bindings/neon/pull/610)
|
||||
* Add [redirect and `NPM_CONFIG_DISTURL`](https://github.com/neon-bindings/neon/pull/620) support
|
||||
|
||||
# Version 0.5.1
|
||||
|
||||
## Performance
|
||||
|
||||
* `smallvec` is used for collecting arguments and yields a small performance gain when calling `JsFunction`
|
||||
|
||||
## Broader Support
|
||||
|
||||
Thanks to @staltz, neon now builds for both iOS and Android with [nodejs-mobile](https://github.com/JaneaSystems/nodejs-mobile).
|
||||
|
||||
# Version 0.5.0
|
||||
|
||||
_Re-publish_
|
||||
|
||||
Versions `0.4.1` and `0.4.2` included a breaking change in `neon-runtime`. At the time, this was considered acceptable because `neon-runtime` is considered an internal crate and not part of the public API. However, it was discovered, after publishing, that `neon-serde`, a commonly used crate in the `neon` ecosystem, contained a direct dependency on `neon-runtime`. In order to best support users, versions `0.4.1` and `0.4.2` were "yanked" and re-published as `0.5.0`.
|
||||
|
||||
Additionally, the team is working with the authors of `neon-serde` to remove the dependency on `neon-runtime` to prevent future issues.
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
* Fix stack overflow in `DowncastError` `Display` impl (https://github.com/neon-bindings/neon/pull/606)
|
||||
|
||||
# Version 0.4.2
|
||||
|
||||
_Unpublished / Yanked_
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
* Fix memory leak and race condition in `EventHandler`
|
||||
|
||||
# Version 0.4.1
|
||||
|
||||
_Unpublished / Yanked_
|
||||
|
||||
## Features
|
||||
|
||||
### Try Catch
|
||||
|
||||
Added the `cx.try_catch` API of [RFC 29](https://github.com/neon-bindings/rfcs/pull/29). This feature is behind the `try-catch-api` feature flag.
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
* Pass `async_context` to `node::MakeCallback` (https://github.com/neon-bindings/neon/pull/498)
|
||||
* Cache bust neon if node version changes (https://github.com/neon-bindings/neon/pull/388)
|
||||
* Fix debug builds in windows (https://github.com/neon-bindings/neon/pull/400)
|
||||
* Fix cross compiling architectures (https://github.com/neon-bindings/neon/pull/491)
|
||||
* Fix neon new hanging on Windows (https://github.com/neon-bindings/neon/pull/537)
|
||||
|
||||
## CI Improvements
|
||||
|
||||
The Neon Project now uses Github Actions thanks to @lhr0909! As part of this change, CI now runs on all of our supported platforms (macOS, Windows, linux) and Node versions.
|
||||
|
||||
# Version ✨0.4✨ 🎉
|
||||
|
||||
## `EventHandler` API
|
||||
|
||||
The [`EventHandler` API](https://github.com/neon-bindings/rfcs/blob/master/text/0025-event-handler.md) is a new feature for scheduling work on the javascript main thread from other threads. Big thanks to @geovie for the RFC and implementation.
|
||||
The [`EventHandler` API](https://github.com/neon-bindings/rfcs/blob/main/text/0025-event-handler.md) is a new feature for scheduling work on the javascript main thread from other threads. Big thanks to @geovie for the RFC and implementation.
|
||||
|
||||
This feature is currently _unstable_ and gated by a `event-handler-api` feature flag.
|
||||
|
||||
@ -47,7 +204,7 @@ Since `neon-build` has been included in the project template since `0.1` this ch
|
||||
|
||||
## N-API
|
||||
|
||||
Neon 0.3.2 lays the groundwork for the next major revision. Development of Neon against an ABI stable Node API (N-API) will occur on master.
|
||||
Neon 0.3.2 lays the groundwork for the next major revision. Development of Neon against an ABI stable Node API (N-API) will occur on main.
|
||||
|
||||
* Added `legacy-runtime` and `n-api` feature flags for toggling neon runtime
|
||||
* Moved the legacy runtime to `nodejs-sys` crate
|
||||
@ -81,16 +238,16 @@ Neon 0.3.2 lays the groundwork for the next major revision. Development of Neon
|
||||
See the [Neon 0.2 Migration Guide](https://github.com/neon-bindings/neon/wiki/Neon-0.2-Migration-Guide) for documentation on migrating your projects from the Neon 0.1.x series to Neon 0.2, and please [let us know](https://github.com/neon-bindings/neon#get-involved) if you need help!
|
||||
|
||||
* Release automation (#318)
|
||||
* New `ArrayBuffer` views API -- see [RFC 5](https://github.com/neon-bindings/rfcs/blob/master/text/0005-array-buffer-views.md) (#306)
|
||||
* VM 2.0 -- see [RFC 14](https://github.com/neon-bindings/rfcs/blob/master/text/0014-vm-2.0.md) (#306)
|
||||
* New `JsString` constructor -- see [RFC 21](https://github.com/neon-bindings/rfcs/blob/master/text/0021-string-constructor.md) (#322)
|
||||
* Eliminated `JsInteger`, `JsVariant`, `callee()` -- see [RFC 22](https://github.com/neon-bindings/rfcs/blob/master/text/0022-zero-dot-two.md) (#323)
|
||||
* Renamed `Key` to `PropertyKey` and its method names -- see [RFC 22](https://github.com/neon-bindings/rfcs/blob/master/text/0022-zero-dot-two.md) (#323)
|
||||
* Module reorganization -- see [RFC 20](https://github.com/neon-bindings/rfcs/blob/master/text/0020-module-reorg.md) (#324)
|
||||
* New `JsError` API -- see [RFC 23](https://github.com/neon-bindings/rfcs/blob/master/text/0023-error-subtyping.md) (#325)
|
||||
* Eliminated `ToJsString` API -- see [RFC 22](https://github.com/neon-bindings/rfcs/blob/master/text/0022-zero-dot-two.md) (#326)
|
||||
* Eliminated `NEON_NODE_ABI` env var -- see [RFC 22](https://github.com/neon-bindings/rfcs/blob/master/text/0022-zero-dot-two.md) (#327)
|
||||
* Default to release builds -- see [RFC 22](https://github.com/neon-bindings/rfcs/blob/master/text/0022-zero-dot-two.md) (#328)
|
||||
* New `ArrayBuffer` views API -- see [RFC 5](https://github.com/neon-bindings/rfcs/blob/main/text/0005-array-buffer-views.md) (#306)
|
||||
* VM 2.0 -- see [RFC 14](https://github.com/neon-bindings/rfcs/blob/main/text/0014-vm-2.0.md) (#306)
|
||||
* New `JsString` constructor -- see [RFC 21](https://github.com/neon-bindings/rfcs/blob/main/text/0021-string-constructor.md) (#322)
|
||||
* Eliminated `JsInteger`, `JsVariant`, `callee()` -- see [RFC 22](https://github.com/neon-bindings/rfcs/blob/main/text/0022-zero-dot-two.md) (#323)
|
||||
* Renamed `Key` to `PropertyKey` and its method names -- see [RFC 22](https://github.com/neon-bindings/rfcs/blob/main/text/0022-zero-dot-two.md) (#323)
|
||||
* Module reorganization -- see [RFC 20](https://github.com/neon-bindings/rfcs/blob/main/text/0020-module-reorg.md) (#324)
|
||||
* New `JsError` API -- see [RFC 23](https://github.com/neon-bindings/rfcs/blob/main/text/0023-error-subtyping.md) (#325)
|
||||
* Eliminated `ToJsString` API -- see [RFC 22](https://github.com/neon-bindings/rfcs/blob/main/text/0022-zero-dot-two.md) (#326)
|
||||
* Eliminated `NEON_NODE_ABI` env var -- see [RFC 22](https://github.com/neon-bindings/rfcs/blob/main/text/0022-zero-dot-two.md) (#327)
|
||||
* Default to release builds -- see [RFC 22](https://github.com/neon-bindings/rfcs/blob/main/text/0022-zero-dot-two.md) (#328)
|
||||
* Made `Buffer` construction safe by default (#329, #331)
|
||||
* Made `Throw` not implement `std::error::Error` to avoid accidental suppression, thanks to [@kjvalencik](https://github.com/kjvalencik) (#334)
|
||||
* Fixed a bug causing unnecessary rebuilds, thanks to [@kjvalencik](https://github.com/kjvalencik) (#343)
|
||||
|
||||
49
appveyor.yml
49
appveyor.yml
@ -1,49 +0,0 @@
|
||||
os: unstable
|
||||
image: Visual Studio 2015
|
||||
|
||||
environment:
|
||||
RUST_BACKTRACE: 1
|
||||
matrix:
|
||||
- PLATFORM: x64
|
||||
NODEJS_VERSION: "8"
|
||||
RUST_TOOLCHAIN: stable-x86_64-pc-windows-msvc
|
||||
- PLATFORM: x64
|
||||
NODEJS_VERSION: "10"
|
||||
RUST_TOOLCHAIN: stable-x86_64-pc-windows-msvc
|
||||
- PLATFORM: x64
|
||||
NODEJS_VERSION: "10"
|
||||
RUST_TOOLCHAIN: beta-x86_64-pc-windows-msvc
|
||||
- PLATFORM: x64
|
||||
NODEJS_VERSION: "10"
|
||||
RUST_TOOLCHAIN: nightly-x86_64-pc-windows-msvc
|
||||
- PLATFORM: x64
|
||||
NODEJS_VERSION: "12"
|
||||
RUST_TOOLCHAIN: stable-x86_64-pc-windows-msvc
|
||||
- PLATFORM: x64
|
||||
NODEJS_VERSION: "12"
|
||||
RUST_TOOLCHAIN: beta-x86_64-pc-windows-msvc
|
||||
- PLATFORM: x64
|
||||
NODEJS_VERSION: "12"
|
||||
RUST_TOOLCHAIN: nightly-x86_64-pc-windows-msvc
|
||||
|
||||
install:
|
||||
- ps: Install-Product node $env:NODEJS_VERSION $env:PLATFORM
|
||||
# Workaround until https://github.com/nodejs/node-gyp/issues/1933 is fixed.
|
||||
- npm install -g npm@6.11.3
|
||||
- npm config set msvs_version 2015
|
||||
- node -e "console.log(process.argv[0], process.arch, process.versions)"
|
||||
- curl -sSf -o rustup-init.exe https://win.rustup.rs
|
||||
- rustup-init.exe -y --default-toolchain %RUST_TOOLCHAIN%
|
||||
- set PATH=%PATH%;C:\Users\appveyor\.cargo\bin
|
||||
- rustup show
|
||||
- rustc -V
|
||||
- cargo -V
|
||||
|
||||
build: false
|
||||
|
||||
test_script:
|
||||
- cargo test --release
|
||||
|
||||
cache:
|
||||
- target
|
||||
- C:\Users\appveyor\.cargo\registry
|
||||
@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
require('make-promises-safe');
|
||||
var CLI = require('../lib/cli.js').default;
|
||||
var cli = new CLI(process.argv, process.cwd());
|
||||
cli.exec()
|
||||
|
||||
2090
cli/package-lock.json
generated
2090
cli/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "neon-cli",
|
||||
"version": "0.4.0",
|
||||
"version": "0.8.2",
|
||||
"description": "Build and load native Rust/Neon modules.",
|
||||
"author": "Dave Herman <david.herman@gmail.com>",
|
||||
"repository": {
|
||||
@ -10,48 +10,34 @@
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
"bin": {
|
||||
"neon": "./bin/cli.js"
|
||||
"neon": "bin/cli.js"
|
||||
},
|
||||
"license": "SEE LICENSE IN LICENSE-*",
|
||||
"dependencies": {
|
||||
"chalk": "~2.1.0",
|
||||
"command-line-args": "^4.0.2",
|
||||
"command-line-commands": "^2.0.0",
|
||||
"command-line-usage": "^4.0.0",
|
||||
"chalk": "^4.1.0",
|
||||
"command-line-args": "^5.1.1",
|
||||
"command-line-commands": "^3.0.1",
|
||||
"command-line-usage": "^6.1.0",
|
||||
"git-config": "0.0.7",
|
||||
"handlebars": "^4.1.0",
|
||||
"inquirer": "^3.0.6",
|
||||
"mkdirp": "^0.5.1",
|
||||
"quickly-copy-file": "^1.0.0",
|
||||
"rimraf": "^2.6.1",
|
||||
"rsvp": "^4.6.1",
|
||||
"semver": "^5.1.0",
|
||||
"toml": "^2.3.0",
|
||||
"ts-typed-json": "^0.2.2",
|
||||
"validate-npm-package-license": "^3.0.1",
|
||||
"handlebars": "^4.7.6",
|
||||
"inquirer": "^7.3.3",
|
||||
"make-promises-safe": "^5.1.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"semver": "^7.3.2",
|
||||
"toml": "^3.0.0",
|
||||
"ts-typed-json": "^0.3.2",
|
||||
"validate-npm-package-license": "^3.0.4",
|
||||
"validate-npm-package-name": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chai": "^4.1.3",
|
||||
"@types/chalk": "^0.4.31",
|
||||
"@types/es6-promise": "0.0.33",
|
||||
"@types/inquirer": "0.0.35",
|
||||
"@types/mkdirp": "^0.5.1",
|
||||
"@types/mocha": "^5.2.0",
|
||||
"@types/nexpect": "^0.4.29",
|
||||
"@types/node": "^8.10.39",
|
||||
"@types/rimraf": "^2.0.2",
|
||||
"@types/rsvp": "^3.3.1",
|
||||
"@types/semver": "^5.3.31",
|
||||
"@types/tmp": "0.0.33",
|
||||
"chai": "^4.1.2",
|
||||
"mocha": "^5.2.0",
|
||||
"nexpect": "^0.5.0",
|
||||
"tmp": "0.0.33",
|
||||
"ts-dict": "^0.1.1",
|
||||
"ts-node": "^3.0.2",
|
||||
"ts-unknown": "^0.2.0",
|
||||
"typescript": "^2.2.2"
|
||||
"@types/chalk": "^2.2.0",
|
||||
"@types/inquirer": "^7.3.0",
|
||||
"@types/mocha": "^8.0.1",
|
||||
"@types/node": "10.17.26",
|
||||
"@types/rimraf": "^3.0.0",
|
||||
"@types/semver": "^7.3.1",
|
||||
"mocha": "^8.1.0",
|
||||
"typescript": "^3.9.7"
|
||||
},
|
||||
"scripts": {
|
||||
"transpile": "tsc",
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import BuildSettings from './build-settings';
|
||||
import { writeFileSync } from 'fs';
|
||||
import Dict from 'ts-dict';
|
||||
import * as JSON from 'ts-typed-json';
|
||||
|
||||
/**
|
||||
@ -16,10 +15,10 @@ export default class Artifacts {
|
||||
/**
|
||||
* A table tracking the state of any build artifacts in the `target`
|
||||
* directory.
|
||||
*
|
||||
*
|
||||
* On Windows, this table has the type:
|
||||
*
|
||||
* ```
|
||||
*
|
||||
* ```json
|
||||
* {
|
||||
* "i686-pc-windows-msvc\\debug"?: BuildSettings,
|
||||
* "i686-pc-windows-msvc\\release"?: BuildSettings,
|
||||
@ -27,20 +26,20 @@ export default class Artifacts {
|
||||
* "x86_64-pc-windows-msvc\\release"?: BuildSettings
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
*
|
||||
* On Linux and macOS, this table has the type:
|
||||
*
|
||||
* ```
|
||||
*
|
||||
* ```json
|
||||
* {
|
||||
* "debug"?: BuildSettings,
|
||||
* "release"?: BuildSettings
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
private targets: Dict<BuildSettings>;
|
||||
private targets: Record<string, BuildSettings>;
|
||||
|
||||
constructor(active: string | null = null,
|
||||
targets: Dict<BuildSettings> = {})
|
||||
targets: Record<string, BuildSettings> = {})
|
||||
{
|
||||
this.active = active;
|
||||
this.targets = targets;
|
||||
@ -55,18 +54,13 @@ export default class Artifacts {
|
||||
}
|
||||
|
||||
static fromJSON(json: JSON.Value): Artifacts {
|
||||
if (!JSON.isObject(json)) {
|
||||
throw new TypeError("expected object, found " + (json === null ? "null" : typeof json));
|
||||
}
|
||||
let active = json.active;
|
||||
json = JSON.asObject(json, "json");
|
||||
const active = json.active;
|
||||
if (typeof active !== 'string' && active !== null) {
|
||||
throw new TypeError("json.active is not a string or null");
|
||||
}
|
||||
let jsonTargets = json.targets;
|
||||
if (!JSON.isObject(jsonTargets)) {
|
||||
throw new TypeError("json.targets is not an object");
|
||||
}
|
||||
let targets: Dict<BuildSettings> = {};
|
||||
const jsonTargets = JSON.asObject(json.targets, "json.targets");
|
||||
let targets: Record<string, BuildSettings> = {};
|
||||
for (let key of Object.keys(jsonTargets)) {
|
||||
targets[key] = BuildSettings.fromJSON(jsonTargets[key]);
|
||||
}
|
||||
@ -74,7 +68,7 @@ export default class Artifacts {
|
||||
}
|
||||
|
||||
toJSON(): JSON.Object {
|
||||
let targets: JSON.Object = {};
|
||||
let targets = {};
|
||||
for (let target of Object.keys(this.targets)) {
|
||||
targets[target] = this.targets[target].toJSON();
|
||||
}
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { promisify } from 'util';
|
||||
import * as child from 'child_process';
|
||||
import child from 'child_process';
|
||||
|
||||
export function spawn(command: string, args?: string[], options?: child.SpawnOptions): Promise<number> {
|
||||
return new Promise((resolve, reject) => {
|
||||
let ps = child.spawn(command, args || [], options);
|
||||
let ps = child.spawn(command, args || [], options!);
|
||||
ps.on('error', reject);
|
||||
ps.on('close', resolve);
|
||||
});
|
||||
|
||||
@ -1,34 +0,0 @@
|
||||
import * as fs from 'fs';
|
||||
import quicklyCopyFile = require('quickly-copy-file');
|
||||
import RSVP = require('rsvp');
|
||||
import rimraf = require('rimraf');
|
||||
import mkdirp = require('mkdirp');
|
||||
|
||||
export let stat: (path: string) => Promise<fs.Stats>
|
||||
= RSVP.denodeify(fs.stat, false);
|
||||
|
||||
let rf: (path: string, options?: { encoding: string; flag?: string; }) => Promise<string | Buffer>
|
||||
= RSVP.denodeify(fs.readFile, false);
|
||||
|
||||
export function readFile(path: string, options: { encoding: string; flag?: string; }): Promise<string>;
|
||||
export function readFile(path: string): Promise<Buffer>;
|
||||
export function readFile(path: string, options?: { encoding: string; flag?: string; }): Promise<string | Buffer> {
|
||||
return rf(path, options);
|
||||
}
|
||||
|
||||
export type WriteOptions = {
|
||||
encoding?: string,
|
||||
mode?: number,
|
||||
flag?: string
|
||||
};
|
||||
|
||||
export let writeFile: (path: string, contents: string, options: WriteOptions) => Promise<void>
|
||||
= RSVP.denodeify(fs.writeFile, false);
|
||||
|
||||
export let copy = quicklyCopyFile;
|
||||
|
||||
export let remove: (path: string) => Promise<void>
|
||||
= RSVP.denodeify(rimraf, false);
|
||||
|
||||
export let mkdirs: (path: string) => Promise<void>
|
||||
= RSVP.denodeify(mkdirp, false);
|
||||
@ -1,7 +0,0 @@
|
||||
import RSVP = require('rsvp');
|
||||
import gitconfig = require('git-config');
|
||||
|
||||
let gc: () => Promise<gitconfig.Dict>
|
||||
= RSVP.denodeify(gitconfig, false);
|
||||
|
||||
export default gc;
|
||||
4
cli/src/async/rimraf.ts
Normal file
4
cli/src/async/rimraf.ts
Normal file
@ -0,0 +1,4 @@
|
||||
import _rimraf from 'rimraf';
|
||||
import { promisify } from 'util';
|
||||
|
||||
export const rimraf = promisify(_rimraf);
|
||||
@ -1,8 +1,7 @@
|
||||
import * as rust from './rust';
|
||||
import Dict from 'ts-dict';
|
||||
import * as JSON from 'ts-typed-json';
|
||||
|
||||
function isStringDict(x: JSON.Object): x is Dict<string | null> {
|
||||
function isStringDict(x: JSON.Object): x is Record<string, string | null> {
|
||||
for (let key of Object.keys(x)) {
|
||||
if (x[key] !== null && typeof x[key] !== 'string') {
|
||||
return false;
|
||||
@ -14,9 +13,9 @@ function isStringDict(x: JSON.Object): x is Dict<string | null> {
|
||||
export default class BuildSettings {
|
||||
private rustc: string;
|
||||
private nodeVersion: string | null;
|
||||
private env: Dict<string | null>;
|
||||
private env: Record<string, string | null>;
|
||||
|
||||
constructor(rustc: string, nodeVersion: string | null, env: Dict<string | null>) {
|
||||
constructor(rustc: string, nodeVersion: string | null, env: Record<string, string | null>) {
|
||||
this.rustc = rustc;
|
||||
this.nodeVersion = nodeVersion;
|
||||
this.env = env;
|
||||
@ -58,14 +57,16 @@ export default class BuildSettings {
|
||||
npm_config_disturl: process.env.npm_config_disturl || null,
|
||||
npm_config_runtime: process.env.npm_config_runtime || null,
|
||||
npm_config_build_from_source: process.env.npm_config_build_from_source || null,
|
||||
npm_config_devdir: process.env.npm_config_devdir || null
|
||||
npm_config_devdir: process.env.npm_config_devdir || null,
|
||||
npm_config_node_engine: process.env.npm_config_node_engine || null,
|
||||
npm_config_nodedir: process.env.npm_config_nodedir || null,
|
||||
npm_config_node_gyp: process.env.npm_config_node_gyp || null,
|
||||
npm_config_platform: process.env.npm_config_platform || null
|
||||
});
|
||||
}
|
||||
|
||||
static fromJSON(value: JSON.Value): BuildSettings {
|
||||
if (!JSON.isObject(value)) {
|
||||
throw new TypeError("value must be an object");
|
||||
}
|
||||
value = JSON.asObject(value, "value")
|
||||
let { rustc, env, nodeVersion } = value;
|
||||
if (typeof rustc !== 'string') {
|
||||
throw new TypeError("value.rustc must be a string");
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import * as path from 'path';
|
||||
import path from 'path';
|
||||
import neon_new from './ops/neon_new';
|
||||
import neon_build from './ops/neon_build';
|
||||
import neon_clean from './ops/neon_clean';
|
||||
@ -8,9 +8,7 @@ import cliArgs = require('command-line-args');
|
||||
import cliUsage = require('command-line-usage');
|
||||
import log from './log';
|
||||
import { setup as setupLogging } from './log';
|
||||
import Dict from 'ts-dict';
|
||||
import * as JSON from 'ts-typed-json';
|
||||
import unknown from 'ts-unknown';
|
||||
import { Toolchain } from './rust';
|
||||
|
||||
let metadata = JSON.loadSync(path.resolve(__dirname, '..', 'package.json'));
|
||||
@ -31,6 +29,23 @@ function logIf(multiple: boolean, action: string, cwd: string, module: string) {
|
||||
}
|
||||
}
|
||||
|
||||
function parseArgv(argv: string[]): { cli: string[], extra: string[] } {
|
||||
let splitAt = argv.indexOf('--');
|
||||
|
||||
// No additional arguments provided
|
||||
if (splitAt < 0) {
|
||||
return {
|
||||
cli: argv,
|
||||
extra: [],
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
cli: argv.slice(0, splitAt),
|
||||
extra: argv.slice(splitAt + 1)
|
||||
};
|
||||
}
|
||||
|
||||
function parseModules(cwd: string, names: string[], paths: boolean) {
|
||||
let modules = names.length
|
||||
? names.map(m => paths ? path.resolve(cwd, m)
|
||||
@ -43,7 +58,7 @@ function parseModules(cwd: string, names: string[], paths: boolean) {
|
||||
};
|
||||
}
|
||||
|
||||
type Action = (this: CLI, options: Dict<unknown>, usage: string) => void;
|
||||
type Action = (this: CLI, options: Record<string, unknown>, usage: string) => void;
|
||||
|
||||
type Command = {
|
||||
args: cliArgs.OptionDefinition[],
|
||||
@ -51,7 +66,7 @@ type Command = {
|
||||
action: Action
|
||||
};
|
||||
|
||||
type Spec = Dict<Command>;
|
||||
type Spec = Record<string, Command>;
|
||||
|
||||
const spec: Spec = {
|
||||
|
||||
@ -63,7 +78,7 @@ const spec: Spec = {
|
||||
content: "Neon is a tool for building native Node.js modules with Rust."
|
||||
}, {
|
||||
header: "Synopsis",
|
||||
content: "$ neon [options] <command>"
|
||||
content: "$ neon [options] <command> -- [cargo options]"
|
||||
}, {
|
||||
header: "Command List",
|
||||
content: [{ name: "new", summary: "Create a new Neon project." },
|
||||
@ -161,7 +176,7 @@ const spec: Spec = {
|
||||
}, {
|
||||
header: "Synopsis",
|
||||
content: ["$ neon build [options]",
|
||||
"$ neon build [options] [underline]{module} ..."]
|
||||
"$ neon build [options] {underline module} ..."]
|
||||
}, {
|
||||
header: "Options",
|
||||
optionList: [{
|
||||
@ -182,6 +197,7 @@ const spec: Spec = {
|
||||
return;
|
||||
}
|
||||
|
||||
let extra = options.extra as string[];
|
||||
let { modules, multiple } = parseModules(this.cwd,
|
||||
(options.modules || []) as string[],
|
||||
!!options.path);
|
||||
@ -189,7 +205,7 @@ const spec: Spec = {
|
||||
for (let module of modules) {
|
||||
logIf(multiple, "building", this.cwd, module);
|
||||
|
||||
await neon_build(module, this.toolchain, !!options.release);
|
||||
await neon_build(module, this.toolchain, !!options.release, extra);
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -204,7 +220,7 @@ const spec: Spec = {
|
||||
}, {
|
||||
header: "Synopsis",
|
||||
content: ["$ neon clean [options]",
|
||||
"$ neon clean [options] [underline]{module} ..."]
|
||||
"$ neon clean [options] {underline module} ..."]
|
||||
}, {
|
||||
header: "Options",
|
||||
optionList: [{
|
||||
@ -247,7 +263,7 @@ const spec: Spec = {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(JSON.asObject(metadata).version);
|
||||
console.log((JSON.asObject(metadata)).version);
|
||||
}
|
||||
}
|
||||
|
||||
@ -291,13 +307,14 @@ export default class CLI {
|
||||
}
|
||||
|
||||
process.exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
let { command, argv } = parsed;
|
||||
let { cli, extra } = parseArgv(argv);
|
||||
let options = { extra, ...cliArgs(spec[command].args, { argv: cli }) };
|
||||
await spec[command].action.call(this,
|
||||
cliArgs(spec[command].args, { argv }),
|
||||
options,
|
||||
cliUsage(spec[command].usage));
|
||||
} catch (e) {
|
||||
console.error(style.error(e.message));
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import * as TOML from 'toml';
|
||||
import * as path from 'path';
|
||||
import { readFileSync } from 'fs';
|
||||
import { remove, copy } from './async/fs';
|
||||
import TOML from 'toml';
|
||||
import path from 'path';
|
||||
import { readFileSync, promises as fs } from 'fs';
|
||||
import Artifacts from './artifacts';
|
||||
import Project from './project';
|
||||
import { rimraf } from './async/rimraf';
|
||||
|
||||
export type CrateOptions = {
|
||||
subdirectory?: string,
|
||||
@ -14,7 +14,7 @@ export type CrateOptions = {
|
||||
export default class Crate {
|
||||
/** The Neon project containing this crate. */
|
||||
readonly project: Project;
|
||||
/** The subpath of this crate relative to the Neon project root. */
|
||||
/** The subpath of this crate relative to the Neon project root. */
|
||||
readonly subdirectory: string;
|
||||
/** The subpath of the `.node` addon relative to this crate root. */
|
||||
readonly nodefile: string;
|
||||
@ -43,12 +43,12 @@ export default class Crate {
|
||||
}
|
||||
|
||||
async finish(dylib: string) {
|
||||
await remove(this.addon);
|
||||
await copy(dylib, this.addon);
|
||||
await rimraf(this.addon);
|
||||
await fs.copyFile(dylib, this.addon);
|
||||
}
|
||||
|
||||
async removeAddon() {
|
||||
await remove(this.addon);
|
||||
await rimraf(this.addon);
|
||||
}
|
||||
|
||||
resetArtifacts() {
|
||||
@ -61,10 +61,17 @@ export default class Crate {
|
||||
|
||||
}
|
||||
|
||||
function loadLibName(file: string): string {
|
||||
let metadata = TOML.parse(readFileSync(file, 'utf8'));
|
||||
type Metadata = {
|
||||
lib?: {
|
||||
name?: string
|
||||
}
|
||||
}
|
||||
|
||||
if (!metadata || typeof metadata !== 'object' || !metadata.lib.name) {
|
||||
function loadLibName(file: string): string {
|
||||
let metadata = TOML.parse<Metadata>(readFileSync(file, 'utf8'));
|
||||
if (!metadata) throw new Error(`Failed to parse TOML file "${file}"`)
|
||||
|
||||
if (!metadata || typeof metadata !== 'object' || !metadata?.lib?.name) {
|
||||
throw new Error("Cargo.toml does not contain a [lib] section with a 'name' field");
|
||||
}
|
||||
|
||||
|
||||
7
cli/src/interfaces/command-line.d.ts
vendored
7
cli/src/interfaces/command-line.d.ts
vendored
@ -1,5 +1,4 @@
|
||||
declare module 'command-line-usage' {
|
||||
import Dict from 'ts-dict';
|
||||
|
||||
namespace internal {
|
||||
export type Sections = Section | Section[];
|
||||
@ -8,7 +7,7 @@ declare module 'command-line-usage' {
|
||||
|
||||
export type ContentSection = {
|
||||
header: string,
|
||||
content: string | string[] | Dict<any>[],
|
||||
content: string | string[] | Record<string, any>[],
|
||||
raw?: boolean
|
||||
};
|
||||
|
||||
@ -43,8 +42,6 @@ declare module 'command-line-commands' {
|
||||
}
|
||||
|
||||
declare module 'command-line-args' {
|
||||
import Dict from 'ts-dict';
|
||||
import unknown from 'ts-unknown';
|
||||
|
||||
namespace internal {
|
||||
export type CommandLineArgsOptions = {
|
||||
@ -67,7 +64,7 @@ declare module 'command-line-args' {
|
||||
|
||||
function internal(optionDefinitions: internal.OptionDefinition[],
|
||||
options?: internal.CommandLineArgsOptions)
|
||||
: Dict<unknown>;
|
||||
: Record<string, unknown>;
|
||||
|
||||
export = internal;
|
||||
}
|
||||
|
||||
16
cli/src/interfaces/git-config.d.ts
vendored
16
cli/src/interfaces/git-config.d.ts
vendored
@ -1,10 +1,12 @@
|
||||
declare module 'git-config' {
|
||||
function internal(callback: internal.GitConfigCallback): void;
|
||||
namespace internal {
|
||||
export type Dict = { [key: string]: any };
|
||||
export type MaybeError = Error | null;
|
||||
export type GitConfigCallback = (err: MaybeError, config?: Dict) => void;
|
||||
export type Config = {
|
||||
user: {
|
||||
name?: string,
|
||||
email?: string
|
||||
},
|
||||
github: {
|
||||
user?: string
|
||||
}
|
||||
|
||||
export = internal;
|
||||
}
|
||||
export function sync(gitFile?: string): Config;
|
||||
}
|
||||
|
||||
4
cli/src/interfaces/quickly-copy-file.d.ts
vendored
4
cli/src/interfaces/quickly-copy-file.d.ts
vendored
@ -1,4 +0,0 @@
|
||||
declare module 'quickly-copy-file' {
|
||||
function internal(from: string, to: string): Promise<void>;
|
||||
export = internal;
|
||||
}
|
||||
4
cli/src/interfaces/toml.d.ts
vendored
4
cli/src/interfaces/toml.d.ts
vendored
@ -1,3 +1,3 @@
|
||||
declare module 'toml' {
|
||||
export function parse(source: string): any;
|
||||
}
|
||||
export function parse<T extends object>(source: string): Partial<T> | undefined | null;
|
||||
}
|
||||
|
||||
@ -3,7 +3,8 @@ import * as rust from '../rust';
|
||||
|
||||
export default async function neon_build(root: string,
|
||||
toolchain: rust.Toolchain = 'default',
|
||||
release: boolean) {
|
||||
release: boolean,
|
||||
args: string[]) {
|
||||
let project = await Project.create(root);
|
||||
await project.build(toolchain, release);
|
||||
await project.build(toolchain, release, args);
|
||||
}
|
||||
|
||||
@ -1,13 +1,15 @@
|
||||
import { readFile, writeFile, mkdirs, stat } from '../async/fs';
|
||||
import { mkdirSync, writeFileSync, promises as fsPromises } from 'fs';
|
||||
import { prompt } from 'inquirer';
|
||||
import gitconfig from '../async/git-config';
|
||||
import * as path from 'path';
|
||||
import * as handlebars from 'handlebars';
|
||||
import * as semver from 'semver';
|
||||
import path from 'path';
|
||||
import handlebars from 'handlebars';
|
||||
import semver from 'semver';
|
||||
import * as style from '../style';
|
||||
import validateLicense = require('validate-npm-package-license');
|
||||
import validateName = require('validate-npm-package-name');
|
||||
import * as JSON from 'ts-typed-json';
|
||||
import gitconfig from 'git-config';
|
||||
|
||||
const { readFile, stat } = fsPromises;
|
||||
|
||||
const ROOT_DIR = path.resolve(__dirname, '..', '..');
|
||||
const TEMPLATES_DIR = path.resolve(ROOT_DIR, 'templates');
|
||||
@ -30,13 +32,18 @@ const LIBRS_TEMPLATE = compile('lib.rs.hbs');
|
||||
const README_TEMPLATE = compile('README.md.hbs');
|
||||
const BUILDRS_TEMPLATE = compile('build.rs.hbs');
|
||||
|
||||
type Author = {
|
||||
name?: string,
|
||||
email?: string
|
||||
};
|
||||
|
||||
async function guessAuthor() {
|
||||
let author = {
|
||||
let author: Author = {
|
||||
name: process.env.USER || process.env.USERNAME,
|
||||
email: undefined
|
||||
};
|
||||
try {
|
||||
let config = await gitconfig();
|
||||
let config = gitconfig.sync();
|
||||
if (config.user.name) {
|
||||
author.name = config.user.name;
|
||||
}
|
||||
@ -73,7 +80,30 @@ async function parseNeonVersion(flag: string | null) : Promise<NeonVersion> {
|
||||
return { type: path.isAbsolute(flag) ? "absolute" : "relative", value: flag };
|
||||
}
|
||||
|
||||
interface Answers {
|
||||
name: {
|
||||
npm: {
|
||||
full: string;
|
||||
scope: string | null;
|
||||
local: string;
|
||||
};
|
||||
cargo: {
|
||||
external: string;
|
||||
internal: string;
|
||||
};
|
||||
};
|
||||
description: string;
|
||||
git: string;
|
||||
author: string;
|
||||
node: string;
|
||||
}
|
||||
|
||||
export default async function wizard(pwd: string, name: string, neon: string | null, features: string | null, noDefaultFeatures: boolean) {
|
||||
let warning = "WARN: `neon new` is deprecated. To create a new project use `npm init neon my-project`.";
|
||||
let banner = "".padStart(warning.length + 4, "#");
|
||||
|
||||
console.warn(`${banner}\n# ${warning} #\n${banner}\n`);
|
||||
|
||||
let its = validateName(name);
|
||||
if (!its.validForNewPackages) {
|
||||
let errors = (its.errors || []).concat(its.warnings || []);
|
||||
@ -92,7 +122,7 @@ export default async function wizard(pwd: string, name: string, neon: string | n
|
||||
let root = path.resolve(pwd, local);
|
||||
let guess = await guessAuthor();
|
||||
|
||||
let answers = await prompt([
|
||||
let answers: Answers = await prompt([
|
||||
{
|
||||
type: 'input',
|
||||
name: 'version',
|
||||
@ -193,16 +223,16 @@ export default async function wizard(pwd: string, name: string, neon: string | n
|
||||
let native_ = path.resolve(root, 'native');
|
||||
let src = path.resolve(native_, 'src');
|
||||
|
||||
await mkdirs(lib);
|
||||
await mkdirs(src);
|
||||
mkdirSync(lib, { recursive: true });
|
||||
mkdirSync(src, { recursive: true });
|
||||
|
||||
await writeFile(path.resolve(root, '.gitignore'), (await GITIGNORE_TEMPLATE)(ctx), { flag: 'wx' });
|
||||
await writeFile(path.resolve(root, 'package.json'), (await NPM_TEMPLATE)(ctx), { flag: 'wx' });
|
||||
await writeFile(path.resolve(native_, 'Cargo.toml'), (await CARGO_TEMPLATE)(ctx), { flag: 'wx' });
|
||||
await writeFile(path.resolve(root, 'README.md'), (await README_TEMPLATE)(ctx), { flag: 'wx' });
|
||||
await writeFile(path.resolve(root, answers.node), (await INDEXJS_TEMPLATE)(ctx), { flag: 'wx' });
|
||||
await writeFile(path.resolve(src, 'lib.rs'), (await LIBRS_TEMPLATE)(ctx), { flag: 'wx' });
|
||||
await writeFile(path.resolve(native_, 'build.rs'), (await BUILDRS_TEMPLATE)(ctx), { flag: 'wx' });
|
||||
writeFileSync(path.resolve(root, '.gitignore'), (await GITIGNORE_TEMPLATE)(ctx), { flag: 'wx' });
|
||||
writeFileSync(path.resolve(root, 'package.json'), (await NPM_TEMPLATE)(ctx), { flag: 'wx' });
|
||||
writeFileSync(path.resolve(native_, 'Cargo.toml'), (await CARGO_TEMPLATE)(ctx), { flag: 'wx' });
|
||||
writeFileSync(path.resolve(root, 'README.md'), (await README_TEMPLATE)(ctx), { flag: 'wx' });
|
||||
writeFileSync(path.resolve(root, answers.node), (await INDEXJS_TEMPLATE)(ctx), { flag: 'wx' });
|
||||
writeFileSync(path.resolve(src, 'lib.rs'), (await LIBRS_TEMPLATE)(ctx), { flag: 'wx' });
|
||||
writeFileSync(path.resolve(native_, 'build.rs'), (await BUILDRS_TEMPLATE)(ctx), { flag: 'wx' });
|
||||
|
||||
let relativeRoot = path.relative(pwd, root);
|
||||
let relativeNode = path.relative(pwd, path.resolve(root, answers.node));
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import * as path from 'path';
|
||||
import path from 'path';
|
||||
import Crate from './crate';
|
||||
import Target from './target';
|
||||
import BuildSettings from './build-settings';
|
||||
@ -38,7 +38,7 @@ export default class Project {
|
||||
});
|
||||
}
|
||||
|
||||
async build(toolchain: rust.Toolchain, release: boolean) {
|
||||
async build(toolchain: rust.Toolchain, release: boolean, args: string[]) {
|
||||
let target = new Target(this.crate, { release: release });
|
||||
let settings = BuildSettings.current(toolchain);
|
||||
|
||||
@ -50,7 +50,7 @@ export default class Project {
|
||||
|
||||
// 2. Build the dylib.
|
||||
log("running cargo");
|
||||
await target.build(toolchain, settings);
|
||||
await target.build(toolchain, settings, args);
|
||||
|
||||
// 3. Copy the dylib as the main addon file.
|
||||
log("generating " + path.join(this.crate.subdirectory, this.crate.nodefile));
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import * as async from './async/child_process';
|
||||
import * as child_process from 'child_process';
|
||||
import * as childProcess from 'child_process';
|
||||
|
||||
export type Toolchain = 'default' | 'stable' | 'nightly' | 'beta';
|
||||
|
||||
@ -10,15 +10,15 @@ function toolchainPrefix(toolchain: Toolchain = 'default') {
|
||||
export function spawnSync(tool: string,
|
||||
args: string[],
|
||||
toolchain: Toolchain = 'default',
|
||||
options?: child_process.SpawnOptions)
|
||||
options?: childProcess.SpawnOptions)
|
||||
{
|
||||
return child_process.spawnSync(tool, toolchainPrefix(toolchain).concat(args), options);
|
||||
return childProcess.spawnSync(tool, toolchainPrefix(toolchain).concat(args), options);
|
||||
}
|
||||
|
||||
export function spawn(tool: string,
|
||||
args: string[],
|
||||
toolchain: Toolchain = 'default',
|
||||
options?: child_process.SpawnOptions)
|
||||
options?: childProcess.SpawnOptions)
|
||||
{
|
||||
return async.spawn(tool, toolchainPrefix(toolchain).concat(args), options);
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import * as chalk from 'chalk';
|
||||
import chalk from 'chalk';
|
||||
|
||||
export let project = chalk.cyan.bold;
|
||||
export let command = chalk.green.bold;
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
import { remove } from './async/fs';
|
||||
import * as rust from './rust';
|
||||
import * as path from 'path';
|
||||
import Dict from 'ts-dict';
|
||||
import path from 'path';
|
||||
import Crate from './crate';
|
||||
import BuildSettings from './build-settings';
|
||||
import { rimraf } from './async/rimraf';
|
||||
|
||||
const LIB_PREFIX: Dict<string> = {
|
||||
const LIB_PREFIX: Record<string, string> = {
|
||||
'darwin': "lib",
|
||||
'freebsd': "lib",
|
||||
'linux': "lib",
|
||||
@ -13,7 +12,7 @@ const LIB_PREFIX: Dict<string> = {
|
||||
'win32': ""
|
||||
};
|
||||
|
||||
const LIB_SUFFIX: Dict<string> = {
|
||||
const LIB_SUFFIX: Record<string, string> = {
|
||||
'darwin': ".dylib",
|
||||
'freebsd': ".so",
|
||||
'linux': ".so",
|
||||
@ -62,7 +61,8 @@ export default class Target {
|
||||
|
||||
async clean() {
|
||||
// Remove the directory associated with this target.
|
||||
await remove(path.resolve(this.crate.root, 'target', this.subdirectory));
|
||||
const absolutePathSubdir = path.resolve(this.crate.root, 'target', this.subdirectory);
|
||||
await rimraf(absolutePathSubdir);
|
||||
|
||||
// If this target was the active target, remove the addon.
|
||||
if (this.crate.artifacts.haveActivated(this.subdirectory)) {
|
||||
@ -75,12 +75,13 @@ export default class Target {
|
||||
}
|
||||
|
||||
async build(toolchain: rust.Toolchain,
|
||||
settings: BuildSettings)
|
||||
settings: BuildSettings,
|
||||
additionalArgs: string[])
|
||||
{
|
||||
let releaseFlags = this.release ? ["--release"] : [];
|
||||
let targetFlags = this.triple ? ["--target=" + this.triple] : [];
|
||||
|
||||
let args = ['build'].concat(releaseFlags, targetFlags);
|
||||
let args = ['build'].concat(releaseFlags, targetFlags, additionalArgs);
|
||||
|
||||
try {
|
||||
let result = await rust.spawn("cargo", args, toolchain, {
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"target": "es6",
|
||||
"lib": [
|
||||
"es5", "es2015.core"
|
||||
"es6",
|
||||
"es7"
|
||||
],
|
||||
"allowJs": false,
|
||||
|
||||
@ -12,6 +13,7 @@
|
||||
|
||||
"declaration": true,
|
||||
|
||||
"esModuleInterop": true,
|
||||
"noImplicitAny": true,
|
||||
"suppressImplicitAnyIndexErrors": true,
|
||||
"strictNullChecks": true,
|
||||
|
||||
@ -1,15 +1,12 @@
|
||||
[package]
|
||||
name = "neon-build"
|
||||
version = "0.4.0"
|
||||
version = "0.8.2"
|
||||
authors = ["Dave Herman <david.herman@gmail.com>"]
|
||||
description = "Build logic required for Neon projects."
|
||||
repository = "https://github.com/neon-bindings/neon"
|
||||
license = "MIT/Apache-2.0"
|
||||
edition = "2018"
|
||||
build = "build.rs"
|
||||
|
||||
[dependencies]
|
||||
neon-sys = { version = "=0.4.0", path = "../neon-sys", optional = true }
|
||||
cfg-if = "0.1.9"
|
||||
|
||||
[build-dependencies]
|
||||
cfg-if = "0.1.9"
|
||||
neon-sys = { version = "=0.8.2", path = "../neon-sys", optional = true }
|
||||
|
||||
@ -1,28 +1,22 @@
|
||||
extern crate cfg_if;
|
||||
#[cfg(all(windows, feature = "neon-sys"))]
|
||||
fn main() {
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(all(windows, feature = "neon-sys"))] {
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
|
||||
// Extract linker metadata from neon-sys and save it in a text file.
|
||||
// The neon-build lib.rs will textually include them into constants.
|
||||
fn save(var: &str, filename: &str) {
|
||||
let path = Path::new(&env::var("OUT_DIR").unwrap()).join(filename);
|
||||
let mut buffer = File::create(path).unwrap();
|
||||
write!(buffer, "{}", env::var(var).unwrap()).unwrap();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
save("DEP_NEON_NODE_ROOT_DIR", "node_root_dir");
|
||||
save("DEP_NEON_NODE_ARCH", "node_arch");
|
||||
save("DEP_NEON_NODE_LIB_FILE", "node_lib_file");
|
||||
}
|
||||
} else {
|
||||
fn main() { }
|
||||
// Extract linker metadata from neon-sys and save it in a text file.
|
||||
// The neon-build lib.rs will textually include them into constants.
|
||||
fn save(var: &str, filename: &str) {
|
||||
let path = Path::new(&env::var("OUT_DIR").unwrap()).join(filename);
|
||||
let mut buffer = File::create(path).unwrap();
|
||||
write!(buffer, "{}", env::var(var).unwrap()).unwrap();
|
||||
}
|
||||
|
||||
save("DEP_NEON_NODE_ROOT_DIR", "node_root_dir");
|
||||
save("DEP_NEON_NODE_ARCH", "node_arch");
|
||||
save("DEP_NEON_NODE_LIB_FILE", "node_lib_file");
|
||||
}
|
||||
|
||||
#[cfg(any(not(windows), not(feature = "neon-sys")))]
|
||||
fn main() {}
|
||||
|
||||
1
crates/neon-build/src/legacy/linux.rs
Normal file
1
crates/neon-build/src/legacy/linux.rs
Normal file
@ -0,0 +1 @@
|
||||
pub(crate) fn setup() {}
|
||||
4
crates/neon-build/src/legacy/macos.rs
Normal file
4
crates/neon-build/src/legacy/macos.rs
Normal file
@ -0,0 +1,4 @@
|
||||
pub(crate) fn setup() {
|
||||
println!("cargo:rustc-cdylib-link-arg=-undefined");
|
||||
println!("cargo:rustc-cdylib-link-arg=dynamic_lookup");
|
||||
}
|
||||
14
crates/neon-build/src/legacy/mod.rs
Normal file
14
crates/neon-build/src/legacy/mod.rs
Normal file
@ -0,0 +1,14 @@
|
||||
#[cfg(all(not(windows), not(target_os = "macos")))]
|
||||
mod linux;
|
||||
#[cfg(all(not(windows), not(target_os = "macos")))]
|
||||
pub(crate) use linux::*;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
mod macos;
|
||||
#[cfg(target_os = "macos")]
|
||||
pub(crate) use macos::*;
|
||||
|
||||
#[cfg(windows)]
|
||||
mod windows;
|
||||
#[cfg(windows)]
|
||||
pub(crate) use windows::*;
|
||||
36
crates/neon-build/src/legacy/windows.rs
Normal file
36
crates/neon-build/src/legacy/windows.rs
Normal file
@ -0,0 +1,36 @@
|
||||
use std::env::var;
|
||||
use std::path::Path;
|
||||
|
||||
const NODE_ROOT_DIR: &'static str = include_str!(concat!(env!("OUT_DIR"), "\\node_root_dir"));
|
||||
const NODE_ARCH: &'static str = include_str!(concat!(env!("OUT_DIR"), "\\node_arch"));
|
||||
const NODE_LIB_FILE: &'static str = include_str!(concat!(env!("OUT_DIR"), "\\node_lib_file"));
|
||||
|
||||
/// Set up the build environment by setting Cargo configuration variables.
|
||||
pub(crate) fn setup() {
|
||||
let debug = var("DEBUG").ok().map_or(false, |s| s == "true");
|
||||
let configuration = if debug { "Debug" } else { "Release" };
|
||||
let node_lib_file_path = Path::new(NODE_LIB_FILE);
|
||||
let mut node_lib_path = Path::new(NODE_ROOT_DIR).to_path_buf();
|
||||
node_lib_path.push(NODE_ARCH);
|
||||
println!(
|
||||
"cargo:rustc-link-search={}\\{}",
|
||||
NODE_ROOT_DIR, configuration
|
||||
);
|
||||
println!(
|
||||
"cargo:rustc-link-search=native={}",
|
||||
&node_lib_path.display()
|
||||
);
|
||||
println!(
|
||||
"cargo:rustc-link-lib={}",
|
||||
&node_lib_file_path.file_stem().unwrap().to_str().unwrap()
|
||||
);
|
||||
|
||||
// Link `win_delay_load_hook.obj` for windows electron
|
||||
let node_runtime_env = "npm_config_runtime";
|
||||
println!("cargo:rerun-if-env-changed={}", node_runtime_env);
|
||||
if var(node_runtime_env).map(|s| s == "electron") == Ok(true) {
|
||||
println!("cargo:rustc-cdylib-link-arg=win_delay_load_hook.obj");
|
||||
println!("cargo:rustc-cdylib-link-arg=delayimp.lib");
|
||||
println!("cargo:rustc-cdylib-link-arg=/DELAYLOAD:node.exe");
|
||||
}
|
||||
}
|
||||
@ -1,43 +1,32 @@
|
||||
extern crate cfg_if;
|
||||
#[cfg(feature = "neon-sys")]
|
||||
mod legacy;
|
||||
#[cfg(not(feature = "neon-sys"))]
|
||||
mod napi;
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
#[cfg(not(feature = "neon-sys"))]
|
||||
pub use napi::Setup;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(all(windows, feature = "neon-sys"))] {
|
||||
use std::env::var;
|
||||
use std::path::Path;
|
||||
|
||||
const NODE_ROOT_DIR: &'static str = include_str!(concat!(env!("OUT_DIR"), "\\node_root_dir"));
|
||||
const NODE_ARCH: &'static str = include_str!(concat!(env!("OUT_DIR"), "\\node_arch"));
|
||||
const NODE_LIB_FILE: &'static str = include_str!(concat!(env!("OUT_DIR"), "\\node_lib_file"));
|
||||
|
||||
/// Set up the build environment by setting Cargo configuration variables.
|
||||
pub fn setup() {
|
||||
let debug = var("DEBUG").ok().map_or(false, |s| s == "true");
|
||||
let configuration = if debug { "Debug" } else { "Release" };
|
||||
let node_lib_file_path = Path::new(NODE_LIB_FILE);
|
||||
let mut node_lib_path = Path::new(NODE_ROOT_DIR).to_path_buf();
|
||||
node_lib_path.push(NODE_ARCH);
|
||||
println!("cargo:rustc-link-search={}\\{}", NODE_ROOT_DIR, configuration);
|
||||
println!("cargo:rustc-link-search=native={}", &node_lib_path.display());
|
||||
println!("cargo:rustc-link-lib={}", &node_lib_file_path.file_stem().unwrap().to_str().unwrap());
|
||||
|
||||
// Link `win_delay_load_hook.obj` for windows electron
|
||||
let node_runtime_env = "npm_config_runtime";
|
||||
println!("cargo:rerun-if-env-changed={}", node_runtime_env);
|
||||
if var(node_runtime_env).map(|s| s == "electron") == Ok(true) {
|
||||
println!("cargo:rustc-cdylib-link-arg=win_delay_load_hook.obj");
|
||||
println!("cargo:rustc-cdylib-link-arg=delayimp.lib");
|
||||
println!("cargo:rustc-cdylib-link-arg=/DELAYLOAD:node.exe");
|
||||
}
|
||||
}
|
||||
} else if #[cfg(target_os = "macos")] {
|
||||
/// Set up the build environment by setting Cargo configuration variables.
|
||||
pub fn setup() {
|
||||
println!("cargo:rustc-cdylib-link-arg=-undefined");
|
||||
println!("cargo:rustc-cdylib-link-arg=dynamic_lookup");
|
||||
}
|
||||
} else {
|
||||
pub fn setup() { }
|
||||
}
|
||||
/// Custom build scripts for [Neon][neon] modules.
|
||||
/// Must be called from `main.rs` in a Cargo [build script][build-script].
|
||||
///
|
||||
/// ```toml
|
||||
/// [package]
|
||||
/// build = "build.rs"
|
||||
/// ```
|
||||
///
|
||||
/// ```rust
|
||||
/// // build.rs
|
||||
/// # #[allow(clippy::needless_doctest_main)]
|
||||
/// fn main() {
|
||||
/// neon_build::setup();
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [neon]: https://docs.rs/neon
|
||||
/// [build-script]: https://doc.rust-lang.org/cargo/reference/build-scripts.html
|
||||
pub fn setup() {
|
||||
#[cfg(feature = "neon-sys")]
|
||||
legacy::setup();
|
||||
#[cfg(not(feature = "neon-sys"))]
|
||||
napi::setup();
|
||||
}
|
||||
|
||||
171
crates/neon-build/src/napi/mod.rs
Normal file
171
crates/neon-build/src/napi/mod.rs
Normal file
@ -0,0 +1,171 @@
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
fn manifest_dir() -> PathBuf {
|
||||
std::env::var_os("CARGO_MANIFEST_DIR")
|
||||
.map(PathBuf::from)
|
||||
.expect("Expected CARGO_MANIFEST_DIR environment variable")
|
||||
}
|
||||
|
||||
fn out_dir() -> PathBuf {
|
||||
std::env::var_os("OUT_DIR")
|
||||
.map(PathBuf::from)
|
||||
.expect("Expected OUT_DIR environment variable")
|
||||
}
|
||||
|
||||
fn is_env(env_var: &str, value: &str) -> bool {
|
||||
std::env::var_os(env_var)
|
||||
.map(|v| v == value)
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
fn setup_unix(output_file: PathBuf) {
|
||||
println!("cargo:rustc-cdylib-link-arg=-o");
|
||||
println!("cargo:rustc-cdylib-link-arg={}", output_file.display());
|
||||
}
|
||||
|
||||
fn setup_windows(output_file: PathBuf) {
|
||||
let pdb_file = output_file
|
||||
.file_name()
|
||||
.map(|file| out_dir().join(Path::new(file).with_extension("pdb")))
|
||||
.expect("Expected a neon output file name");
|
||||
|
||||
println!("cargo:rustc-cdylib-link-arg=/OUT:{}", output_file.display());
|
||||
println!("cargo:rustc-cdylib-link-arg=/PDB:{}", pdb_file.display());
|
||||
}
|
||||
|
||||
/// `Setup` acts as a builder for initializing a Neon build script
|
||||
///
|
||||
/// A default setup builder is provided as [`neon_build::setup()`](crate::setup()).
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// Output the neon module at `lib/native.node`
|
||||
///
|
||||
/// ```
|
||||
/// # #[allow(clippy::needless_doctest_main)]
|
||||
/// fn main() {
|
||||
/// neon_build::Setup::options()
|
||||
/// .output_dir("lib")
|
||||
/// .output_dir("native.node")
|
||||
/// .setup();
|
||||
/// }
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Setup {
|
||||
output_dir: Option<PathBuf>,
|
||||
output_file: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl Setup {
|
||||
/// Create a new builder for Setup options
|
||||
pub fn options() -> Self {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
/// Sets the output directory for the native library.
|
||||
/// Defaults to the cargo manifest directory. If not absolute, paths will
|
||||
/// be relative to the cargo manifest directory.
|
||||
pub fn output_dir(&mut self, output_dir: impl AsRef<Path>) -> &mut Self {
|
||||
self.output_dir = Some(output_dir.as_ref().to_path_buf());
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the name of the native library. Defaults to `index.node`. If not
|
||||
/// absolute, paths will be relative to the [`Setup::output_dir`].
|
||||
///
|
||||
/// **Note**: Node.js requires that native libraries have the `.node`
|
||||
/// extension to be loaded by `require`.
|
||||
pub fn output_file(&mut self, output_file: impl AsRef<Path>) -> &mut Self {
|
||||
self.output_file = Some(output_file.as_ref().to_path_buf());
|
||||
self
|
||||
}
|
||||
|
||||
/// Setup the Cargo build process for Neon. Should be called once from
|
||||
/// `fn main` in a cargo build script.
|
||||
pub fn setup(&self) {
|
||||
let output_file = self.absolute_output_file();
|
||||
let is_windows = is_env("CARGO_CFG_TARGET_OS", "windows");
|
||||
let is_gnu = is_env("CARGO_CFG_TARGET_ENV", "gnu");
|
||||
|
||||
if is_windows && !is_gnu {
|
||||
setup_windows(output_file);
|
||||
} else {
|
||||
setup_unix(output_file);
|
||||
}
|
||||
}
|
||||
|
||||
fn absolute_output_file(&self) -> PathBuf {
|
||||
let output_file = self
|
||||
.output_file
|
||||
.clone()
|
||||
.unwrap_or_else(|| PathBuf::from("index.node"));
|
||||
|
||||
// Don't prepend `output_dir` if `output_file` is absolute
|
||||
if output_file.is_absolute() {
|
||||
return output_file;
|
||||
}
|
||||
|
||||
let output_dir = if let Some(output_dir) = self.output_dir.clone() {
|
||||
// If `output_dir` is absolute, use it, otherwise
|
||||
// append it to `manifest_dir()`
|
||||
if output_dir.is_absolute() {
|
||||
output_dir
|
||||
} else {
|
||||
manifest_dir().join(output_dir)
|
||||
}
|
||||
} else {
|
||||
// Default to `manifest_dir()`
|
||||
manifest_dir()
|
||||
};
|
||||
|
||||
output_dir.join(output_file)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn setup() {
|
||||
Setup::options().setup()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_absolute_output_file_defaults() {
|
||||
let expected = manifest_dir().join("index.node");
|
||||
let actual = Setup::options().absolute_output_file();
|
||||
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_absolute_output_file_absolute_file() {
|
||||
let expected = PathBuf::from("/tmp/hello.node");
|
||||
let actual = Setup::options()
|
||||
.output_dir("/tmp/ignore/me")
|
||||
.output_file("/tmp/hello.node")
|
||||
.absolute_output_file();
|
||||
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_absolute_output_file_absolute_dir() {
|
||||
let expected = PathBuf::from("/tmp/index.node");
|
||||
let actual = Setup::options().output_dir("/tmp").absolute_output_file();
|
||||
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_absolute_output_file_relative_dir() {
|
||||
let expected = manifest_dir().join("lib").join("index.node");
|
||||
let actual = Setup::options().output_dir("lib").absolute_output_file();
|
||||
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_absolute_output_file_relative_file() {
|
||||
let expected = manifest_dir().join("lib.node");
|
||||
let actual = Setup::options()
|
||||
.output_file("lib.node")
|
||||
.absolute_output_file();
|
||||
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
18
crates/neon-macros/Cargo.toml
Normal file
18
crates/neon-macros/Cargo.toml
Normal file
@ -0,0 +1,18 @@
|
||||
[package]
|
||||
name = "neon-macros"
|
||||
version = "0.8.2"
|
||||
authors = ["Dave Herman <david.herman@gmail.com>"]
|
||||
description = "Procedural macros supporting Neon"
|
||||
repository = "https://github.com/neon-bindings/neon"
|
||||
license = "MIT/Apache-2.0"
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[features]
|
||||
napi = []
|
||||
|
||||
[dependencies]
|
||||
quote = "1"
|
||||
syn = { version = "1", features = ["full"] }
|
||||
201
crates/neon-macros/LICENSE-APACHE
Normal file
201
crates/neon-macros/LICENSE-APACHE
Normal file
@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
19
crates/neon-macros/LICENSE-MIT
Normal file
19
crates/neon-macros/LICENSE-MIT
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2015 David Herman
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
81
crates/neon-macros/src/legacy.rs
Normal file
81
crates/neon-macros/src/legacy.rs
Normal file
@ -0,0 +1,81 @@
|
||||
pub(crate) fn main(
|
||||
_attr: proc_macro::TokenStream,
|
||||
item: proc_macro::TokenStream,
|
||||
) -> proc_macro::TokenStream {
|
||||
let input = syn::parse_macro_input!(item as syn::ItemFn);
|
||||
|
||||
let attrs = &input.attrs;
|
||||
let vis = &input.vis;
|
||||
let sig = &input.sig;
|
||||
let block = &input.block;
|
||||
let name = &sig.ident;
|
||||
|
||||
quote::quote!(
|
||||
#(#attrs) *
|
||||
#vis #sig {
|
||||
// Mark this function as a global constructor (like C++).
|
||||
#[allow(improper_ctypes)]
|
||||
#[cfg_attr(target_os = "linux", link_section = ".ctors")]
|
||||
#[cfg_attr(target_os = "android", link_section = ".ctors")]
|
||||
#[cfg_attr(target_os = "macos", link_section = "__DATA,__mod_init_func")]
|
||||
#[cfg_attr(target_os = "ios", link_section = "__DATA,__mod_init_func")]
|
||||
#[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")]
|
||||
#[used]
|
||||
static __LOAD_NEON_MODULE: extern "C" fn() = {
|
||||
extern "C" fn __load_neon_module() {
|
||||
// Put everything else in the ctor fn so the user fn can't see it.
|
||||
#[repr(C)]
|
||||
struct __NodeModule {
|
||||
version: i32,
|
||||
flags: u32,
|
||||
dso_handle: *mut u8,
|
||||
filename: *const u8,
|
||||
register_func: Option<extern "C" fn(
|
||||
::neon::handle::Handle<::neon::types::JsObject>, *mut u8, *mut u8)>,
|
||||
context_register_func: Option<extern "C" fn(
|
||||
::neon::handle::Handle<::neon::types::JsObject>, *mut u8, *mut u8, *mut u8)>,
|
||||
modname: *const u8,
|
||||
priv_data: *mut u8,
|
||||
link: *mut __NodeModule
|
||||
}
|
||||
|
||||
// Mark as used during tests to suppress warnings
|
||||
#[cfg_attr(test, used)]
|
||||
static mut __NODE_MODULE: __NodeModule = __NodeModule {
|
||||
version: 0,
|
||||
flags: 0,
|
||||
dso_handle: 0 as *mut _,
|
||||
filename: b"neon_source.rs\0" as *const u8,
|
||||
register_func: Some(__register_neon_module),
|
||||
context_register_func: None,
|
||||
modname: b"neon_module\0" as *const u8,
|
||||
priv_data: 0 as *mut _,
|
||||
link: 0 as *mut _
|
||||
};
|
||||
|
||||
extern "C" fn __register_neon_module(
|
||||
m: ::neon::handle::Handle<::neon::types::JsObject>, _: *mut u8, _: *mut u8) {
|
||||
::neon::macro_internal::initialize_module(m, #name);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn node_module_register(module: *mut __NodeModule);
|
||||
}
|
||||
|
||||
// During tests, node is not available. Skip module registration.
|
||||
#[cfg(not(test))]
|
||||
unsafe {
|
||||
// Set the ABI version based on the NODE_MODULE_VERSION constant provided by the current node headers.
|
||||
__NODE_MODULE.version = ::neon::macro_internal::runtime::module::get_version();
|
||||
node_module_register(&mut __NODE_MODULE);
|
||||
}
|
||||
}
|
||||
|
||||
__load_neon_module
|
||||
};
|
||||
|
||||
#block
|
||||
}
|
||||
)
|
||||
.into()
|
||||
}
|
||||
44
crates/neon-macros/src/lib.rs
Normal file
44
crates/neon-macros/src/lib.rs
Normal file
@ -0,0 +1,44 @@
|
||||
//! Procedural macros supporting [Neon](https://docs.rs/neon/latest/neon/)
|
||||
|
||||
#[cfg(feature = "napi")]
|
||||
mod napi;
|
||||
#[cfg(feature = "napi")]
|
||||
use napi as macros;
|
||||
|
||||
#[cfg(not(feature = "napi"))]
|
||||
mod legacy;
|
||||
#[cfg(not(feature = "napi"))]
|
||||
use legacy as macros;
|
||||
|
||||
// Proc macro definitions must be in the root of the crate
|
||||
// Implementations are in the backend dependent module
|
||||
|
||||
#[proc_macro_attribute]
|
||||
/// Marks a function as the main entry point for initialization in
|
||||
/// a Neon module.
|
||||
///
|
||||
/// This attribute should only be used _once_ in a module and will
|
||||
/// be called each time the module is initialized in a context.
|
||||
///
|
||||
/// ```ignore
|
||||
/// #[neon::main]
|
||||
/// fn main(mut cx: ModuleContext) -> NeonResult<()> {
|
||||
/// let version = cx.string("1.0.0");
|
||||
///
|
||||
/// cx.export_value("version", version)?;
|
||||
///
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// If multiple functions are marked with `#[neon::main]`, there may be a compile error:
|
||||
///
|
||||
/// ```sh
|
||||
/// error: symbol `napi_register_module_v1` is already defined
|
||||
/// ```
|
||||
pub fn main(
|
||||
attr: proc_macro::TokenStream,
|
||||
item: proc_macro::TokenStream,
|
||||
) -> proc_macro::TokenStream {
|
||||
macros::main(attr, item)
|
||||
}
|
||||
34
crates/neon-macros/src/napi.rs
Normal file
34
crates/neon-macros/src/napi.rs
Normal file
@ -0,0 +1,34 @@
|
||||
pub(crate) fn main(
|
||||
_attr: proc_macro::TokenStream,
|
||||
item: proc_macro::TokenStream,
|
||||
) -> proc_macro::TokenStream {
|
||||
let input = syn::parse_macro_input!(item as syn::ItemFn);
|
||||
|
||||
let attrs = &input.attrs;
|
||||
let vis = &input.vis;
|
||||
let sig = &input.sig;
|
||||
let block = &input.block;
|
||||
let name = &sig.ident;
|
||||
|
||||
quote::quote!(
|
||||
#(#attrs) *
|
||||
#vis #sig {
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn napi_register_module_v1(
|
||||
env: ::neon::macro_internal::runtime::raw::Env,
|
||||
m: ::neon::macro_internal::runtime::raw::Local,
|
||||
) -> ::neon::macro_internal::runtime::raw::Local {
|
||||
::neon::macro_internal::initialize_module(
|
||||
env,
|
||||
::std::mem::transmute(m),
|
||||
#name,
|
||||
);
|
||||
|
||||
m
|
||||
}
|
||||
|
||||
#block
|
||||
}
|
||||
)
|
||||
.into()
|
||||
}
|
||||
@ -1,18 +1,30 @@
|
||||
[package]
|
||||
name = "neon-runtime"
|
||||
version = "0.4.0"
|
||||
version = "0.8.2"
|
||||
authors = ["Dave Herman <david.herman@gmail.com>"]
|
||||
description = "Bindings to the Node.js native addon API, used by the Neon implementation."
|
||||
repository = "https://github.com/neon-bindings/neon"
|
||||
license = "MIT/Apache-2.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
cfg-if = "0.1.9"
|
||||
neon-sys = { version = "=0.4.0", path = "../neon-sys", optional = true }
|
||||
nodejs-sys = { version = "0.2.0", optional = true }
|
||||
cfg-if = "1.0.0"
|
||||
libloading = { version = "0.6.5", optional = true }
|
||||
neon-sys = { version = "=0.8.2", path = "../neon-sys", optional = true }
|
||||
smallvec = "1.4.2"
|
||||
|
||||
[dev-dependencies]
|
||||
nodejs-sys = "0.7.0" # Not strictly needed; just here for easy manual copying
|
||||
|
||||
[features]
|
||||
default = []
|
||||
napi = ["libloading"]
|
||||
napi-2 = ["napi"]
|
||||
napi-3 = ["napi-2"]
|
||||
napi-4 = ["napi-3"]
|
||||
napi-5 = ["napi-4"]
|
||||
napi-6 = ["napi-5"]
|
||||
napi-experimental = ["napi-6"]
|
||||
docs-only = ["neon-sys/docs-only"]
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
|
||||
@ -1,25 +1,23 @@
|
||||
extern crate cfg_if;
|
||||
|
||||
#[cfg(all(not(feature = "neon-sys"), not(feature = "nodejs-sys")))]
|
||||
compile_error!("The Neon runtime must have at least one of the `neon-sys` or `nodejs-sys` backends enabled.");
|
||||
#[cfg(all(not(feature = "neon-sys"), not(feature = "napi")))]
|
||||
compile_error!(
|
||||
"The Neon runtime must have at least one of the `neon-sys` or `napi` backends enabled."
|
||||
);
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "nodejs-sys")] {
|
||||
pub extern crate nodejs_sys;
|
||||
if #[cfg(feature = "napi")] {
|
||||
pub mod napi;
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "neon-sys")] {
|
||||
extern crate neon_sys;
|
||||
pub mod nan;
|
||||
// The legacy variant is the default API as long as it's present.
|
||||
pub use nan::*;
|
||||
} else if #[cfg(feature = "nodejs-sys")] {
|
||||
pub use crate::nan::*;
|
||||
} else if #[cfg(feature = "napi")] {
|
||||
// The N-API variant is only the default API if the legacy variant is disabled.
|
||||
pub use napi::*;
|
||||
pub use crate::napi::*;
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,7 +18,7 @@ pub use neon_sys::Neon_Call_IsConstruct as is_construct;
|
||||
/// the function is bound to.
|
||||
pub use neon_sys::Neon_Call_This as this;
|
||||
|
||||
/// Mutates the `out` argument provided to refer to the `v8::Local` handle value of the
|
||||
/// Mutates the `out` argument provided to refer to the pointer value of the
|
||||
/// `v8::FunctionCallbackInfo` `Data`.
|
||||
pub use neon_sys::Neon_Call_Data as data;
|
||||
|
||||
|
||||
@ -1,16 +1,28 @@
|
||||
//! Facilities for creating and throwing JS errors.
|
||||
|
||||
use crate::raw::{Isolate, Local};
|
||||
|
||||
/// Throws an `Error` object in the current context.
|
||||
pub use neon_sys::Neon_Error_Throw as throw;
|
||||
pub unsafe fn throw(_: Isolate, val: Local) {
|
||||
neon_sys::Neon_Error_Throw(val)
|
||||
}
|
||||
|
||||
/// Mutates the `out` argument provided to refer to a newly created `Error` object.
|
||||
pub use neon_sys::Neon_Error_NewError as new_error;
|
||||
pub unsafe fn new_error(_: Isolate, out: &mut Local, msg: Local) {
|
||||
neon_sys::Neon_Error_NewError(out, msg)
|
||||
}
|
||||
|
||||
/// Mutates the `out` argument provided to refer to a newly created `TypeError` object.
|
||||
pub use neon_sys::Neon_Error_NewTypeError as new_type_error;
|
||||
pub unsafe fn new_type_error(_: Isolate, out: &mut Local, msg: Local) {
|
||||
neon_sys::Neon_Error_NewTypeError(out, msg)
|
||||
}
|
||||
|
||||
/// Mutates the `out` argument provided to refer to a newly created `RangeError` object.
|
||||
pub use neon_sys::Neon_Error_NewRangeError as new_range_error;
|
||||
pub unsafe fn new_range_error(_: Isolate, out: &mut Local, msg: Local) {
|
||||
neon_sys::Neon_Error_NewRangeError(out, msg)
|
||||
}
|
||||
|
||||
/// Throws an `Error` object in the current context.
|
||||
pub use neon_sys::Neon_Error_ThrowErrorFromUtf8 as throw_error_from_utf8;
|
||||
pub unsafe fn throw_error_from_utf8(_: Isolate, msg: *const u8, len: i32) {
|
||||
neon_sys::Neon_Error_ThrowErrorFromUtf8(msg, len)
|
||||
}
|
||||
|
||||
@ -1,18 +1,19 @@
|
||||
pub mod raw;
|
||||
pub mod call;
|
||||
pub mod scope;
|
||||
pub mod object;
|
||||
pub mod array;
|
||||
pub mod string;
|
||||
pub mod primitive;
|
||||
pub mod error;
|
||||
pub mod arraybuffer;
|
||||
pub mod buffer;
|
||||
pub mod tag;
|
||||
pub mod module;
|
||||
pub mod mem;
|
||||
pub mod fun;
|
||||
pub mod convert;
|
||||
pub mod call;
|
||||
pub mod class;
|
||||
pub mod task;
|
||||
pub mod convert;
|
||||
pub mod error;
|
||||
pub mod fun;
|
||||
pub mod handler;
|
||||
pub mod mem;
|
||||
pub mod module;
|
||||
pub mod object;
|
||||
pub mod primitive;
|
||||
pub mod raw;
|
||||
pub mod scope;
|
||||
pub mod string;
|
||||
pub mod tag;
|
||||
pub mod task;
|
||||
pub mod try_catch;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
//! Fundamental definitions for mapping to the V8 memory space.
|
||||
|
||||
pub use neon_sys::{Local, FunctionCallbackInfo, Isolate, HandleScope, EscapableHandleScope, InheritedHandleScope};
|
||||
pub use neon_sys::{
|
||||
EscapableHandleScope, FunctionCallbackInfo, HandleScope, InheritedHandleScope, Isolate, Local,
|
||||
};
|
||||
|
||||
@ -1,15 +1,23 @@
|
||||
//! Facilities for working with `v8::HandleScope`s and `v8::EscapableHandleScope`s.
|
||||
|
||||
use raw::{HandleScope, EscapableHandleScope, InheritedHandleScope, Isolate};
|
||||
use crate::raw::{EscapableHandleScope, HandleScope, InheritedHandleScope, Isolate};
|
||||
|
||||
pub trait Root {
|
||||
/// # Safety
|
||||
/// Allocates an uninitialized scope. See `enter` and `exit`.
|
||||
unsafe fn allocate() -> Self;
|
||||
unsafe fn enter(&mut self, Isolate);
|
||||
unsafe fn exit(&mut self, Isolate);
|
||||
/// # Safety
|
||||
/// Must be called exactly once after creating a `Root` and before usage
|
||||
unsafe fn enter(&mut self, _: Isolate);
|
||||
/// # Safety
|
||||
/// Must be called exactly once, if and only if `enter` succeeds
|
||||
unsafe fn exit(&mut self, _: Isolate);
|
||||
}
|
||||
|
||||
impl Root for HandleScope {
|
||||
unsafe fn allocate() -> Self { HandleScope::new() }
|
||||
unsafe fn allocate() -> Self {
|
||||
HandleScope::new()
|
||||
}
|
||||
unsafe fn enter(&mut self, isolate: Isolate) {
|
||||
enter(self, isolate)
|
||||
}
|
||||
@ -19,7 +27,9 @@ impl Root for HandleScope {
|
||||
}
|
||||
|
||||
impl Root for EscapableHandleScope {
|
||||
unsafe fn allocate() -> Self { EscapableHandleScope::new() }
|
||||
unsafe fn allocate() -> Self {
|
||||
EscapableHandleScope::new()
|
||||
}
|
||||
unsafe fn enter(&mut self, isolate: Isolate) {
|
||||
enter_escapable(self, isolate)
|
||||
}
|
||||
@ -29,9 +39,11 @@ impl Root for EscapableHandleScope {
|
||||
}
|
||||
|
||||
impl Root for InheritedHandleScope {
|
||||
unsafe fn allocate() -> Self { InheritedHandleScope }
|
||||
unsafe fn enter(&mut self, _: Isolate) { }
|
||||
unsafe fn exit(&mut self, _: Isolate) { }
|
||||
unsafe fn allocate() -> Self {
|
||||
InheritedHandleScope
|
||||
}
|
||||
unsafe fn enter(&mut self, _: Isolate) {}
|
||||
unsafe fn exit(&mut self, _: Isolate) {}
|
||||
}
|
||||
|
||||
/// Mutates the `out` argument provided to refer to the newly escaped `v8::Local` value.
|
||||
|
||||
4
crates/neon-runtime/src/nan/try_catch.rs
Normal file
4
crates/neon-runtime/src/nan/try_catch.rs
Normal file
@ -0,0 +1,4 @@
|
||||
/// Wraps a computation with an RAII-allocated Nan::TryCatch.
|
||||
pub use neon_sys::Neon_TryCatch_With as with;
|
||||
|
||||
pub use neon_sys::TryCatchControl;
|
||||
@ -1,18 +1,26 @@
|
||||
//! Facilities for working with Array `napi_value`s.
|
||||
|
||||
use raw::{Local, Env};
|
||||
use crate::raw::{Env, Local};
|
||||
|
||||
use nodejs_sys as napi;
|
||||
use crate::napi::bindings as napi;
|
||||
|
||||
pub unsafe extern "C" fn new(_out: &mut Local, _env: Env, _length: u32) { unimplemented!() }
|
||||
pub unsafe fn new(out: &mut Local, env: Env, length: u32) {
|
||||
assert_eq!(
|
||||
napi::create_array_with_length(env, length as usize, out as *mut _),
|
||||
napi::Status::Ok,
|
||||
);
|
||||
}
|
||||
|
||||
/// Gets the length of a `napi_value` containing a JavaScript Array.
|
||||
///
|
||||
/// # Panics
|
||||
/// This function panics if `array` is not an Array, or if a previous n-api call caused a pending
|
||||
/// exception.
|
||||
pub unsafe extern "C" fn len(env: Env, array: Local) -> u32 {
|
||||
pub unsafe fn len(env: Env, array: Local) -> u32 {
|
||||
let mut len = 0;
|
||||
assert_eq!(napi::napi_get_array_length(env, array, &mut len as *mut _), napi::napi_status::napi_ok);
|
||||
assert_eq!(
|
||||
napi::get_array_length(env, array, &mut len as *mut _),
|
||||
napi::Status::Ok
|
||||
);
|
||||
len
|
||||
}
|
||||
|
||||
@ -1,6 +1,50 @@
|
||||
use raw::Local;
|
||||
use crate::raw::{Env, Local};
|
||||
use std::mem::MaybeUninit;
|
||||
use std::os::raw::c_void;
|
||||
use std::ptr::null_mut;
|
||||
|
||||
pub unsafe extern "C" fn new(_out: &mut Local, _isolate: *mut c_void, _size: u32) -> bool { unimplemented!() }
|
||||
use crate::napi::bindings as napi;
|
||||
|
||||
pub unsafe extern "C" fn data<'a, 'b>(_base_out: &'a mut *mut c_void, _obj: Local) -> usize { unimplemented!() }
|
||||
pub unsafe fn new(out: &mut Local, env: Env, size: u32) -> bool {
|
||||
let status = napi::create_arraybuffer(env, size as usize, null_mut(), out as *mut _);
|
||||
|
||||
status == napi::Status::Ok
|
||||
}
|
||||
|
||||
pub unsafe fn data(env: Env, base_out: &mut *mut c_void, obj: Local) -> usize {
|
||||
let mut size = 0;
|
||||
assert_eq!(
|
||||
napi::get_arraybuffer_info(env, obj, base_out as *mut _, &mut size as *mut _),
|
||||
napi::Status::Ok,
|
||||
);
|
||||
size
|
||||
}
|
||||
|
||||
pub unsafe fn new_external<T>(env: Env, data: T) -> Local
|
||||
where
|
||||
T: AsMut<[u8]> + Send,
|
||||
{
|
||||
// Safety: Boxing could move the data; must box before grabbing a raw pointer
|
||||
let mut data = Box::new(data);
|
||||
let buf = data.as_mut().as_mut();
|
||||
let length = buf.len();
|
||||
let mut result = MaybeUninit::uninit();
|
||||
|
||||
assert_eq!(
|
||||
napi::create_external_arraybuffer(
|
||||
env,
|
||||
buf.as_mut_ptr() as *mut _,
|
||||
length,
|
||||
Some(drop_external::<T>),
|
||||
Box::into_raw(data) as *mut _,
|
||||
result.as_mut_ptr(),
|
||||
),
|
||||
napi::Status::Ok,
|
||||
);
|
||||
|
||||
result.assume_init()
|
||||
}
|
||||
|
||||
unsafe extern "C" fn drop_external<T>(_env: Env, _data: *mut c_void, hint: *mut c_void) {
|
||||
Box::<T>::from_raw(hint as *mut _);
|
||||
}
|
||||
|
||||
327
crates/neon-runtime/src/napi/bindings/functions.rs
Normal file
327
crates/neon-runtime/src/napi/bindings/functions.rs
Normal file
@ -0,0 +1,327 @@
|
||||
#![allow(clippy::too_many_arguments)]
|
||||
|
||||
mod napi1 {
|
||||
use super::super::types::*;
|
||||
use std::os::raw::{c_char, c_void};
|
||||
|
||||
generate!(
|
||||
extern "C" {
|
||||
fn get_undefined(env: Env, result: *mut Value) -> Status;
|
||||
|
||||
fn get_null(env: Env, result: *mut Value) -> Status;
|
||||
|
||||
fn get_global(env: Env, result: *mut Value) -> Status;
|
||||
|
||||
fn get_boolean(env: Env, value: bool, result: *mut Value) -> Status;
|
||||
|
||||
fn create_double(env: Env, value: f64, result: *mut Value) -> Status;
|
||||
|
||||
fn create_object(env: Env, result: *mut Value) -> Status;
|
||||
|
||||
fn get_value_bool(env: Env, value: Value, result: *mut bool) -> Status;
|
||||
|
||||
fn get_value_double(env: Env, value: Value, result: *mut f64) -> Status;
|
||||
|
||||
fn create_array_with_length(env: Env, length: usize, result: *mut Value) -> Status;
|
||||
|
||||
fn get_array_length(env: Env, value: Value, result: *mut u32) -> Status;
|
||||
|
||||
fn get_new_target(env: Env, cbinfo: CallbackInfo, result: *mut Value) -> Status;
|
||||
|
||||
fn coerce_to_object(env: Env, value: Value, result: *mut Value) -> Status;
|
||||
|
||||
fn coerce_to_string(env: Env, value: Value, result: *mut Value) -> Status;
|
||||
|
||||
fn throw(env: Env, error: Value) -> Status;
|
||||
|
||||
fn create_error(env: Env, code: Value, msg: Value, result: *mut Value) -> Status;
|
||||
|
||||
fn get_and_clear_last_exception(env: Env, result: *mut Value) -> Status;
|
||||
|
||||
fn is_exception_pending(env: Env, result: *mut bool) -> Status;
|
||||
|
||||
fn get_value_external(env: Env, value: Value, result: *mut *mut c_void) -> Status;
|
||||
|
||||
fn typeof_value(env: Env, value: Value, result: *mut ValueType) -> Status;
|
||||
|
||||
fn close_escapable_handle_scope(env: Env, scope: EscapableHandleScope) -> Status;
|
||||
|
||||
fn open_escapable_handle_scope(env: Env, result: *mut EscapableHandleScope) -> Status;
|
||||
|
||||
fn open_handle_scope(env: Env, result: *mut HandleScope) -> Status;
|
||||
|
||||
fn close_handle_scope(env: Env, scope: HandleScope) -> Status;
|
||||
|
||||
fn is_arraybuffer(env: Env, value: Value, result: *mut bool) -> Status;
|
||||
fn is_buffer(env: Env, value: Value, result: *mut bool) -> Status;
|
||||
fn is_error(env: Env, value: Value, result: *mut bool) -> Status;
|
||||
fn is_array(env: Env, value: Value, result: *mut bool) -> Status;
|
||||
|
||||
fn get_value_string_utf8(
|
||||
env: Env,
|
||||
value: Value,
|
||||
buf: *mut c_char,
|
||||
bufsize: usize,
|
||||
result: *mut usize,
|
||||
) -> Status;
|
||||
|
||||
fn create_type_error(env: Env, code: Value, msg: Value, result: *mut Value) -> Status;
|
||||
|
||||
fn create_range_error(env: Env, code: Value, msg: Value, result: *mut Value) -> Status;
|
||||
|
||||
fn create_string_utf8(
|
||||
env: Env,
|
||||
str: *const c_char,
|
||||
length: usize,
|
||||
result: *mut Value,
|
||||
) -> Status;
|
||||
|
||||
fn create_arraybuffer(
|
||||
env: Env,
|
||||
byte_length: usize,
|
||||
data: *mut *mut c_void,
|
||||
result: *mut Value,
|
||||
) -> Status;
|
||||
|
||||
fn get_arraybuffer_info(
|
||||
env: Env,
|
||||
arraybuffer: Value,
|
||||
data: *mut *mut c_void,
|
||||
byte_length: *mut usize,
|
||||
) -> Status;
|
||||
|
||||
fn create_buffer(
|
||||
env: Env,
|
||||
length: usize,
|
||||
data: *mut *mut c_void,
|
||||
result: *mut Value,
|
||||
) -> Status;
|
||||
|
||||
fn get_buffer_info(
|
||||
env: Env,
|
||||
value: Value,
|
||||
data: *mut *mut c_void,
|
||||
length: *mut usize,
|
||||
) -> Status;
|
||||
|
||||
fn get_cb_info(
|
||||
env: Env,
|
||||
cbinfo: CallbackInfo,
|
||||
argc: *mut usize,
|
||||
argv: *mut Value,
|
||||
this_arg: *mut Value,
|
||||
data: *mut *mut c_void,
|
||||
) -> Status;
|
||||
|
||||
fn create_external(
|
||||
env: Env,
|
||||
data: *mut c_void,
|
||||
finalize_cb: Finalize,
|
||||
finalize_hint: *mut c_void,
|
||||
result: *mut Value,
|
||||
) -> Status;
|
||||
|
||||
fn new_instance(
|
||||
env: Env,
|
||||
constructor: Value,
|
||||
argc: usize,
|
||||
argv: *const Value,
|
||||
result: *mut Value,
|
||||
) -> Status;
|
||||
|
||||
fn call_function(
|
||||
env: Env,
|
||||
recv: Value,
|
||||
func: Value,
|
||||
argc: usize,
|
||||
argv: *const Value,
|
||||
result: *mut Value,
|
||||
) -> Status;
|
||||
|
||||
fn create_function(
|
||||
env: Env,
|
||||
utf8name: *const c_char,
|
||||
length: usize,
|
||||
cb: Callback,
|
||||
data: *mut c_void,
|
||||
result: *mut Value,
|
||||
) -> Status;
|
||||
|
||||
fn set_property(env: Env, object: Value, key: Value, value: Value) -> Status;
|
||||
|
||||
fn get_property(env: Env, object: Value, key: Value, result: *mut Value) -> Status;
|
||||
|
||||
fn set_element(env: Env, object: Value, index: u32, value: Value) -> Status;
|
||||
|
||||
fn get_element(env: Env, object: Value, index: u32, result: *mut Value) -> Status;
|
||||
|
||||
fn escape_handle(
|
||||
env: Env,
|
||||
scope: EscapableHandleScope,
|
||||
escapee: Value,
|
||||
result: *mut Value,
|
||||
) -> Status;
|
||||
|
||||
fn create_reference(
|
||||
env: Env,
|
||||
value: Value,
|
||||
initial_ref_count: u32,
|
||||
result: *mut Ref,
|
||||
) -> Status;
|
||||
|
||||
fn reference_ref(env: Env, reference: Ref, result: *mut u32) -> Status;
|
||||
|
||||
fn reference_unref(env: Env, reference: Ref, result: *mut u32) -> Status;
|
||||
|
||||
fn get_reference_value(env: Env, reference: Ref, result: *mut Value) -> Status;
|
||||
|
||||
fn strict_equals(env: Env, lhs: Value, rhs: Value, result: *mut bool) -> Status;
|
||||
|
||||
fn create_external_arraybuffer(
|
||||
env: Env,
|
||||
data: *mut c_void,
|
||||
length: usize,
|
||||
finalize_cb: Finalize,
|
||||
finalize_hint: *mut c_void,
|
||||
result: *mut Value,
|
||||
) -> Status;
|
||||
|
||||
fn create_external_buffer(
|
||||
env: Env,
|
||||
length: usize,
|
||||
data: *mut c_void,
|
||||
finalize_cb: Finalize,
|
||||
finalize_hint: *mut c_void,
|
||||
result: *mut Value,
|
||||
) -> Status;
|
||||
|
||||
fn run_script(env: Env, script: Value, result: *mut Value) -> Status;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "napi-4")]
|
||||
mod napi4 {
|
||||
use super::super::types::*;
|
||||
use std::os::raw::c_void;
|
||||
|
||||
generate!(
|
||||
extern "C" {
|
||||
fn create_threadsafe_function(
|
||||
env: Env,
|
||||
func: Value,
|
||||
async_resource: Value,
|
||||
async_resource_name: Value,
|
||||
max_queue_size: usize,
|
||||
initial_thread_count: usize,
|
||||
thread_finalize_data: *mut c_void,
|
||||
thread_finalize_cb: Finalize,
|
||||
context: *mut c_void,
|
||||
call_js_cb: ThreadsafeFunctionCallJs,
|
||||
result: *mut ThreadsafeFunction,
|
||||
) -> Status;
|
||||
|
||||
fn call_threadsafe_function(
|
||||
func: ThreadsafeFunction,
|
||||
data: *mut c_void,
|
||||
is_blocking: ThreadsafeFunctionCallMode,
|
||||
) -> Status;
|
||||
|
||||
fn release_threadsafe_function(
|
||||
func: ThreadsafeFunction,
|
||||
mode: ThreadsafeFunctionReleaseMode,
|
||||
) -> Status;
|
||||
|
||||
fn ref_threadsafe_function(env: Env, func: ThreadsafeFunction) -> Status;
|
||||
|
||||
fn unref_threadsafe_function(env: Env, func: ThreadsafeFunction) -> Status;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "napi-5")]
|
||||
mod napi5 {
|
||||
use super::super::types::*;
|
||||
|
||||
generate!(
|
||||
extern "C" {
|
||||
fn create_date(env: Env, value: f64, result: *mut Value) -> Status;
|
||||
|
||||
fn get_date_value(env: Env, value: Value, result: *mut f64) -> Status;
|
||||
|
||||
fn is_date(env: Env, value: Value, result: *mut bool) -> Status;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "napi-6")]
|
||||
mod napi6 {
|
||||
use super::super::types::*;
|
||||
use std::os::raw::c_void;
|
||||
|
||||
generate!(
|
||||
extern "C" {
|
||||
fn get_all_property_names(
|
||||
env: Env,
|
||||
object: Value,
|
||||
key_mode: KeyCollectionMode,
|
||||
key_filter: KeyFilter,
|
||||
key_conversion: KeyConversion,
|
||||
result: *mut Value,
|
||||
) -> Status;
|
||||
|
||||
fn set_instance_data(
|
||||
env: Env,
|
||||
data: *mut c_void,
|
||||
finalize_cb: Finalize,
|
||||
finalize_hint: *mut c_void,
|
||||
) -> Status;
|
||||
|
||||
fn get_instance_data(env: Env, data: *mut *mut c_void) -> Status;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
pub(crate) use napi1::*;
|
||||
#[cfg(feature = "napi-4")]
|
||||
pub(crate) use napi4::*;
|
||||
#[cfg(feature = "napi-5")]
|
||||
pub(crate) use napi5::*;
|
||||
#[cfg(feature = "napi-6")]
|
||||
pub(crate) use napi6::*;
|
||||
|
||||
use super::{Env, Status};
|
||||
|
||||
// This symbol is loaded separately because it is a prerequisite
|
||||
unsafe fn get_version(host: &libloading::Library, env: Env) -> Result<u32, libloading::Error> {
|
||||
let get_version = host.get::<fn(Env, *mut u32) -> Status>(b"napi_get_version")?;
|
||||
let mut version = 0;
|
||||
|
||||
assert_eq!(get_version(env, &mut version as *mut _), Status::Ok,);
|
||||
|
||||
Ok(version)
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn load(env: Env) -> Result<(), libloading::Error> {
|
||||
#[cfg(not(windows))]
|
||||
let host = libloading::os::unix::Library::this().into();
|
||||
#[cfg(windows)]
|
||||
let host = libloading::os::windows::Library::this()?.into();
|
||||
|
||||
// This never fail since `get_version` is in N-API Version 1 and the module will fail
|
||||
// with `Error: Module did not self-register` if N-API does not exist.
|
||||
let version = get_version(&host, env).expect("Failed to find N-API version");
|
||||
|
||||
napi1::load(&host, version, 1)?;
|
||||
|
||||
#[cfg(feature = "napi-4")]
|
||||
napi4::load(&host, version, 4)?;
|
||||
|
||||
#[cfg(feature = "napi-5")]
|
||||
napi5::load(&host, version, 5)?;
|
||||
|
||||
#[cfg(feature = "napi-6")]
|
||||
napi6::load(&host, version, 6)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
185
crates/neon-runtime/src/napi/bindings/mod.rs
Normal file
185
crates/neon-runtime/src/napi/bindings/mod.rs
Normal file
@ -0,0 +1,185 @@
|
||||
//! # FFI bindings to N-API symbols
|
||||
//!
|
||||
//! These types are manually copied from bindings generated from `bindgen`. To
|
||||
//! update, use the following approach:
|
||||
//!
|
||||
//! * Run `cargo test --manifest-path=crates/neon-runtime/Cargo.toml --features napi`
|
||||
//! at least once to install `nodejs-sys`
|
||||
//! * Open the generated bindings at `target/release/build/nodejs-sys-*/out/bindings.rs`
|
||||
//! * Copy the types needed into `types.rs` and `functions.rs`
|
||||
//! * Modify to match Rust naming conventions:
|
||||
//! - Remove `napi_` prefixes
|
||||
//! - Use `PascalCase` for types
|
||||
//! - Rename types that match a reserved word
|
||||
|
||||
/// Constructs the name of a N-API symbol as a string from a function identifier
|
||||
/// E.g., `get_undefined` becomes `"napi_get_undefined"`
|
||||
macro_rules! napi_name {
|
||||
// Explicitly replace identifiers that have been renamed from the N-API
|
||||
// symbol because they would match a reserved word.
|
||||
(typeof_value) => {
|
||||
"napi_typeof"
|
||||
};
|
||||
// Default case: Stringify the identifier and prefix with `napi_`
|
||||
($name:ident) => {
|
||||
concat!("napi_", stringify!($name))
|
||||
};
|
||||
}
|
||||
|
||||
/// Generate dynamic bindings to N-API symbols from definitions in an
|
||||
/// block `extern "C"`.
|
||||
///
|
||||
/// * A single global mutable struct holds references to the N-API functions
|
||||
/// * The global `Napi` struct is initialized with stubs that panic if called
|
||||
/// * A `load` function is generated that loads the N-API symbols from the
|
||||
/// host process and replaces the global struct with real implementations
|
||||
/// * `load` should be called exactly once before using any N-API functions
|
||||
/// * Wrapper functions are generated to delegate to fields in the `Napi` struct
|
||||
///
|
||||
/// Sample input:
|
||||
///
|
||||
/// ```
|
||||
/// extern "C" {
|
||||
/// fn get_undefined(env: Env, result: *mut Value) -> Status;
|
||||
/// /* Additional functions may be included */
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Generated output:
|
||||
///
|
||||
/// ```
|
||||
/// // Each field is a pointer to a N-API function
|
||||
/// pub(crate) struct Napi {
|
||||
/// get_undefined: unsafe extern "C" fn(env: Env, result: *mut Value) -> Status,
|
||||
/// /* ... repeat for each N-API function */
|
||||
/// }
|
||||
///
|
||||
/// // Defines a panic function that is called if symbols have not been loaded
|
||||
/// #[inline(never)]
|
||||
/// fn panic_load<T>() -> T {
|
||||
/// panic!("Must load N-API bindings")
|
||||
/// }
|
||||
///
|
||||
/// // Mutable global instance of the Napi struct
|
||||
/// // Initialized with stubs of N-API methods that panic
|
||||
/// static mut NAPI: Napi = {
|
||||
/// // Stubs are defined in a block to prevent naming conflicts with wrappers
|
||||
/// unsafe extern "C" fn get_undefined(_: Env, _: *mut Value) -> Status {
|
||||
/// panic_load()
|
||||
/// }
|
||||
/// /* ... repeat for each N-API function */
|
||||
///
|
||||
/// Napi {
|
||||
/// get_undefined,
|
||||
/// /* ... repeat for each N-API function */
|
||||
/// }
|
||||
/// };
|
||||
///
|
||||
/// // Load N-API symbols from the host process
|
||||
/// // # Safety: Must only be called once
|
||||
/// pub(crate) unsafe fn load(
|
||||
/// host: &libloading::Library,
|
||||
/// actual_napi_version: u32,
|
||||
/// expected_napi_version: u32,
|
||||
/// ) -> Result<(), libloading::Error> {
|
||||
/// assert!(
|
||||
/// actual_napi_version >= expected_napi_version,
|
||||
/// "Minimum required N-API version {}, found {}.",
|
||||
/// expected_napi_version,
|
||||
/// actual_napi_version,
|
||||
/// );
|
||||
///
|
||||
/// NAPI = Napi {
|
||||
/// // Load each N-API symbol
|
||||
/// get_undefined: *host.get("napi_get_undefined".as_bytes())?,
|
||||
/// /* ... repeat for each N-API function */
|
||||
/// };
|
||||
///
|
||||
/// Ok(())
|
||||
/// }
|
||||
///
|
||||
/// // Each N-API function has wrapper for easy calling. These calls are optimized
|
||||
/// // to a single pointer dereference.
|
||||
/// #[inline]
|
||||
/// pub(crate) unsafe fn get_undefined(env: Env, result: *mut Value) -> Status {
|
||||
/// (NAPI.get_undefined)(env, result)
|
||||
/// }
|
||||
/// ```
|
||||
macro_rules! generate {
|
||||
(extern "C" {
|
||||
$(fn $name:ident($($param:ident: $ptype:ty$(,)?)*) -> $rtype:ty;)+
|
||||
}) => {
|
||||
pub(crate) struct Napi {
|
||||
$(
|
||||
$name: unsafe extern "C" fn(
|
||||
$($param: $ptype,)*
|
||||
) -> $rtype,
|
||||
)*
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn panic_load<T>() -> T {
|
||||
panic!("Must load N-API bindings")
|
||||
}
|
||||
|
||||
static mut NAPI: Napi = {
|
||||
$(
|
||||
unsafe extern "C" fn $name($(_: $ptype,)*) -> $rtype {
|
||||
panic_load()
|
||||
}
|
||||
)*
|
||||
|
||||
Napi {
|
||||
$(
|
||||
$name,
|
||||
)*
|
||||
}
|
||||
};
|
||||
|
||||
pub(crate) unsafe fn load(
|
||||
host: &libloading::Library,
|
||||
actual_napi_version: u32,
|
||||
expected_napi_version: u32,
|
||||
) -> Result<(), libloading::Error> {
|
||||
assert!(
|
||||
actual_napi_version >= expected_napi_version,
|
||||
"Minimum required N-API version {}, found {}.",
|
||||
expected_napi_version,
|
||||
actual_napi_version,
|
||||
);
|
||||
|
||||
NAPI = Napi {
|
||||
$(
|
||||
$name: *host.get(napi_name!($name).as_bytes())?,
|
||||
)*
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
$(
|
||||
#[inline]
|
||||
pub(crate) unsafe fn $name($($param: $ptype,)*) -> $rtype {
|
||||
(NAPI.$name)($($param,)*)
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
use std::sync::Once;
|
||||
|
||||
pub(crate) use functions::*;
|
||||
pub(crate) use types::*;
|
||||
|
||||
mod functions;
|
||||
mod types;
|
||||
|
||||
static SETUP: Once = Once::new();
|
||||
|
||||
/// Loads N-API symbols from host process.
|
||||
/// Must be called at least once before using any functions in `neon-runtime` or
|
||||
/// they will panic.
|
||||
/// Safety: `env` must be a valid `napi_env` for the current thread
|
||||
pub unsafe fn setup(env: Env) {
|
||||
SETUP.call_once(|| load(env).expect("Failed to load N-API symbols"));
|
||||
}
|
||||
188
crates/neon-runtime/src/napi/bindings/types.rs
Normal file
188
crates/neon-runtime/src/napi/bindings/types.rs
Normal file
@ -0,0 +1,188 @@
|
||||
use std::ffi::c_void;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Env__ {
|
||||
_unused: [u8; 0],
|
||||
}
|
||||
|
||||
pub type Env = *mut Env__;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Value__ {
|
||||
_unused: [u8; 0],
|
||||
}
|
||||
|
||||
pub type Value = *mut Value__;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct CallbackInfo__ {
|
||||
_unused: [u8; 0],
|
||||
}
|
||||
|
||||
pub type CallbackInfo = *mut CallbackInfo__;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct EscapableHandleScope__ {
|
||||
_unused: [u8; 0],
|
||||
}
|
||||
pub type EscapableHandleScope = *mut EscapableHandleScope__;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct HandleScope__ {
|
||||
_unused: [u8; 0],
|
||||
}
|
||||
|
||||
pub type HandleScope = *mut HandleScope__;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Ref__ {
|
||||
_unused: [u8; 0],
|
||||
}
|
||||
|
||||
pub type Ref = *mut Ref__;
|
||||
|
||||
#[cfg(feature = "napi-4")]
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct ThreadsafeFunction__ {
|
||||
_unused: [u8; 0],
|
||||
}
|
||||
|
||||
#[cfg(feature = "napi-4")]
|
||||
pub type ThreadsafeFunction = *mut ThreadsafeFunction__;
|
||||
|
||||
pub(crate) type Callback = Option<unsafe extern "C" fn(env: Env, info: CallbackInfo) -> Value>;
|
||||
|
||||
pub(crate) type Finalize =
|
||||
Option<unsafe extern "C" fn(env: Env, finalize_data: *mut c_void, finalize_hint: *mut c_void)>;
|
||||
|
||||
#[cfg(feature = "napi-4")]
|
||||
pub type ThreadsafeFunctionCallJs = Option<
|
||||
unsafe extern "C" fn(env: Env, js_callback: Value, context: *mut c_void, data: *mut c_void),
|
||||
>;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[repr(u32)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum Status {
|
||||
Ok = 0,
|
||||
InvalidArg = 1,
|
||||
ObjectExpected = 2,
|
||||
StringExpected = 3,
|
||||
NameExpected = 4,
|
||||
FunctionExpected = 5,
|
||||
NumberExpected = 6,
|
||||
BooleanExpected = 7,
|
||||
ArrayExpected = 8,
|
||||
GenericFailure = 9,
|
||||
PendingException = 10,
|
||||
Cancelled = 11,
|
||||
EscapeCalledTwice = 12,
|
||||
HandleScopeMismatch = 13,
|
||||
CallbackScopeMismatch = 14,
|
||||
QueueFull = 15,
|
||||
Closing = 16,
|
||||
BigintExpected = 17,
|
||||
DateExpected = 18,
|
||||
ArraybufferExpected = 19,
|
||||
DetachableArraybufferExpected = 20,
|
||||
WouldDeadlock = 21,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[repr(u32)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub(crate) enum ValueType {
|
||||
Undefined = 0,
|
||||
Null = 1,
|
||||
Boolean = 2,
|
||||
Number = 3,
|
||||
String = 4,
|
||||
Symbol = 5,
|
||||
Object = 6,
|
||||
Function = 7,
|
||||
External = 8,
|
||||
BigInt = 9,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[repr(u32)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum KeyCollectionMode {
|
||||
IncludePrototypes = 0,
|
||||
OwnOnly = 1,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[repr(u32)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum KeyConversion {
|
||||
KeepNumbers = 0,
|
||||
NumbersToStrings = 1,
|
||||
}
|
||||
|
||||
#[cfg(feature = "napi-4")]
|
||||
#[repr(u32)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum ThreadsafeFunctionCallMode {
|
||||
NonBlocking = 0,
|
||||
Blocking = 1,
|
||||
}
|
||||
|
||||
#[cfg(feature = "napi-4")]
|
||||
#[allow(dead_code)]
|
||||
#[repr(u32)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum ThreadsafeFunctionReleaseMode {
|
||||
Release = 0,
|
||||
Abort = 1,
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub(crate) struct KeyFilter(pub ::std::os::raw::c_uint);
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl KeyFilter {
|
||||
pub(crate) const ALL_PROPERTIES: KeyFilter = KeyFilter(0);
|
||||
pub(crate) const WRITABLE: KeyFilter = KeyFilter(1);
|
||||
pub(crate) const CONFIGURABLE: KeyFilter = KeyFilter(4);
|
||||
pub(crate) const SKIP_STRINGS: KeyFilter = KeyFilter(8);
|
||||
pub(crate) const SKIP_SYMBOLS: KeyFilter = KeyFilter(16);
|
||||
}
|
||||
|
||||
impl std::ops::BitOr<KeyFilter> for KeyFilter {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn bitor(self, other: Self) -> Self {
|
||||
KeyFilter(self.0 | other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::BitOrAssign for KeyFilter {
|
||||
#[inline]
|
||||
fn bitor_assign(&mut self, rhs: KeyFilter) {
|
||||
self.0 |= rhs.0;
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::BitAnd<KeyFilter> for KeyFilter {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn bitand(self, other: Self) -> Self {
|
||||
KeyFilter(self.0 & other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::BitAndAssign for KeyFilter {
|
||||
#[inline]
|
||||
fn bitand_assign(&mut self, rhs: KeyFilter) {
|
||||
self.0 &= rhs.0;
|
||||
}
|
||||
}
|
||||
@ -1,8 +1,63 @@
|
||||
use raw::Local;
|
||||
use crate::raw::{Env, Local};
|
||||
use std::mem::MaybeUninit;
|
||||
use std::os::raw::c_void;
|
||||
use std::ptr::null_mut;
|
||||
|
||||
pub unsafe extern "C" fn new(_out: &mut Local, _size: u32) -> bool { unimplemented!() }
|
||||
use crate::napi::bindings as napi;
|
||||
|
||||
pub unsafe extern "C" fn uninitialized(_out: &mut Local, _size: u32) -> bool { unimplemented!() }
|
||||
pub unsafe fn new(env: Env, out: &mut Local, size: u32) -> bool {
|
||||
let mut bytes = null_mut();
|
||||
let status = napi::create_buffer(env, size as usize, &mut bytes as *mut _, out as *mut _);
|
||||
if status == napi::Status::Ok {
|
||||
// zero-initialize it. If performance is critical, JsBuffer::uninitialized can be used
|
||||
// instead.
|
||||
std::ptr::write_bytes(bytes, 0, size as usize);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn data<'a, 'b>(_base_out: &'a mut *mut c_void, _obj: Local) -> usize { unimplemented!() }
|
||||
pub unsafe fn uninitialized(env: Env, out: &mut Local, size: u32) -> bool {
|
||||
let mut bytes = null_mut();
|
||||
let status = napi::create_buffer(env, size as usize, &mut bytes as *mut _, out as *mut _);
|
||||
status == napi::Status::Ok
|
||||
}
|
||||
|
||||
pub unsafe fn new_external<T>(env: Env, data: T) -> Local
|
||||
where
|
||||
T: AsMut<[u8]> + Send,
|
||||
{
|
||||
// Safety: Boxing could move the data; must box before grabbing a raw pointer
|
||||
let mut data = Box::new(data);
|
||||
let buf = data.as_mut().as_mut();
|
||||
let length = buf.len();
|
||||
let mut result = MaybeUninit::uninit();
|
||||
|
||||
assert_eq!(
|
||||
napi::create_external_buffer(
|
||||
env,
|
||||
length,
|
||||
buf.as_mut_ptr() as *mut _,
|
||||
Some(drop_external::<T>),
|
||||
Box::into_raw(data) as *mut _,
|
||||
result.as_mut_ptr(),
|
||||
),
|
||||
napi::Status::Ok,
|
||||
);
|
||||
|
||||
result.assume_init()
|
||||
}
|
||||
|
||||
pub unsafe fn data(env: Env, base_out: &mut *mut c_void, obj: Local) -> usize {
|
||||
let mut size = 0;
|
||||
assert_eq!(
|
||||
napi::get_buffer_info(env, obj, base_out as *mut _, &mut size as *mut _),
|
||||
napi::Status::Ok,
|
||||
);
|
||||
size
|
||||
}
|
||||
|
||||
unsafe extern "C" fn drop_external<T>(_env: Env, _data: *mut c_void, hint: *mut c_void) {
|
||||
Box::<T>::from_raw(hint as *mut _);
|
||||
}
|
||||
|
||||
@ -1,35 +1,93 @@
|
||||
use std::mem::MaybeUninit;
|
||||
use std::os::raw::c_void;
|
||||
use std::ptr::null_mut;
|
||||
use raw::{FunctionCallbackInfo, Env, Local};
|
||||
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
|
||||
use crate::napi::bindings as napi;
|
||||
use crate::raw::{Env, FunctionCallbackInfo, Local};
|
||||
|
||||
#[repr(C)]
|
||||
pub struct CCallback {
|
||||
pub static_callback: *mut c_void,
|
||||
pub dynamic_callback: *mut c_void
|
||||
pub dynamic_callback: *mut c_void,
|
||||
}
|
||||
|
||||
impl Default for CCallback {
|
||||
fn default() -> Self {
|
||||
CCallback {
|
||||
static_callback: null_mut(),
|
||||
dynamic_callback: null_mut()
|
||||
dynamic_callback: null_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn set_return(_info: &FunctionCallbackInfo, _value: Local) { unimplemented!() }
|
||||
pub unsafe fn is_construct(env: Env, info: FunctionCallbackInfo) -> bool {
|
||||
let mut target: MaybeUninit<Local> = MaybeUninit::zeroed();
|
||||
|
||||
pub unsafe extern "C" fn get_isolate(_info: &FunctionCallbackInfo) -> Env { unimplemented!() }
|
||||
let status = napi::get_new_target(env, info, target.as_mut_ptr());
|
||||
|
||||
// FIXME: Remove. This will never be implemented
|
||||
pub unsafe extern "C" fn current_isolate() -> Env { panic!("current_isolate won't be implemented in n-api") }
|
||||
assert_eq!(status, napi::Status::Ok);
|
||||
|
||||
pub unsafe extern "C" fn is_construct(_info: &FunctionCallbackInfo) -> bool { unimplemented!() }
|
||||
// get_new_target is guaranteed to assign to target, so it's initialized.
|
||||
let target: Local = target.assume_init();
|
||||
|
||||
pub unsafe extern "C" fn this(_info: &FunctionCallbackInfo, _out: &mut Local) { unimplemented!() }
|
||||
// By the get_new_target contract, target will either be NULL if the current
|
||||
// function was called without `new`, or a valid napi_value handle if the current
|
||||
// function was called with `new`.
|
||||
!target.is_null()
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn data(_info: &FunctionCallbackInfo, _out: &mut Local) { unimplemented!() }
|
||||
pub unsafe fn this(env: Env, info: FunctionCallbackInfo, out: &mut Local) {
|
||||
let status = napi::get_cb_info(env, info, null_mut(), null_mut(), out as *mut _, null_mut());
|
||||
assert_eq!(status, napi::Status::Ok);
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn len(_info: &FunctionCallbackInfo) -> i32 { unimplemented!() }
|
||||
/// Mutates the `out` argument provided to refer to the associated data value of the
|
||||
/// `napi_callback_info`.
|
||||
pub unsafe fn data(env: Env, info: FunctionCallbackInfo, out: &mut *mut c_void) {
|
||||
let mut data = null_mut();
|
||||
let status = napi::get_cb_info(
|
||||
env,
|
||||
info,
|
||||
null_mut(),
|
||||
null_mut(),
|
||||
null_mut(),
|
||||
&mut data as *mut _,
|
||||
);
|
||||
if status == napi::Status::Ok {
|
||||
*out = data;
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn get(_info: &FunctionCallbackInfo, _i: i32, _out: &mut Local) { unimplemented!() }
|
||||
/// Gets the number of arguments passed to the function.
|
||||
pub unsafe fn len(env: Env, info: FunctionCallbackInfo) -> i32 {
|
||||
let mut argc = 0usize;
|
||||
let status = napi::get_cb_info(
|
||||
env,
|
||||
info,
|
||||
&mut argc as *mut _,
|
||||
null_mut(),
|
||||
null_mut(),
|
||||
null_mut(),
|
||||
);
|
||||
assert_eq!(status, napi::Status::Ok);
|
||||
argc as i32
|
||||
}
|
||||
|
||||
/// Returns the function arguments as a `SmallVec<[Local; 8]>`
|
||||
pub unsafe fn argv(env: Env, info: FunctionCallbackInfo) -> SmallVec<[Local; 8]> {
|
||||
let len = len(env, info);
|
||||
let mut args = smallvec![null_mut(); len as usize];
|
||||
let mut num_args = args.len();
|
||||
let status = napi::get_cb_info(
|
||||
env,
|
||||
info,
|
||||
&mut num_args as *mut _,
|
||||
args.as_mut_ptr(),
|
||||
null_mut(),
|
||||
null_mut(),
|
||||
);
|
||||
assert_eq!(status, napi::Status::Ok);
|
||||
args
|
||||
}
|
||||
|
||||
@ -1,39 +0,0 @@
|
||||
use std::os::raw::c_void;
|
||||
use call::CCallback;
|
||||
use raw::{Env, Local};
|
||||
|
||||
pub unsafe extern "C" fn get_class_map(_isolate: Env) -> *mut c_void { unimplemented!() }
|
||||
|
||||
pub unsafe extern "C" fn set_class_map(_isolate: Env, _map: *mut c_void, _free_map: *mut c_void) { unimplemented!() }
|
||||
|
||||
pub unsafe extern "C" fn create_base(_isolate: Env,
|
||||
_allocate: CCallback,
|
||||
_construct: CCallback,
|
||||
_call: CCallback,
|
||||
_drop: extern "C" fn(*mut c_void)) -> *mut c_void { unimplemented!() }
|
||||
|
||||
pub unsafe extern "C" fn get_name<'a>(_base_out: &'a mut *mut u8, _isolate: Env, _metadata: *const c_void) -> usize { unimplemented!() }
|
||||
|
||||
pub unsafe extern "C" fn set_name(_isolate: Env, _metadata: *mut c_void, _name: *const u8, _byte_length: u32) -> bool { unimplemented!() }
|
||||
|
||||
pub unsafe extern "C" fn throw_call_error(_isolate: Env, _metadata: *mut c_void) { unimplemented!() }
|
||||
|
||||
pub unsafe extern "C" fn throw_this_error(_isolate: Env, _metadata: *mut c_void) { unimplemented!() }
|
||||
|
||||
pub unsafe extern "C" fn add_method(_isolate: Env, _metadata: *mut c_void, _name: *const u8, _byte_length: u32, _method: Local) -> bool { unimplemented!() }
|
||||
|
||||
pub unsafe extern "C" fn metadata_to_constructor(_out: &mut Local, _isolate: Env, _metadata: *mut c_void) -> bool { unimplemented!() }
|
||||
|
||||
// FIXME: get rid of all the "kernel" nomenclature
|
||||
|
||||
pub unsafe extern "C" fn get_allocate_kernel(_obj: Local) -> *mut c_void { unimplemented!() }
|
||||
|
||||
pub unsafe extern "C" fn get_construct_kernel(_obj: Local) -> *mut c_void { unimplemented!() }
|
||||
|
||||
pub unsafe extern "C" fn get_call_kernel(_obj: Local) -> *mut c_void { unimplemented!() }
|
||||
|
||||
pub unsafe extern "C" fn constructor(_out: &mut Local, _ft: Local) -> bool { unimplemented!() }
|
||||
|
||||
pub unsafe extern "C" fn has_instance(_metadata: *mut c_void, _v: Local) -> bool { unimplemented!() }
|
||||
|
||||
pub unsafe extern "C" fn get_instance_internals(_obj: Local) -> *mut c_void { unimplemented!() }
|
||||
@ -1,11 +1,15 @@
|
||||
use nodejs_sys as napi;
|
||||
use crate::napi::bindings as napi;
|
||||
use crate::raw::{Env, Local};
|
||||
|
||||
use raw::{Env, Local};
|
||||
/// This API is currently unused, see https://github.com/neon-bindings/neon/issues/572
|
||||
pub unsafe fn to_object(out: &mut Local, env: Env, value: Local) -> bool {
|
||||
let status = napi::coerce_to_object(env, value, out as *mut _);
|
||||
|
||||
pub unsafe extern "C" fn to_object(_out: &mut Local, _value: &Local) -> bool { unimplemented!() }
|
||||
|
||||
pub unsafe extern "C" fn to_string(out: &mut Local, env: Env, value: Local) -> bool {
|
||||
let status = napi::napi_coerce_to_string(env, value, out as *mut _);
|
||||
|
||||
status == napi::napi_status::napi_ok
|
||||
status == napi::Status::Ok
|
||||
}
|
||||
|
||||
pub unsafe fn to_string(out: &mut Local, env: Env, value: Local) -> bool {
|
||||
let status = napi::coerce_to_string(env, value, out as *mut _);
|
||||
|
||||
status == napi::Status::Ok
|
||||
}
|
||||
|
||||
28
crates/neon-runtime/src/napi/date.rs
Normal file
28
crates/neon-runtime/src/napi/date.rs
Normal file
@ -0,0 +1,28 @@
|
||||
use crate::napi::bindings as napi;
|
||||
use crate::raw::{Env, Local};
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
/// Create a new date object
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `env` is a raw pointer. Please ensure it points to a napi_env that is valid for the current context.
|
||||
pub unsafe fn new_date(env: Env, value: f64) -> Local {
|
||||
let mut local = MaybeUninit::zeroed();
|
||||
let status = napi::create_date(env, value, local.as_mut_ptr());
|
||||
assert_eq!(status, napi::Status::Ok);
|
||||
local.assume_init()
|
||||
}
|
||||
|
||||
/// Get the value of a date object
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `env` is a raw pointer. Please ensure it points to a napi_env that is valid for the current context.
|
||||
/// `Local` must be an NAPI value associated with the given `Env`
|
||||
pub unsafe fn value(env: Env, p: Local) -> f64 {
|
||||
let mut value = 0.0;
|
||||
let status = napi::get_date_value(env, p, &mut value as *mut _);
|
||||
assert_eq!(status, napi::Status::Ok);
|
||||
value
|
||||
}
|
||||
@ -1,11 +1,90 @@
|
||||
use raw::Local;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::ptr;
|
||||
|
||||
pub unsafe extern "C" fn throw(_val: Local) { unimplemented!() }
|
||||
use crate::napi::bindings as napi;
|
||||
use crate::raw::{Env, Local};
|
||||
|
||||
pub unsafe extern "C" fn new_error(_out: &mut Local, _msg: Local) { unimplemented!() }
|
||||
pub unsafe fn is_throwing(env: Env) -> bool {
|
||||
let mut b: MaybeUninit<bool> = MaybeUninit::zeroed();
|
||||
|
||||
pub unsafe extern "C" fn new_type_error(_out: &mut Local, _msg: Local) { unimplemented!() }
|
||||
let status = napi::is_exception_pending(env, b.as_mut_ptr());
|
||||
|
||||
pub unsafe extern "C" fn new_range_error(_out: &mut Local, _msg: Local) { unimplemented!() }
|
||||
assert_eq!(status, napi::Status::Ok);
|
||||
|
||||
pub unsafe extern "C" fn throw_error_from_utf8(_msg: *const u8, _len: i32) { unimplemented!() }
|
||||
b.assume_init()
|
||||
}
|
||||
|
||||
pub unsafe fn catch_error(env: Env, error: *mut Local) -> bool {
|
||||
if !is_throwing(env) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let status = napi::get_and_clear_last_exception(env, error);
|
||||
|
||||
assert_eq!(status, napi::Status::Ok);
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
pub unsafe fn clear_exception(env: Env) {
|
||||
let mut result = MaybeUninit::uninit();
|
||||
let status = napi::is_exception_pending(env, result.as_mut_ptr());
|
||||
|
||||
assert_eq!(status, napi::Status::Ok);
|
||||
|
||||
if !result.assume_init() {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut result = MaybeUninit::uninit();
|
||||
let status = napi::get_and_clear_last_exception(env, result.as_mut_ptr());
|
||||
|
||||
assert_eq!(status, napi::Status::Ok);
|
||||
}
|
||||
|
||||
pub unsafe fn throw(env: Env, val: Local) {
|
||||
let status = napi::throw(env, val);
|
||||
|
||||
assert_eq!(status, napi::Status::Ok);
|
||||
}
|
||||
|
||||
pub unsafe fn new_error(env: Env, out: &mut Local, msg: Local) {
|
||||
let mut result = MaybeUninit::uninit();
|
||||
let status = napi::create_error(env, ptr::null_mut(), msg, result.as_mut_ptr());
|
||||
|
||||
assert_eq!(status, napi::Status::Ok);
|
||||
|
||||
*out = result.assume_init();
|
||||
}
|
||||
|
||||
pub unsafe fn new_type_error(env: Env, out: &mut Local, msg: Local) {
|
||||
let mut result = MaybeUninit::uninit();
|
||||
let status = napi::create_type_error(env, ptr::null_mut(), msg, result.as_mut_ptr());
|
||||
|
||||
assert_eq!(status, napi::Status::Ok);
|
||||
|
||||
*out = result.assume_init();
|
||||
}
|
||||
|
||||
pub unsafe fn new_range_error(env: Env, out: &mut Local, msg: Local) {
|
||||
let mut result = MaybeUninit::uninit();
|
||||
let status = napi::create_range_error(env, ptr::null_mut(), msg, result.as_mut_ptr());
|
||||
|
||||
assert_eq!(status, napi::Status::Ok);
|
||||
|
||||
*out = result.assume_init();
|
||||
}
|
||||
|
||||
pub unsafe fn throw_error_from_utf8(env: Env, msg: *const u8, len: i32) {
|
||||
let mut out = MaybeUninit::uninit();
|
||||
let status = napi::create_string_utf8(env, msg as *const _, len as usize, out.as_mut_ptr());
|
||||
|
||||
assert_eq!(status, napi::Status::Ok);
|
||||
|
||||
let mut err = MaybeUninit::uninit();
|
||||
let status = napi::create_error(env, ptr::null_mut(), out.assume_init(), err.as_mut_ptr());
|
||||
|
||||
assert_eq!(status, napi::Status::Ok);
|
||||
|
||||
throw(env, err.assume_init());
|
||||
}
|
||||
|
||||
72
crates/neon-runtime/src/napi/external.rs
Normal file
72
crates/neon-runtime/src/napi/external.rs
Normal file
@ -0,0 +1,72 @@
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
use crate::napi::bindings as napi;
|
||||
use crate::raw::{Env, Local};
|
||||
|
||||
/// `finalize_external` is invoked immediately before a `napi_external` is garbage collected
|
||||
extern "C" fn finalize_external<T: Send + 'static>(
|
||||
env: Env,
|
||||
// Raw pointer to a `Box<T>` stored by a `napi_external`
|
||||
data: *mut std::ffi::c_void,
|
||||
// Pointer to a Rust `fn` stored in the `hint` parameter of a `napi_external` called
|
||||
// with the contents of `data` immediately before the value is garbage collected.
|
||||
hint: *mut std::ffi::c_void,
|
||||
) {
|
||||
unsafe {
|
||||
let data = Box::<T>::from_raw(data as *mut _);
|
||||
let finalizer: fn(Env, T) = std::mem::transmute(hint as *const ());
|
||||
|
||||
finalizer(env, *data);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a pointer to data stored in a `napi_external`
|
||||
/// Safety: `deref` must only be called with `napi_external` created by that
|
||||
/// module. Calling `deref` with an external created by another native module,
|
||||
/// even another neon module, is undefined behavior.
|
||||
/// https://github.com/neon-bindings/neon/issues/591
|
||||
pub unsafe fn deref<T: Send + 'static>(env: Env, local: Local) -> Option<*const T> {
|
||||
let mut result = MaybeUninit::uninit();
|
||||
let status = napi::typeof_value(env, local, result.as_mut_ptr());
|
||||
|
||||
assert_eq!(status, napi::Status::Ok);
|
||||
|
||||
let result = result.assume_init();
|
||||
|
||||
// Note: This only validates it is an external, not that it was created by
|
||||
// this module. In this future, this can be improved with type tagging:
|
||||
// https://nodejs.org/api/n-api.html#n_api_napi_type_tag
|
||||
// https://github.com/neon-bindings/neon/issues/591
|
||||
if result != napi::ValueType::External {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut result = MaybeUninit::uninit();
|
||||
let status = napi::get_value_external(env, local, result.as_mut_ptr());
|
||||
|
||||
assert_eq!(status, napi::Status::Ok);
|
||||
|
||||
Some(result.assume_init() as *const _)
|
||||
}
|
||||
|
||||
/// Creates a `napi_external` from a Rust type
|
||||
pub unsafe fn create<T: Send + 'static>(env: Env, v: T, finalizer: fn(Env, T)) -> Local {
|
||||
let v = Box::new(v);
|
||||
let mut result = MaybeUninit::uninit();
|
||||
|
||||
let status = napi::create_external(
|
||||
env,
|
||||
Box::into_raw(v) as *mut _,
|
||||
Some(finalize_external::<T>),
|
||||
// Casting to `*const ()` is required to ensure the correct layout
|
||||
// https://rust-lang.github.io/unsafe-code-guidelines/layout/function-pointers.html
|
||||
finalizer as *const () as *mut _,
|
||||
result.as_mut_ptr(),
|
||||
);
|
||||
|
||||
// `napi_create_external` will only fail if the VM is in a throwing state
|
||||
// or shutting down.
|
||||
assert_eq!(status, napi::Status::Ok);
|
||||
|
||||
result.assume_init()
|
||||
}
|
||||
@ -1,13 +1,59 @@
|
||||
//! Facilities for working with JS functions.
|
||||
|
||||
use std::os::raw::c_void;
|
||||
use call::CCallback;
|
||||
use raw::{Env, Local};
|
||||
use std::ptr::null;
|
||||
|
||||
pub unsafe extern "C" fn new(_out: &mut Local, _env: Env, _callback: CCallback) -> bool { unimplemented!() }
|
||||
use crate::call::CCallback;
|
||||
use crate::napi::bindings as napi;
|
||||
use crate::raw::{Env, Local};
|
||||
|
||||
pub unsafe extern "C" fn new_template(_out: &mut Local, _env: Env, _callback: CCallback) -> bool { unimplemented!() }
|
||||
/// Mutates the `out` argument provided to refer to a newly created `v8::Function`. Returns
|
||||
/// `false` if the value couldn't be created.
|
||||
pub unsafe fn new(out: &mut Local, env: Env, callback: CCallback) -> bool {
|
||||
let status = napi::create_function(
|
||||
env,
|
||||
null(),
|
||||
0,
|
||||
Some(std::mem::transmute(callback.static_callback)),
|
||||
callback.dynamic_callback,
|
||||
out as *mut Local,
|
||||
);
|
||||
|
||||
pub unsafe extern "C" fn get_dynamic_callback(_obj: Local) -> *mut c_void { unimplemented!() }
|
||||
status == napi::Status::Ok
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn call(_out: &mut Local, _env: Env, _fun: Local, _this: Local, _argc: i32, _argv: *mut c_void) -> bool { unimplemented!() }
|
||||
pub unsafe fn get_dynamic_callback(_env: Env, data: *mut c_void) -> *mut c_void {
|
||||
data
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn construct(_out: &mut Local, _env: Env, _fun: Local, _argc: i32, _argv: *mut c_void) -> bool { unimplemented!() }
|
||||
pub unsafe fn call(
|
||||
out: &mut Local,
|
||||
env: Env,
|
||||
fun: Local,
|
||||
this: Local,
|
||||
argc: i32,
|
||||
argv: *mut c_void,
|
||||
) -> bool {
|
||||
let status = napi::call_function(
|
||||
env,
|
||||
this,
|
||||
fun,
|
||||
argc as usize,
|
||||
argv as *const _,
|
||||
out as *mut _,
|
||||
);
|
||||
|
||||
status == napi::Status::Ok
|
||||
}
|
||||
|
||||
pub unsafe fn construct(
|
||||
out: &mut Local,
|
||||
env: Env,
|
||||
fun: Local,
|
||||
argc: i32,
|
||||
argv: *mut c_void,
|
||||
) -> bool {
|
||||
let status = napi::new_instance(env, fun, argc as usize, argv as *const _, out as *mut _);
|
||||
|
||||
status == napi::Status::Ok
|
||||
}
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
use raw::Local;
|
||||
use std::os::raw::c_void;
|
||||
|
||||
pub unsafe extern "C" fn new(_isolate: *mut c_void, _this: Local, _callback: Local) -> *mut c_void { unimplemented!() }
|
||||
pub unsafe extern "C" fn schedule(_thread_safe_cb: *mut c_void, _rust_callback: *mut c_void,
|
||||
_complete: unsafe extern fn(Local, Local, *mut c_void)) { unimplemented!() }
|
||||
pub unsafe extern "C" fn delete(_thread_safe_cb: *mut c_void) { unimplemented!() }
|
||||
49
crates/neon-runtime/src/napi/lifecycle.rs
Normal file
49
crates/neon-runtime/src/napi/lifecycle.rs
Normal file
@ -0,0 +1,49 @@
|
||||
//! # Environment life cycle APIs
|
||||
//!
|
||||
//! These APIs map to the life cycle of a specific "Agent" or self-contained
|
||||
//! environment. If a Neon module is loaded multiple times (Web Workers, worker
|
||||
//! threads), these API will be handle data associated with a specific instance.
|
||||
//!
|
||||
//! See the [N-API Lifecycle][npai-docs] documentation for more details.
|
||||
//!
|
||||
//! [napi-docs]: https://nodejs.org/api/n-api.html#n_api_environment_life_cycle_apis
|
||||
|
||||
use std::mem::MaybeUninit;
|
||||
use std::os::raw::c_void;
|
||||
use std::ptr;
|
||||
|
||||
use crate::napi::bindings as napi;
|
||||
use crate::raw::Env;
|
||||
|
||||
/// # Safety
|
||||
/// `env` must point to a valid `napi_env` for this thread
|
||||
pub unsafe fn set_instance_data<T: Send + 'static>(env: Env, data: T) -> *mut T {
|
||||
let data = Box::into_raw(Box::new(data));
|
||||
|
||||
assert_eq!(
|
||||
napi::set_instance_data(env, data.cast(), Some(drop_box::<T>), ptr::null_mut(),),
|
||||
napi::Status::Ok,
|
||||
);
|
||||
|
||||
data
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
/// * `T` must be the same type used in `set_instance_data`
|
||||
/// * Caller must ensure reference does not outlive `Env`
|
||||
/// * Return value may be `null`
|
||||
/// * `env` must point to a valid `napi_env` for this thread
|
||||
pub unsafe fn get_instance_data<T: Send + 'static>(env: Env) -> *mut T {
|
||||
let mut data = MaybeUninit::uninit();
|
||||
|
||||
assert_eq!(
|
||||
napi::get_instance_data(env, data.as_mut_ptr(),),
|
||||
napi::Status::Ok,
|
||||
);
|
||||
|
||||
data.assume_init().cast()
|
||||
}
|
||||
|
||||
unsafe extern "C" fn drop_box<T>(_env: Env, data: *mut c_void, _hint: *mut c_void) {
|
||||
Box::<T>::from_raw(data.cast());
|
||||
}
|
||||
@ -1,3 +1,11 @@
|
||||
use raw::Local;
|
||||
use crate::napi::bindings as napi;
|
||||
use crate::raw::{Env, Local};
|
||||
|
||||
pub unsafe extern "C" fn same_handle(_h1: Local, _h2: Local) -> bool { unimplemented!() }
|
||||
pub unsafe fn strict_equals(env: Env, lhs: Local, rhs: Local) -> bool {
|
||||
let mut result = false;
|
||||
assert_eq!(
|
||||
napi::strict_equals(env, lhs, rhs, &mut result as *mut _),
|
||||
napi::Status::Ok
|
||||
);
|
||||
result
|
||||
}
|
||||
|
||||
@ -2,16 +2,24 @@ pub mod array;
|
||||
pub mod arraybuffer;
|
||||
pub mod buffer;
|
||||
pub mod call;
|
||||
pub mod class;
|
||||
pub mod convert;
|
||||
#[cfg(feature = "napi-5")]
|
||||
pub mod date;
|
||||
pub mod error;
|
||||
pub mod external;
|
||||
pub mod fun;
|
||||
#[cfg(feature = "napi-6")]
|
||||
pub mod lifecycle;
|
||||
pub mod mem;
|
||||
pub mod object;
|
||||
pub mod primitive;
|
||||
pub mod raw;
|
||||
pub mod reference;
|
||||
pub mod scope;
|
||||
pub mod string;
|
||||
pub mod tag;
|
||||
pub mod task;
|
||||
pub mod handler;
|
||||
#[cfg(feature = "napi-4")]
|
||||
pub mod tsfn;
|
||||
|
||||
mod bindings;
|
||||
pub use bindings::*;
|
||||
|
||||
@ -1,98 +1,41 @@
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
use nodejs_sys as napi;
|
||||
|
||||
use array;
|
||||
use convert;
|
||||
use tag;
|
||||
use raw::{Env, Local};
|
||||
use crate::napi::bindings as napi;
|
||||
use crate::raw::{Env, Local};
|
||||
|
||||
/// Mutates the `out` argument to refer to a `napi_value` containing a newly created JavaScript Object.
|
||||
pub unsafe extern "C" fn new(out: &mut Local, env: Env) {
|
||||
napi::napi_create_object(env, out as *mut _);
|
||||
pub unsafe fn new(out: &mut Local, env: Env) {
|
||||
napi::create_object(env, out as *mut _);
|
||||
}
|
||||
|
||||
#[cfg(feature = "napi-6")]
|
||||
/// Mutates the `out` argument to refer to a `napi_value` containing the own property names of the
|
||||
/// `object` as a JavaScript Array.
|
||||
pub unsafe extern "C" fn get_own_property_names(out: &mut Local, env: Env, object: Local) -> bool {
|
||||
// Node.js 13+ have `napi_get_all_property_names`, which does the conversion right and allows
|
||||
// us to ask for only own properties or prototype properties or anything we like.
|
||||
// Unfortunately, earlier versions do not support that method, so we have to implement it
|
||||
// manually.
|
||||
//
|
||||
// So we use a temporary array for the raw names:
|
||||
let mut raw_names = MaybeUninit::uninit();
|
||||
if napi::napi_get_property_names(env, object, raw_names.as_mut_ptr()) != napi::napi_status::napi_ok {
|
||||
return false;
|
||||
}
|
||||
// And a "fixed" array for the actual return value:
|
||||
let mut fixed_names = MaybeUninit::uninit();
|
||||
if napi::napi_create_array(env, fixed_names.as_mut_ptr()) != napi::napi_status::napi_ok {
|
||||
pub unsafe fn get_own_property_names(out: &mut Local, env: Env, object: Local) -> bool {
|
||||
let mut property_names = MaybeUninit::uninit();
|
||||
|
||||
if napi::get_all_property_names(
|
||||
env,
|
||||
object,
|
||||
napi::KeyCollectionMode::OwnOnly,
|
||||
napi::KeyFilter::ALL_PROPERTIES | napi::KeyFilter::SKIP_SYMBOLS,
|
||||
napi::KeyConversion::NumbersToStrings,
|
||||
property_names.as_mut_ptr(),
|
||||
) != napi::Status::Ok
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
let raw_names = raw_names.assume_init();
|
||||
let fixed_names = fixed_names.assume_init();
|
||||
|
||||
*out = fixed_names;
|
||||
|
||||
let raw_len = array::len(env, raw_names);
|
||||
let mut fixed_len = 0;
|
||||
for index in 0..raw_len {
|
||||
let mut property_name: Local = std::mem::zeroed();
|
||||
|
||||
// In general, getters may cause arbitrary JS code to be run, but this is a newly created
|
||||
// Array from an official internal API so it doesn't do anything strange.
|
||||
if !get_index(&mut property_name, env, raw_names, index) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Before https://github.com/nodejs/node/pull/27524, `napi_get_property_names` would return
|
||||
// numbers for numeric indices instead of strings.
|
||||
// Make sure we always return strings.
|
||||
let property_name = if !tag::is_string(env, property_name) {
|
||||
let mut stringified: Local = std::mem::zeroed();
|
||||
// If we can't convert to a string, something went wrong.
|
||||
if !convert::to_string(&mut stringified, env, property_name) {
|
||||
return false;
|
||||
}
|
||||
stringified
|
||||
} else {
|
||||
property_name
|
||||
};
|
||||
|
||||
let mut is_own_property = false;
|
||||
// May return a non-OK status if `key` is not a string or a Symbol, but here it is always
|
||||
// a string.
|
||||
if napi::napi_has_own_property(env, object, property_name, &mut is_own_property as *mut _) != napi::napi_status::napi_ok {
|
||||
return false;
|
||||
}
|
||||
|
||||
if !is_own_property {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut dummy = false;
|
||||
// If we can't convert assign to this array, something went wrong.
|
||||
if !set_index(&mut dummy, env, fixed_names, fixed_len, property_name) {
|
||||
return false;
|
||||
}
|
||||
fixed_len += 1;
|
||||
}
|
||||
*out = property_names.assume_init();
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
// Unused.
|
||||
pub unsafe extern "C" fn get_isolate(_obj: Local) -> Env {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/// Mutate the `out` argument to refer to the value at `index` in the given `object`. Returns `false` if the value couldn't be retrieved.
|
||||
pub unsafe extern "C" fn get_index(out: &mut Local, env: Env, object: Local, index: u32) -> bool {
|
||||
let status = napi::napi_get_element(env, object, index, out as *mut _);
|
||||
pub unsafe fn get_index(out: &mut Local, env: Env, object: Local, index: u32) -> bool {
|
||||
let status = napi::get_element(env, object, index, out as *mut _);
|
||||
|
||||
status == napi::napi_status::napi_ok
|
||||
status == napi::Status::Ok
|
||||
}
|
||||
|
||||
/// Sets the key value of a `napi_value` at the `index` provided. Returns `true` if the set
|
||||
@ -102,29 +45,33 @@ pub unsafe extern "C" fn get_index(out: &mut Local, env: Env, object: Local, ind
|
||||
/// see [discussion].
|
||||
///
|
||||
/// [discussion]: https://github.com/neon-bindings/neon/pull/458#discussion_r344827965
|
||||
pub unsafe extern "C" fn set_index(out: &mut bool, env: Env, object: Local, index: u32, val: Local) -> bool {
|
||||
let status = napi::napi_set_element(env, object, index, val);
|
||||
*out = status == napi::napi_status::napi_ok;
|
||||
pub unsafe fn set_index(out: &mut bool, env: Env, object: Local, index: u32, val: Local) -> bool {
|
||||
let status = napi::set_element(env, object, index, val);
|
||||
*out = status == napi::Status::Ok;
|
||||
|
||||
*out
|
||||
}
|
||||
|
||||
/// Mutate the `out` argument to refer to the value at a named `key` in the given `object`. Returns `false` if the value couldn't be retrieved.
|
||||
pub unsafe extern "C" fn get_string(env: Env, out: &mut Local, object: Local, key: *const u8, len: i32) -> bool {
|
||||
pub unsafe fn get_string(
|
||||
env: Env,
|
||||
out: &mut Local,
|
||||
object: Local,
|
||||
key: *const u8,
|
||||
len: i32,
|
||||
) -> bool {
|
||||
let mut key_val = MaybeUninit::uninit();
|
||||
|
||||
// Not using `crate::string::new()` because it requires a _reference_ to a Local,
|
||||
// while we only have uninitialized memory.
|
||||
if napi::napi_create_string_utf8(env, key as *const i8, len as usize, key_val.as_mut_ptr())
|
||||
!= napi::napi_status::napi_ok
|
||||
if napi::create_string_utf8(env, key as *const _, len as usize, key_val.as_mut_ptr())
|
||||
!= napi::Status::Ok
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Not using napi_get_named_property() because the `key` may not be null terminated.
|
||||
if napi::napi_get_property(env, object, key_val.assume_init(), out as *mut _)
|
||||
!= napi::napi_status::napi_ok
|
||||
{
|
||||
if napi::get_property(env, object, key_val.assume_init(), out as *mut _) != napi::Status::Ok {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -137,21 +84,26 @@ pub unsafe extern "C" fn get_string(env: Env, out: &mut Local, object: Local, ke
|
||||
/// see [discussion].
|
||||
///
|
||||
/// [discussion]: https://github.com/neon-bindings/neon/pull/458#discussion_r344827965
|
||||
pub unsafe extern "C" fn set_string(env: Env, out: &mut bool, object: Local, key: *const u8, len: i32, val: Local) -> bool {
|
||||
pub unsafe fn set_string(
|
||||
env: Env,
|
||||
out: &mut bool,
|
||||
object: Local,
|
||||
key: *const u8,
|
||||
len: i32,
|
||||
val: Local,
|
||||
) -> bool {
|
||||
let mut key_val = MaybeUninit::uninit();
|
||||
|
||||
*out = true;
|
||||
|
||||
if napi::napi_create_string_utf8(env, key as *const i8, len as usize, key_val.as_mut_ptr())
|
||||
!= napi::napi_status::napi_ok
|
||||
if napi::create_string_utf8(env, key as *const _, len as usize, key_val.as_mut_ptr())
|
||||
!= napi::Status::Ok
|
||||
{
|
||||
*out = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if napi::napi_set_property(env, object, key_val.assume_init(), val)
|
||||
!= napi::napi_status::napi_ok
|
||||
{
|
||||
if napi::set_property(env, object, key_val.assume_init(), val) != napi::Status::Ok {
|
||||
*out = false;
|
||||
return false;
|
||||
}
|
||||
@ -161,21 +113,21 @@ pub unsafe extern "C" fn set_string(env: Env, out: &mut bool, object: Local, key
|
||||
|
||||
/// Mutates `out` to refer to the value of the property of `object` named by the `key` value.
|
||||
/// Returns false if the value couldn't be retrieved.
|
||||
pub unsafe extern "C" fn get(out: &mut Local, env: Env, object: Local, key: Local) -> bool {
|
||||
let status = napi::napi_get_property(env, object, key, out as *mut _);
|
||||
pub unsafe fn get(out: &mut Local, env: Env, object: Local, key: Local) -> bool {
|
||||
let status = napi::get_property(env, object, key, out as *mut _);
|
||||
|
||||
status == napi::napi_status::napi_ok
|
||||
status == napi::Status::Ok
|
||||
}
|
||||
|
||||
/// Sets the property value of an `napi_value` object, named by another `napi_value` `key`. Returns `true` if the set succeeded.
|
||||
/// Sets the property value of an `napi_value` object, named by another `value` `key`. Returns `true` if the set succeeded.
|
||||
///
|
||||
/// The `out` parameter and the return value contain the same information for historical reasons,
|
||||
/// see [discussion].
|
||||
///
|
||||
/// [discussion]: https://github.com/neon-bindings/neon/pull/458#discussion_r344827965
|
||||
pub unsafe extern "C" fn set(out: &mut bool, env: Env, object: Local, key: Local, val: Local) -> bool {
|
||||
let status = napi::napi_set_property(env, object, key, val);
|
||||
*out = status == napi::napi_status::napi_ok;
|
||||
pub unsafe fn set(out: &mut bool, env: Env, object: Local, key: Local, val: Local) -> bool {
|
||||
let status = napi::set_property(env, object, key, val);
|
||||
*out = status == napi::Status::Ok;
|
||||
|
||||
*out
|
||||
}
|
||||
|
||||
@ -1,50 +1,45 @@
|
||||
use raw::{Local, Env};
|
||||
|
||||
use nodejs_sys as napi;
|
||||
use crate::napi::bindings as napi;
|
||||
use crate::raw::{Env, Local};
|
||||
|
||||
/// Mutates the `out` argument provided to refer to the global `undefined` object.
|
||||
pub unsafe extern "C" fn undefined(out: &mut Local, env: Env) {
|
||||
napi::napi_get_undefined(env, out as *mut Local);
|
||||
pub unsafe fn undefined(out: &mut Local, env: Env) {
|
||||
napi::get_undefined(env, out as *mut Local);
|
||||
}
|
||||
|
||||
/// Mutates the `out` argument provided to refer to the global `null` object.
|
||||
pub unsafe extern "C" fn null(out: &mut Local, env: Env) {
|
||||
napi::napi_get_null(env, out as *mut Local);
|
||||
pub unsafe fn null(out: &mut Local, env: Env) {
|
||||
napi::get_null(env, out as *mut Local);
|
||||
}
|
||||
|
||||
/// Mutates the `out` argument provided to refer to one of the global `true` or `false` objects.
|
||||
pub unsafe extern "C" fn boolean(out: &mut Local, env: Env, b: bool) {
|
||||
napi::napi_get_boolean(env, b, out as *mut Local);
|
||||
pub unsafe fn boolean(out: &mut Local, env: Env, b: bool) {
|
||||
napi::get_boolean(env, b, out as *mut Local);
|
||||
}
|
||||
|
||||
/// Get the boolean value out of a `Local` object. If the `Local` object does not contain a
|
||||
/// boolean, this function panics.
|
||||
pub unsafe extern "C" fn boolean_value(env: Env, p: Local) -> bool {
|
||||
pub unsafe fn boolean_value(env: Env, p: Local) -> bool {
|
||||
let mut value = false;
|
||||
assert_eq!(napi::napi_get_value_bool(env, p, &mut value as *mut bool), napi::napi_status::napi_ok);
|
||||
assert_eq!(
|
||||
napi::get_value_bool(env, p, &mut value as *mut bool),
|
||||
napi::Status::Ok
|
||||
);
|
||||
value
|
||||
}
|
||||
|
||||
// DEPRECATE(0.2)
|
||||
pub unsafe extern "C" fn integer(_out: &mut Local, _isolate: Env, _x: i32) { unimplemented!() }
|
||||
|
||||
pub unsafe extern "C" fn is_u32(_p: Local) -> bool { unimplemented!() }
|
||||
|
||||
pub unsafe extern "C" fn is_i32(_p: Local) -> bool { unimplemented!() }
|
||||
|
||||
// DEPRECATE(0.2)
|
||||
pub unsafe extern "C" fn integer_value(_p: Local) -> i64 { unimplemented!() }
|
||||
|
||||
/// Mutates the `out` argument provided to refer to a newly created `Local` containing a
|
||||
/// JavaScript number.
|
||||
pub unsafe extern "C" fn number(out: &mut Local, env: Env, v: f64) {
|
||||
napi::napi_create_double(env, v, out as *mut Local);
|
||||
pub unsafe fn number(out: &mut Local, env: Env, v: f64) {
|
||||
napi::create_double(env, v, out as *mut Local);
|
||||
}
|
||||
|
||||
/// Gets the underlying value of an `Local` object containing a JavaScript number. Panics if
|
||||
/// the given `Local` is not a number.
|
||||
pub unsafe extern "C" fn number_value(env: Env, p: Local) -> f64 {
|
||||
pub unsafe fn number_value(env: Env, p: Local) -> f64 {
|
||||
let mut value = 0.0;
|
||||
assert_eq!(napi::napi_get_value_double(env, p, &mut value as *mut f64), napi::napi_status::napi_ok);
|
||||
return value;
|
||||
assert_eq!(
|
||||
napi::get_value_double(env, p, &mut value as *mut f64),
|
||||
napi::Status::Ok
|
||||
);
|
||||
value
|
||||
}
|
||||
|
||||
@ -1,32 +1,51 @@
|
||||
use std::os::raw::c_void;
|
||||
use std::ptr;
|
||||
|
||||
use nodejs_sys as napi;
|
||||
use crate::napi::bindings as napi;
|
||||
|
||||
pub type Local = napi::napi_value;
|
||||
pub type Local = napi::Value;
|
||||
|
||||
pub type FunctionCallbackInfo = c_void;
|
||||
pub type FunctionCallbackInfo = napi::CallbackInfo;
|
||||
|
||||
pub type Env = napi::napi_env;
|
||||
pub type Env = napi::Env;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct HandleScope {
|
||||
pub word: napi::napi_handle_scope
|
||||
pub word: napi::HandleScope,
|
||||
}
|
||||
|
||||
impl HandleScope {
|
||||
pub fn new() -> Self { Self { word: ptr::null_mut() } }
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
word: ptr::null_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for HandleScope {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct EscapableHandleScope {
|
||||
pub word: napi::napi_escapable_handle_scope
|
||||
pub word: napi::EscapableHandleScope,
|
||||
}
|
||||
|
||||
impl EscapableHandleScope {
|
||||
pub fn new() -> Self { Self { word: ptr::null_mut() } }
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
word: ptr::null_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for EscapableHandleScope {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
|
||||
49
crates/neon-runtime/src/napi/reference.rs
Normal file
49
crates/neon-runtime/src/napi/reference.rs
Normal file
@ -0,0 +1,49 @@
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
use crate::napi::bindings as napi;
|
||||
|
||||
use crate::raw::{Env, Local};
|
||||
|
||||
pub unsafe fn new(env: Env, value: Local) -> napi::Ref {
|
||||
let mut result = MaybeUninit::uninit();
|
||||
|
||||
assert_eq!(
|
||||
napi::create_reference(env, value, 1, result.as_mut_ptr()),
|
||||
napi::Status::Ok,
|
||||
);
|
||||
|
||||
result.assume_init()
|
||||
}
|
||||
|
||||
pub unsafe fn reference(env: Env, value: napi::Ref) -> usize {
|
||||
let mut result = MaybeUninit::uninit();
|
||||
|
||||
assert_eq!(
|
||||
napi::reference_ref(env, value, result.as_mut_ptr()),
|
||||
napi::Status::Ok,
|
||||
);
|
||||
|
||||
result.assume_init() as usize
|
||||
}
|
||||
|
||||
pub unsafe fn unreference(env: Env, value: napi::Ref) -> usize {
|
||||
let mut result = MaybeUninit::uninit();
|
||||
|
||||
assert_eq!(
|
||||
napi::reference_unref(env, value, result.as_mut_ptr()),
|
||||
napi::Status::Ok,
|
||||
);
|
||||
|
||||
result.assume_init() as usize
|
||||
}
|
||||
|
||||
pub unsafe fn get(env: Env, value: napi::Ref) -> Local {
|
||||
let mut result = MaybeUninit::uninit();
|
||||
|
||||
assert_eq!(
|
||||
napi::get_reference_value(env, value, result.as_mut_ptr()),
|
||||
napi::Status::Ok,
|
||||
);
|
||||
|
||||
result.assume_init()
|
||||
}
|
||||
@ -1,72 +1,71 @@
|
||||
use std::os::raw::c_void;
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
use nodejs_sys as napi;
|
||||
|
||||
use raw::{Env, HandleScope, EscapableHandleScope, InheritedHandleScope};
|
||||
|
||||
type Local = napi::napi_value;
|
||||
use crate::napi::bindings as napi;
|
||||
use crate::raw::{Env, EscapableHandleScope, HandleScope, InheritedHandleScope, Local};
|
||||
|
||||
// TODO: This leaves a lot of room for UB; we can have a cleaner
|
||||
// implementation for N-API.
|
||||
pub trait Root {
|
||||
unsafe fn allocate() -> Self;
|
||||
unsafe fn enter(&mut self, Env);
|
||||
unsafe fn exit(&mut self, Env);
|
||||
unsafe fn enter(&mut self, env: Env);
|
||||
unsafe fn exit(&mut self, env: Env);
|
||||
}
|
||||
|
||||
impl Root for HandleScope {
|
||||
unsafe fn allocate() -> Self { HandleScope::new() }
|
||||
unsafe fn allocate() -> Self {
|
||||
HandleScope::new()
|
||||
}
|
||||
unsafe fn enter(&mut self, env: Env) {
|
||||
let mut scope = MaybeUninit::uninit();
|
||||
let status = napi::napi_open_handle_scope(env, scope.as_mut_ptr());
|
||||
let status = napi::open_handle_scope(env, scope.as_mut_ptr());
|
||||
|
||||
assert_eq!(status, napi::napi_status::napi_ok);
|
||||
assert_eq!(status, napi::Status::Ok);
|
||||
|
||||
self.word = scope.assume_init();
|
||||
}
|
||||
unsafe fn exit(&mut self, env: Env) {
|
||||
let status = napi::napi_close_handle_scope(env, self.word);
|
||||
let status = napi::close_handle_scope(env, self.word);
|
||||
|
||||
assert_eq!(status, napi::napi_status::napi_ok);
|
||||
assert_eq!(status, napi::Status::Ok);
|
||||
}
|
||||
}
|
||||
|
||||
impl Root for EscapableHandleScope {
|
||||
unsafe fn allocate() -> Self { EscapableHandleScope::new() }
|
||||
unsafe fn allocate() -> Self {
|
||||
EscapableHandleScope::new()
|
||||
}
|
||||
unsafe fn enter(&mut self, env: Env) {
|
||||
let mut scope = MaybeUninit::uninit();
|
||||
let status = napi::napi_open_escapable_handle_scope(env, scope.as_mut_ptr());
|
||||
let status = napi::open_escapable_handle_scope(env, scope.as_mut_ptr());
|
||||
|
||||
assert_eq!(status, napi::napi_status::napi_ok);
|
||||
assert_eq!(status, napi::Status::Ok);
|
||||
|
||||
self.word = scope.assume_init();
|
||||
}
|
||||
unsafe fn exit(&mut self, env: Env) {
|
||||
let status = napi::napi_close_escapable_handle_scope(env, self.word);
|
||||
let status = napi::close_escapable_handle_scope(env, self.word);
|
||||
|
||||
assert_eq!(status, napi::napi_status::napi_ok);
|
||||
assert_eq!(status, napi::Status::Ok);
|
||||
}
|
||||
}
|
||||
|
||||
impl Root for InheritedHandleScope {
|
||||
unsafe fn allocate() -> Self { InheritedHandleScope }
|
||||
unsafe fn enter(&mut self, _: Env) { }
|
||||
unsafe fn exit(&mut self, _: Env) { }
|
||||
unsafe fn allocate() -> Self {
|
||||
InheritedHandleScope
|
||||
}
|
||||
unsafe fn enter(&mut self, _: Env) {}
|
||||
unsafe fn exit(&mut self, _: Env) {}
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn escape(_out: &mut Local, _scope: *mut EscapableHandleScope, _value: Local) { unimplemented!() }
|
||||
pub unsafe fn escape(env: Env, out: &mut Local, scope: *mut EscapableHandleScope, value: Local) {
|
||||
let status = napi::escape_handle(env, (*scope).word, value, out as *mut _);
|
||||
|
||||
pub unsafe extern "C" fn chained(_out: *mut c_void, _closure: *mut c_void, _callback: extern fn(&mut c_void, *mut c_void, *mut c_void, *mut c_void), _parent_scope: *mut c_void) { unimplemented!() }
|
||||
assert_eq!(status, napi::Status::Ok);
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn nested(_out: *mut c_void, _closure: *mut c_void, _callback: extern fn(&mut c_void, *mut c_void, *mut c_void), _realm: *mut c_void) { unimplemented!() }
|
||||
|
||||
pub unsafe extern "C" fn size() -> usize { unimplemented!() }
|
||||
|
||||
pub unsafe extern "C" fn alignment() -> usize { unimplemented!() }
|
||||
|
||||
pub unsafe extern "C" fn escapable_size() -> usize { unimplemented!() }
|
||||
|
||||
pub unsafe extern "C" fn escapable_alignment() -> usize { unimplemented!() }
|
||||
|
||||
pub unsafe extern "C" fn get_global(_env: Env, _out: &mut Local) { unimplemented!() }
|
||||
pub unsafe fn get_global(env: Env, out: &mut Local) {
|
||||
assert_eq!(
|
||||
crate::napi::bindings::get_global(env, out as *mut _),
|
||||
napi::Status::Ok
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,47 +1,36 @@
|
||||
use std::mem::MaybeUninit;
|
||||
use std::ptr;
|
||||
|
||||
use nodejs_sys as napi;
|
||||
|
||||
use raw::{Env, Local};
|
||||
use crate::napi::bindings as napi;
|
||||
use crate::raw::{Env, Local};
|
||||
|
||||
pub unsafe fn new(out: &mut Local, env: Env, data: *const u8, len: i32) -> bool {
|
||||
let status = napi::napi_create_string_utf8(
|
||||
env,
|
||||
data as *const i8,
|
||||
len as usize,
|
||||
out,
|
||||
);
|
||||
let status = napi::create_string_utf8(env, data as *const _, len as usize, out);
|
||||
|
||||
status == napi::napi_status::napi_ok
|
||||
status == napi::Status::Ok
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn utf8_len(env: Env, value: Local) -> isize {
|
||||
pub unsafe fn utf8_len(env: Env, value: Local) -> isize {
|
||||
let mut len = MaybeUninit::uninit();
|
||||
let status = napi::napi_get_value_string_utf8(
|
||||
env,
|
||||
value,
|
||||
ptr::null_mut(),
|
||||
0,
|
||||
len.as_mut_ptr(),
|
||||
);
|
||||
let status = napi::get_value_string_utf8(env, value, ptr::null_mut(), 0, len.as_mut_ptr());
|
||||
|
||||
assert_eq!(status, napi::napi_status::napi_ok);
|
||||
assert_eq!(status, napi::Status::Ok);
|
||||
|
||||
len.assume_init() as isize
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn data(env: Env, out: *mut u8, len: isize, value: Local) -> isize {
|
||||
pub unsafe fn data(env: Env, out: *mut u8, len: isize, value: Local) -> isize {
|
||||
let mut read = MaybeUninit::uninit();
|
||||
let status = napi::napi_get_value_string_utf8(
|
||||
env,
|
||||
value,
|
||||
out as *mut i8,
|
||||
len as usize,
|
||||
read.as_mut_ptr(),
|
||||
);
|
||||
let status =
|
||||
napi::get_value_string_utf8(env, value, out as *mut _, len as usize, read.as_mut_ptr());
|
||||
|
||||
assert_eq!(status, napi::napi_status::napi_ok);
|
||||
assert_eq!(status, napi::Status::Ok);
|
||||
|
||||
read.assume_init() as isize
|
||||
}
|
||||
|
||||
pub unsafe fn run_script(out: &mut Local, env: Env, value: Local) -> bool {
|
||||
let status = napi::run_script(env, value, out as *mut _);
|
||||
|
||||
status == napi::Status::Ok
|
||||
}
|
||||
|
||||
@ -1,44 +1,91 @@
|
||||
use raw::{Env, Local};
|
||||
|
||||
use nodejs_sys as napi;
|
||||
use crate::napi::bindings as napi;
|
||||
use crate::raw::{Env, Local};
|
||||
|
||||
/// Return true if an `napi_value` `val` has the expected value type.
|
||||
unsafe fn is_type(env: Env, val: Local, expect: napi::napi_valuetype) -> bool {
|
||||
let mut actual = napi::napi_valuetype::napi_undefined;
|
||||
if napi::napi_typeof(env, val, &mut actual as *mut _) == napi::napi_status::napi_ok {
|
||||
actual == expect
|
||||
} else {
|
||||
false
|
||||
}
|
||||
unsafe fn is_type(env: Env, val: Local, expect: napi::ValueType) -> bool {
|
||||
let mut actual = napi::ValueType::Undefined;
|
||||
assert_eq!(
|
||||
napi::typeof_value(env, val, &mut actual as *mut _),
|
||||
napi::Status::Ok
|
||||
);
|
||||
actual == expect
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn is_undefined(_env: Env, _val: Local) -> bool { unimplemented!() }
|
||||
pub unsafe fn is_undefined(env: Env, val: Local) -> bool {
|
||||
is_type(env, val, napi::ValueType::Undefined)
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn is_null(_env: Env, _val: Local) -> bool { unimplemented!() }
|
||||
pub unsafe fn is_null(env: Env, val: Local) -> bool {
|
||||
is_type(env, val, napi::ValueType::Null)
|
||||
}
|
||||
|
||||
/// Is `val` a JavaScript number?
|
||||
pub unsafe extern "C" fn is_number(env: Env, val: Local) -> bool {
|
||||
is_type(env, val, napi::napi_valuetype::napi_number)
|
||||
pub unsafe fn is_number(env: Env, val: Local) -> bool {
|
||||
is_type(env, val, napi::ValueType::Number)
|
||||
}
|
||||
|
||||
/// Is `val` a JavaScript boolean?
|
||||
pub unsafe extern "C" fn is_boolean(env: Env, val: Local) -> bool {
|
||||
is_type(env, val, napi::napi_valuetype::napi_boolean)
|
||||
pub unsafe fn is_boolean(env: Env, val: Local) -> bool {
|
||||
is_type(env, val, napi::ValueType::Boolean)
|
||||
}
|
||||
|
||||
/// Is `val` a JavaScript string?
|
||||
pub unsafe extern "C" fn is_string(env: Env, val: Local) -> bool {
|
||||
is_type(env, val, napi::napi_valuetype::napi_string)
|
||||
pub unsafe fn is_string(env: Env, val: Local) -> bool {
|
||||
is_type(env, val, napi::ValueType::String)
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn is_object(_env: Env, _val: Local) -> bool { unimplemented!() }
|
||||
pub unsafe fn is_object(env: Env, val: Local) -> bool {
|
||||
is_type(env, val, napi::ValueType::Object)
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn is_array(_env: Env, _val: Local) -> bool { unimplemented!() }
|
||||
pub unsafe fn is_array(env: Env, val: Local) -> bool {
|
||||
let mut result = false;
|
||||
assert_eq!(
|
||||
napi::is_array(env, val, &mut result as *mut _),
|
||||
napi::Status::Ok
|
||||
);
|
||||
result
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn is_function(_env: Env, _val: Local) -> bool { unimplemented!() }
|
||||
pub unsafe fn is_function(env: Env, val: Local) -> bool {
|
||||
is_type(env, val, napi::ValueType::Function)
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn is_error(_env: Env, _val: Local) -> bool { unimplemented!() }
|
||||
pub unsafe fn is_error(env: Env, val: Local) -> bool {
|
||||
let mut result = false;
|
||||
assert_eq!(
|
||||
napi::is_error(env, val, &mut result as *mut _),
|
||||
napi::Status::Ok
|
||||
);
|
||||
result
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn is_buffer(_env: Env, _obj: Local) -> bool { unimplemented!() }
|
||||
/// Is `val` a Node.js Buffer instance?
|
||||
pub unsafe fn is_buffer(env: Env, val: Local) -> bool {
|
||||
let mut result = false;
|
||||
assert_eq!(
|
||||
napi::is_buffer(env, val, &mut result as *mut _),
|
||||
napi::Status::Ok
|
||||
);
|
||||
result
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn is_arraybuffer(_env: Env, _obj: Local) -> bool { unimplemented!() }
|
||||
/// Is `val` an ArrayBuffer instance?
|
||||
pub unsafe fn is_arraybuffer(env: Env, val: Local) -> bool {
|
||||
let mut result = false;
|
||||
assert_eq!(
|
||||
napi::is_arraybuffer(env, val, &mut result as *mut _),
|
||||
napi::Status::Ok
|
||||
);
|
||||
result
|
||||
}
|
||||
|
||||
#[cfg(feature = "napi-5")]
|
||||
pub unsafe fn is_date(env: Env, val: Local) -> bool {
|
||||
let mut result = false;
|
||||
assert_eq!(
|
||||
napi::is_date(env, val, &mut result as *mut _),
|
||||
napi::Status::Ok
|
||||
);
|
||||
result
|
||||
}
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
use raw::Local;
|
||||
use std::os::raw::c_void;
|
||||
|
||||
pub unsafe extern "C" fn schedule(_task: *mut c_void,
|
||||
_perform: unsafe extern fn(*mut c_void) -> *mut c_void,
|
||||
_complete: unsafe extern fn(*mut c_void, &mut Local),
|
||||
_callback: Local) { unimplemented!() }
|
||||
177
crates/neon-runtime/src/napi/tsfn.rs
Normal file
177
crates/neon-runtime/src/napi/tsfn.rs
Normal file
@ -0,0 +1,177 @@
|
||||
//! Idiomatic Rust wrappers for N-API threadsafe functions
|
||||
|
||||
use std::ffi::c_void;
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
use crate::napi::bindings as napi;
|
||||
use crate::raw::{Env, Local};
|
||||
|
||||
unsafe fn string(env: Env, s: impl AsRef<str>) -> Local {
|
||||
let s = s.as_ref();
|
||||
let mut result = MaybeUninit::uninit();
|
||||
|
||||
assert_eq!(
|
||||
napi::create_string_utf8(
|
||||
env,
|
||||
s.as_bytes().as_ptr() as *const _,
|
||||
s.len(),
|
||||
result.as_mut_ptr(),
|
||||
),
|
||||
napi::Status::Ok,
|
||||
);
|
||||
|
||||
result.assume_init()
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Tsfn(napi::ThreadsafeFunction);
|
||||
|
||||
unsafe impl Send for Tsfn {}
|
||||
unsafe impl Sync for Tsfn {}
|
||||
|
||||
#[derive(Debug)]
|
||||
/// Threadsafe Function encapsulate a Rust function pointer and N-API threadsafe
|
||||
/// function for scheduling tasks to execute on a JavaScript thread.
|
||||
pub struct ThreadsafeFunction<T> {
|
||||
tsfn: Tsfn,
|
||||
callback: fn(Option<Env>, T),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Callback<T> {
|
||||
callback: fn(Option<Env>, T),
|
||||
data: T,
|
||||
}
|
||||
|
||||
/// Error returned when scheduling a threadsafe function with some data
|
||||
pub struct CallError<T> {
|
||||
kind: napi::Status,
|
||||
data: T,
|
||||
}
|
||||
|
||||
impl<T> CallError<T> {
|
||||
/// The specific error that occurred
|
||||
pub fn kind(&self) -> napi::Status {
|
||||
self.kind
|
||||
}
|
||||
|
||||
/// Returns the data that was sent when scheduling to allow re-scheduling
|
||||
pub fn into_inner(self) -> T {
|
||||
self.data
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Send + 'static> ThreadsafeFunction<T> {
|
||||
/// Creates a new unbounded N-API Threadsafe Function
|
||||
/// Safety: `Env` must be valid for the current thread
|
||||
pub unsafe fn new(env: Env, callback: fn(Option<Env>, T)) -> Self {
|
||||
Self::with_capacity(env, 0, callback)
|
||||
}
|
||||
|
||||
/// Creates a bounded N-API Threadsafe Function
|
||||
/// Safety: `Env` must be valid for the current thread
|
||||
pub unsafe fn with_capacity(
|
||||
env: Env,
|
||||
max_queue_size: usize,
|
||||
callback: fn(Option<Env>, T),
|
||||
) -> Self {
|
||||
let mut result = MaybeUninit::uninit();
|
||||
|
||||
assert_eq!(
|
||||
napi::create_threadsafe_function(
|
||||
env,
|
||||
std::ptr::null_mut(),
|
||||
std::ptr::null_mut(),
|
||||
string(env, "neon threadsafe function"),
|
||||
max_queue_size,
|
||||
// Always set the reference count to 1. Prefer using
|
||||
// Rust `Arc` to maintain the struct.
|
||||
1,
|
||||
std::ptr::null_mut(),
|
||||
None,
|
||||
std::ptr::null_mut(),
|
||||
Some(Self::callback),
|
||||
result.as_mut_ptr(),
|
||||
),
|
||||
napi::Status::Ok,
|
||||
);
|
||||
|
||||
Self {
|
||||
tsfn: Tsfn(result.assume_init()),
|
||||
callback,
|
||||
}
|
||||
}
|
||||
|
||||
/// Schedule a threadsafe function to be executed with some data
|
||||
pub fn call(
|
||||
&self,
|
||||
data: T,
|
||||
is_blocking: Option<napi::ThreadsafeFunctionCallMode>,
|
||||
) -> Result<(), CallError<T>> {
|
||||
let is_blocking = is_blocking.unwrap_or(napi::ThreadsafeFunctionCallMode::Blocking);
|
||||
|
||||
let callback = Box::into_raw(Box::new(Callback {
|
||||
callback: self.callback,
|
||||
data,
|
||||
}));
|
||||
|
||||
let status =
|
||||
unsafe { napi::call_threadsafe_function(self.tsfn.0, callback as *mut _, is_blocking) };
|
||||
|
||||
if status == napi::Status::Ok {
|
||||
Ok(())
|
||||
} else {
|
||||
// If the call failed, the callback won't execute
|
||||
let callback = unsafe { Box::from_raw(callback) };
|
||||
|
||||
Err(CallError {
|
||||
kind: status,
|
||||
data: callback.data,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// References a threadsafe function to prevent exiting the event loop until it has been dropped. (Default)
|
||||
/// Safety: `Env` must be valid for the current thread
|
||||
pub unsafe fn reference(&mut self, env: Env) {
|
||||
assert_eq!(
|
||||
napi::ref_threadsafe_function(env, self.tsfn.0,),
|
||||
napi::Status::Ok,
|
||||
);
|
||||
}
|
||||
|
||||
/// Unreferences a threadsafe function to allow exiting the event loop before it has been dropped.
|
||||
/// Safety: `Env` must be valid for the current thread
|
||||
pub unsafe fn unref(&mut self, env: Env) {
|
||||
assert_eq!(
|
||||
napi::unref_threadsafe_function(env, self.tsfn.0,),
|
||||
napi::Status::Ok,
|
||||
);
|
||||
}
|
||||
|
||||
// Provides a C ABI wrapper for invoking the user supplied function pointer
|
||||
unsafe extern "C" fn callback(
|
||||
env: Env,
|
||||
_js_callback: napi::Value,
|
||||
_context: *mut c_void,
|
||||
data: *mut c_void,
|
||||
) {
|
||||
let Callback { callback, data } = *Box::from_raw(data as *mut Callback<T>);
|
||||
|
||||
// Event loop has terminated
|
||||
let env = if env.is_null() { None } else { Some(env) };
|
||||
|
||||
callback(env, data);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Drop for ThreadsafeFunction<T> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
napi::release_threadsafe_function(
|
||||
self.tsfn.0,
|
||||
napi::ThreadsafeFunctionReleaseMode::Release,
|
||||
);
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "neon-sys"
|
||||
version = "0.4.0"
|
||||
version = "0.8.2"
|
||||
authors = ["David Herman <david.herman@gmail.com>"]
|
||||
description = "Exposes the low-level V8/NAN C/C++ APIs. Will be superseded by N-API."
|
||||
edition = "2018"
|
||||
|
||||
@ -12,11 +12,11 @@ mod build {
|
||||
|
||||
#[cfg(not(feature = "docs-only"))]
|
||||
mod build {
|
||||
use std::process::Command;
|
||||
use regex::Regex;
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use regex::Regex;
|
||||
use std::process::Command;
|
||||
|
||||
pub fn main() {
|
||||
let out_dir = env::var("OUT_DIR").unwrap();
|
||||
@ -94,7 +94,8 @@ mod build {
|
||||
//
|
||||
// gyp verb architecture ia32
|
||||
fn parse_node_arch(node_gyp_output: &str) -> String {
|
||||
let version_regex = Regex::new(r"gyp verb architecture (?P<arch>ia32|x64)").unwrap();
|
||||
let version_regex =
|
||||
Regex::new(r"gyp verb architecture (?P<arch>ia32|x64|arm|arm64)").unwrap();
|
||||
let captures = version_regex.captures(&node_gyp_output).unwrap();
|
||||
String::from(&captures["arch"])
|
||||
}
|
||||
@ -109,7 +110,10 @@ mod build {
|
||||
.find(node_root_dir_flag_pattern)
|
||||
.map(|i| i + node_root_dir_flag_pattern.len())
|
||||
.expect("Couldn't find node_root_dir in node-gyp output.");
|
||||
let node_root_dir_end_index = node_gyp_output[node_root_dir_start_index..].find("'").unwrap() + node_root_dir_start_index;
|
||||
let node_root_dir_end_index = node_gyp_output[node_root_dir_start_index..]
|
||||
.find('\'')
|
||||
.unwrap()
|
||||
+ node_root_dir_start_index;
|
||||
&node_gyp_output[node_root_dir_start_index..node_root_dir_end_index]
|
||||
}
|
||||
|
||||
@ -131,7 +135,10 @@ mod build {
|
||||
.find(node_lib_file_flag_pattern)
|
||||
.map(|i| i + node_lib_file_flag_pattern.len())
|
||||
.expect("Couldn't find node_lib_file in node-gyp output.");
|
||||
let node_lib_file_end_index = node_gyp_output[node_lib_file_start_index..].find("'").unwrap() + node_lib_file_start_index;
|
||||
let node_lib_file_end_index = node_gyp_output[node_lib_file_start_index..]
|
||||
.find('\'')
|
||||
.unwrap()
|
||||
+ node_lib_file_start_index;
|
||||
&node_gyp_output[node_lib_file_start_index..node_lib_file_end_index]
|
||||
}
|
||||
|
||||
@ -147,37 +154,70 @@ mod build {
|
||||
}
|
||||
|
||||
// Ensure that all package.json dependencies and dev dependencies are installed.
|
||||
npm(native_dir).args(&["install", "--silent"]).status().ok().expect("Failed to run \"npm install\" for neon-sys!");
|
||||
npm(native_dir)
|
||||
.args(&["install", "--silent"])
|
||||
.status()
|
||||
.expect("Failed to run \"npm install\" for neon-sys!");
|
||||
|
||||
// Run `node-gyp configure` in verbose mode to read node_root_dir on Windows.
|
||||
let output = npm(native_dir)
|
||||
.args(&["run", if debug() { "configure-debug" } else { "configure-release" }])
|
||||
.args(&[
|
||||
"run",
|
||||
if debug() {
|
||||
"configure-debug"
|
||||
} else {
|
||||
"configure-release"
|
||||
},
|
||||
])
|
||||
.output()
|
||||
.expect("Failed to run \"node-gyp configure\" for neon-sys!");
|
||||
|
||||
if !output.status.success() {
|
||||
panic!(format!(
|
||||
panic!(
|
||||
"Failed to run \"node-gyp configure\" for neon-sys!\n Out: {}\n Err: {}",
|
||||
String::from_utf8_lossy(&output.stdout),
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
));
|
||||
);
|
||||
}
|
||||
|
||||
if cfg!(windows) {
|
||||
let node_gyp_output = String::from_utf8_lossy(&output.stderr);
|
||||
println!("cargo:node_root_dir={}", parse_node_root_dir(&node_gyp_output));
|
||||
println!("cargo:node_lib_file={}", parse_node_lib_file(&node_gyp_output));
|
||||
println!(
|
||||
"cargo:node_root_dir={}",
|
||||
parse_node_root_dir(&node_gyp_output)
|
||||
);
|
||||
println!(
|
||||
"cargo:node_lib_file={}",
|
||||
parse_node_lib_file(&node_gyp_output)
|
||||
);
|
||||
}
|
||||
|
||||
// Run `node-gyp build`.
|
||||
let build_output = npm(native_dir)
|
||||
.args(&["run", if debug() { "build-debug" } else { "build-release" }])
|
||||
.args(&[
|
||||
"run",
|
||||
if debug() {
|
||||
"build-debug"
|
||||
} else {
|
||||
"build-release"
|
||||
},
|
||||
])
|
||||
.output()
|
||||
.ok()
|
||||
.expect("Failed to run \"node-gyp build\" for neon-sys!");
|
||||
|
||||
if !build_output.status.success() {
|
||||
panic!(
|
||||
"Failed to run \"node-gyp build\" for neon-sys!\n Out: {}\n Err: {}",
|
||||
String::from_utf8_lossy(&build_output.stdout),
|
||||
String::from_utf8_lossy(&build_output.stderr)
|
||||
);
|
||||
}
|
||||
|
||||
let node_gyp_build_output = String::from_utf8_lossy(&build_output.stderr);
|
||||
println!("cargo:node_arch={}", parse_node_arch(&node_gyp_build_output));
|
||||
println!(
|
||||
"cargo:node_arch={}",
|
||||
parse_node_arch(&node_gyp_build_output)
|
||||
);
|
||||
}
|
||||
|
||||
// Link the built object file into a static library.
|
||||
@ -193,15 +233,23 @@ mod build {
|
||||
.join("src")
|
||||
.join("neon.o")
|
||||
} else {
|
||||
native_dir
|
||||
let neon_dir = native_dir
|
||||
.join("build")
|
||||
.join(configuration)
|
||||
.join("obj")
|
||||
.join("neon")
|
||||
.join("neon.obj")
|
||||
.join("neon");
|
||||
let object_path = neon_dir.join("src").join("neon.obj");
|
||||
if object_path.exists() {
|
||||
object_path
|
||||
} else {
|
||||
neon_dir.join("neon.obj")
|
||||
}
|
||||
};
|
||||
|
||||
cc::Build::new().cpp(true).object(object_path).compile("libneon.a");
|
||||
cc::Build::new()
|
||||
.cpp(true)
|
||||
.object(object_path)
|
||||
.compile("libneon.a");
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
@ -232,7 +280,7 @@ mod build {
|
||||
fn debug() -> bool {
|
||||
match env::var("DEBUG") {
|
||||
Ok(s) => s == "true",
|
||||
Err(_) => false
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
432
crates/neon-sys/native/package-lock.json
generated
432
crates/neon-sys/native/package-lock.json
generated
@ -8,14 +8,14 @@
|
||||
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
|
||||
},
|
||||
"ajv": {
|
||||
"version": "5.5.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
|
||||
"integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
|
||||
"version": "6.12.6",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||
"requires": {
|
||||
"co": "^4.6.0",
|
||||
"fast-deep-equal": "^1.0.0",
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.3.0"
|
||||
"json-schema-traverse": "^0.4.1",
|
||||
"uri-js": "^4.2.2"
|
||||
}
|
||||
},
|
||||
"ansi-regex": {
|
||||
@ -29,18 +29,21 @@
|
||||
"integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
|
||||
},
|
||||
"are-we-there-yet": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz",
|
||||
"integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=",
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
|
||||
"integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
|
||||
"requires": {
|
||||
"delegates": "^1.0.0",
|
||||
"readable-stream": "^2.0.6"
|
||||
}
|
||||
},
|
||||
"asn1": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
|
||||
"integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y="
|
||||
"version": "0.2.4",
|
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
|
||||
"integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
|
||||
"requires": {
|
||||
"safer-buffer": "~2.1.0"
|
||||
}
|
||||
},
|
||||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
@ -58,9 +61,9 @@
|
||||
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
|
||||
},
|
||||
"aws4": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz",
|
||||
"integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w=="
|
||||
"version": "1.11.0",
|
||||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
|
||||
"integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA=="
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
@ -68,10 +71,9 @@
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
|
||||
},
|
||||
"bcrypt-pbkdf": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz",
|
||||
"integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=",
|
||||
"optional": true,
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
|
||||
"integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
|
||||
"requires": {
|
||||
"tweetnacl": "^0.14.3"
|
||||
}
|
||||
@ -81,18 +83,10 @@
|
||||
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz",
|
||||
"integrity": "sha1-FK1hE4EtLTfXLme0ystLtyZQXxE="
|
||||
},
|
||||
"block-stream": {
|
||||
"version": "0.0.9",
|
||||
"resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
|
||||
"integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
|
||||
"requires": {
|
||||
"inherits": "~2.0.0"
|
||||
}
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.8",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
|
||||
"integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=",
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
@ -103,10 +97,10 @@
|
||||
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
|
||||
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
|
||||
},
|
||||
"co": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
|
||||
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
|
||||
"chownr": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
|
||||
"integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="
|
||||
},
|
||||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
@ -114,9 +108,9 @@
|
||||
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
|
||||
"integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=",
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"requires": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
}
|
||||
@ -155,14 +149,19 @@
|
||||
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
|
||||
},
|
||||
"ecc-jsbn": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
|
||||
"integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
|
||||
"optional": true,
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
|
||||
"integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
|
||||
"requires": {
|
||||
"jsbn": "~0.1.0"
|
||||
"jsbn": "~0.1.0",
|
||||
"safer-buffer": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"env-paths": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz",
|
||||
"integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA=="
|
||||
},
|
||||
"extend": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||
@ -174,14 +173,14 @@
|
||||
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
|
||||
},
|
||||
"fast-deep-equal": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
|
||||
"integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ="
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
|
||||
},
|
||||
"fast-json-stable-stringify": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
|
||||
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
||||
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
|
||||
},
|
||||
"forever-agent": {
|
||||
"version": "0.6.1",
|
||||
@ -189,31 +188,28 @@
|
||||
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
|
||||
},
|
||||
"form-data": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz",
|
||||
"integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=",
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
|
||||
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
|
||||
"requires": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "1.0.6",
|
||||
"combined-stream": "^1.0.6",
|
||||
"mime-types": "^2.1.12"
|
||||
}
|
||||
},
|
||||
"fs-minipass": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
|
||||
"integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
|
||||
"requires": {
|
||||
"minipass": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
|
||||
},
|
||||
"fstream": {
|
||||
"version": "1.0.12",
|
||||
"resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
|
||||
"integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.2",
|
||||
"inherits": "~2.0.0",
|
||||
"mkdirp": ">=0.5 0",
|
||||
"rimraf": "2"
|
||||
}
|
||||
},
|
||||
"gauge": {
|
||||
"version": "2.7.4",
|
||||
"resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
|
||||
@ -238,9 +234,9 @@
|
||||
}
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
|
||||
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
|
||||
"version": "7.1.6",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
|
||||
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
@ -251,9 +247,9 @@
|
||||
}
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.1.11",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
|
||||
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg="
|
||||
"version": "4.2.4",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
|
||||
"integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw=="
|
||||
},
|
||||
"har-schema": {
|
||||
"version": "2.0.0",
|
||||
@ -261,11 +257,11 @@
|
||||
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
|
||||
},
|
||||
"har-validator": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz",
|
||||
"integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=",
|
||||
"version": "5.1.5",
|
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
|
||||
"integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
|
||||
"requires": {
|
||||
"ajv": "^5.1.0",
|
||||
"ajv": "^6.12.3",
|
||||
"har-schema": "^2.0.0"
|
||||
}
|
||||
},
|
||||
@ -294,9 +290,9 @@
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "1.0.0",
|
||||
@ -329,8 +325,7 @@
|
||||
"jsbn": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
|
||||
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
|
||||
"optional": true
|
||||
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
|
||||
},
|
||||
"json-schema": {
|
||||
"version": "0.2.3",
|
||||
@ -338,9 +333,9 @@
|
||||
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
|
||||
"integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A="
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
|
||||
},
|
||||
"json-stringify-safe": {
|
||||
"version": "5.0.1",
|
||||
@ -359,16 +354,16 @@
|
||||
}
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.33.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz",
|
||||
"integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ=="
|
||||
"version": "1.44.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
|
||||
"integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg=="
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.18",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz",
|
||||
"integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==",
|
||||
"version": "2.1.27",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz",
|
||||
"integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==",
|
||||
"requires": {
|
||||
"mime-db": "~1.33.0"
|
||||
"mime-db": "1.44.0"
|
||||
}
|
||||
},
|
||||
"minimatch": {
|
||||
@ -379,18 +374,27 @@
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
|
||||
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
|
||||
"minipass": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz",
|
||||
"integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==",
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"minizlib": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
|
||||
"integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
|
||||
"requires": {
|
||||
"minipass": "^3.0.0",
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
||||
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
|
||||
},
|
||||
"nan": {
|
||||
"version": "2.14.0",
|
||||
@ -398,29 +402,26 @@
|
||||
"integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg=="
|
||||
},
|
||||
"node-gyp": {
|
||||
"version": "3.6.2",
|
||||
"resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.6.2.tgz",
|
||||
"integrity": "sha1-m/vlRWIoYoSDjnUOrAUpWFP6HGA=",
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-7.1.2.tgz",
|
||||
"integrity": "sha512-CbpcIo7C3eMu3dL1c3d0xw449fHIGALIJsRP4DDPHpyiW8vcriNY7ubh9TE4zEKfSxscY7PjeFnshE7h75ynjQ==",
|
||||
"requires": {
|
||||
"fstream": "^1.0.0",
|
||||
"glob": "^7.0.3",
|
||||
"graceful-fs": "^4.1.2",
|
||||
"minimatch": "^3.0.2",
|
||||
"mkdirp": "^0.5.0",
|
||||
"nopt": "2 || 3",
|
||||
"npmlog": "0 || 1 || 2 || 3 || 4",
|
||||
"osenv": "0",
|
||||
"request": "2",
|
||||
"rimraf": "2",
|
||||
"semver": "~5.3.0",
|
||||
"tar": "^2.0.0",
|
||||
"which": "1"
|
||||
"env-paths": "^2.2.0",
|
||||
"glob": "^7.1.4",
|
||||
"graceful-fs": "^4.2.3",
|
||||
"nopt": "^5.0.0",
|
||||
"npmlog": "^4.1.2",
|
||||
"request": "^2.88.2",
|
||||
"rimraf": "^3.0.2",
|
||||
"semver": "^7.3.2",
|
||||
"tar": "^6.0.2",
|
||||
"which": "^2.0.2"
|
||||
}
|
||||
},
|
||||
"nopt": {
|
||||
"version": "3.0.6",
|
||||
"resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
|
||||
"integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
|
||||
"integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
|
||||
"requires": {
|
||||
"abbrev": "1"
|
||||
}
|
||||
@ -442,9 +443,9 @@
|
||||
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
|
||||
},
|
||||
"oauth-sign": {
|
||||
"version": "0.8.2",
|
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
|
||||
"integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM="
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
|
||||
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
@ -459,25 +460,6 @@
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"os-homedir": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
|
||||
"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="
|
||||
},
|
||||
"os-tmpdir": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
|
||||
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
|
||||
},
|
||||
"osenv": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz",
|
||||
"integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=",
|
||||
"requires": {
|
||||
"os-homedir": "^1.0.0",
|
||||
"os-tmpdir": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
@ -489,14 +471,19 @@
|
||||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
|
||||
},
|
||||
"process-nextick-args": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
|
||||
"integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
|
||||
},
|
||||
"psl": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
|
||||
"integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ=="
|
||||
},
|
||||
"punycode": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
|
||||
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.5.2",
|
||||
@ -504,63 +491,68 @@
|
||||
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
|
||||
"integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==",
|
||||
"version": "2.3.7",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
|
||||
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
|
||||
"requires": {
|
||||
"core-util-is": "~1.0.0",
|
||||
"inherits": "~2.0.3",
|
||||
"isarray": "~1.0.0",
|
||||
"process-nextick-args": "~1.0.6",
|
||||
"process-nextick-args": "~2.0.0",
|
||||
"safe-buffer": "~5.1.1",
|
||||
"string_decoder": "~1.0.3",
|
||||
"string_decoder": "~1.1.1",
|
||||
"util-deprecate": "~1.0.1"
|
||||
}
|
||||
},
|
||||
"request": {
|
||||
"version": "2.87.0",
|
||||
"resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz",
|
||||
"integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==",
|
||||
"version": "2.88.2",
|
||||
"resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
|
||||
"integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
|
||||
"requires": {
|
||||
"aws-sign2": "~0.7.0",
|
||||
"aws4": "^1.6.0",
|
||||
"aws4": "^1.8.0",
|
||||
"caseless": "~0.12.0",
|
||||
"combined-stream": "~1.0.5",
|
||||
"extend": "~3.0.1",
|
||||
"combined-stream": "~1.0.6",
|
||||
"extend": "~3.0.2",
|
||||
"forever-agent": "~0.6.1",
|
||||
"form-data": "~2.3.1",
|
||||
"har-validator": "~5.0.3",
|
||||
"form-data": "~2.3.2",
|
||||
"har-validator": "~5.1.3",
|
||||
"http-signature": "~1.2.0",
|
||||
"is-typedarray": "~1.0.0",
|
||||
"isstream": "~0.1.2",
|
||||
"json-stringify-safe": "~5.0.1",
|
||||
"mime-types": "~2.1.17",
|
||||
"oauth-sign": "~0.8.2",
|
||||
"mime-types": "~2.1.19",
|
||||
"oauth-sign": "~0.9.0",
|
||||
"performance-now": "^2.1.0",
|
||||
"qs": "~6.5.1",
|
||||
"safe-buffer": "^5.1.1",
|
||||
"tough-cookie": "~2.3.3",
|
||||
"qs": "~6.5.2",
|
||||
"safe-buffer": "^5.1.2",
|
||||
"tough-cookie": "~2.5.0",
|
||||
"tunnel-agent": "^0.6.0",
|
||||
"uuid": "^3.1.0"
|
||||
"uuid": "^3.3.2"
|
||||
}
|
||||
},
|
||||
"rimraf": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
|
||||
"integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
|
||||
"requires": {
|
||||
"glob": "^7.0.5"
|
||||
"glob": "^7.1.3"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
|
||||
"integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
|
||||
"integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8="
|
||||
"version": "7.3.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
|
||||
"integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ=="
|
||||
},
|
||||
"set-blocking": {
|
||||
"version": "2.0.0",
|
||||
@ -568,14 +560,14 @@
|
||||
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
|
||||
},
|
||||
"signal-exit": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
|
||||
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
|
||||
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA=="
|
||||
},
|
||||
"sshpk": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz",
|
||||
"integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=",
|
||||
"version": "1.16.1",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
|
||||
"integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
|
||||
"requires": {
|
||||
"asn1": "~0.2.3",
|
||||
"assert-plus": "^1.0.0",
|
||||
@ -584,6 +576,7 @@
|
||||
"ecc-jsbn": "~0.1.1",
|
||||
"getpass": "^0.1.1",
|
||||
"jsbn": "~0.1.0",
|
||||
"safer-buffer": "^2.0.2",
|
||||
"tweetnacl": "~0.14.0"
|
||||
}
|
||||
},
|
||||
@ -598,9 +591,9 @@
|
||||
}
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
||||
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||
"requires": {
|
||||
"safe-buffer": "~5.1.0"
|
||||
}
|
||||
@ -614,34 +607,25 @@
|
||||
}
|
||||
},
|
||||
"tar": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz",
|
||||
"integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==",
|
||||
"version": "6.0.5",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-6.0.5.tgz",
|
||||
"integrity": "sha512-0b4HOimQHj9nXNEAA7zWwMM91Zhhba3pspja6sQbgTpynOJf+bkjBnfybNYzbpLbnwXnbyB4LOREvlyXLkCHSg==",
|
||||
"requires": {
|
||||
"block-stream": "*",
|
||||
"fstream": "^1.0.12",
|
||||
"inherits": "2"
|
||||
},
|
||||
"dependencies": {
|
||||
"fstream": {
|
||||
"version": "1.0.12",
|
||||
"resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
|
||||
"integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.2",
|
||||
"inherits": "~2.0.0",
|
||||
"mkdirp": ">=0.5 0",
|
||||
"rimraf": "2"
|
||||
}
|
||||
}
|
||||
"chownr": "^2.0.0",
|
||||
"fs-minipass": "^2.0.0",
|
||||
"minipass": "^3.0.0",
|
||||
"minizlib": "^2.1.1",
|
||||
"mkdirp": "^1.0.3",
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "2.3.4",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz",
|
||||
"integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==",
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
|
||||
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
|
||||
"requires": {
|
||||
"punycode": "^1.4.1"
|
||||
"psl": "^1.1.28",
|
||||
"punycode": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"tunnel-agent": {
|
||||
@ -655,8 +639,15 @@
|
||||
"tweetnacl": {
|
||||
"version": "0.14.5",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
|
||||
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
|
||||
"optional": true
|
||||
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
|
||||
},
|
||||
"uri-js": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz",
|
||||
"integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==",
|
||||
"requires": {
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
@ -664,9 +655,9 @@
|
||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz",
|
||||
"integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA=="
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
|
||||
},
|
||||
"verror": {
|
||||
"version": "1.10.0",
|
||||
@ -679,25 +670,30 @@
|
||||
}
|
||||
},
|
||||
"which": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz",
|
||||
"integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==",
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"requires": {
|
||||
"isexe": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"wide-align": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz",
|
||||
"integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==",
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
|
||||
"integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
|
||||
"requires": {
|
||||
"string-width": "^1.0.2"
|
||||
"string-width": "^1.0.2 || 2"
|
||||
}
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||
},
|
||||
"yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"bindings": "1.2.1",
|
||||
"node-gyp": "^3.5.0",
|
||||
"nan": "^2.14.0"
|
||||
"nan": "^2.14.0",
|
||||
"node-gyp": "^7.1.2"
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,25 +26,30 @@ extern "C" bool Neon_Call_IsConstruct(v8::FunctionCallbackInfo<v8::Value> *info)
|
||||
return info->IsConstructCall();
|
||||
}
|
||||
|
||||
extern "C" void Neon_Call_This(v8::FunctionCallbackInfo<v8::Value> *info, v8::Local<v8::Object> *out) {
|
||||
extern "C" void Neon_Call_This(v8::Isolate *isolate, v8::FunctionCallbackInfo<v8::Value> *info, v8::Local<v8::Object> *out) {
|
||||
*out = info->This();
|
||||
}
|
||||
|
||||
extern "C" void Neon_Call_Data(v8::FunctionCallbackInfo<v8::Value> *info, v8::Local<v8::Value> *out) {
|
||||
extern "C" void Neon_Call_Data(v8::Isolate *isolate, v8::FunctionCallbackInfo<v8::Value> *info, void **out) {
|
||||
/*
|
||||
printf("Call_Data: v8 info = %p\n", *(void **)info);
|
||||
dump((void *)info, 3);
|
||||
printf("Call_Data: v8 info implicit:\n");
|
||||
dump_implicit((void *)info);
|
||||
*/
|
||||
*out = info->Data();
|
||||
|
||||
// Call data is stored wrapped in a v8::External by Neon_Fun_New et al, so we need to unwrap it before handing it back to Rust.
|
||||
v8::Local<v8::Value> external = info->Data();
|
||||
if (external->IsExternal()) {
|
||||
*out = external.As<v8::External>()->Value();
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" int32_t Neon_Call_Length(v8::FunctionCallbackInfo<v8::Value> *info) {
|
||||
extern "C" int32_t Neon_Call_Length(v8::Isolate *isolate, v8::FunctionCallbackInfo<v8::Value> *info) {
|
||||
return info->Length();
|
||||
}
|
||||
|
||||
extern "C" void Neon_Call_Get(v8::FunctionCallbackInfo<v8::Value> *info, int32_t i, v8::Local<v8::Value> *out) {
|
||||
extern "C" void Neon_Call_Get(v8::Isolate *isolate, v8::FunctionCallbackInfo<v8::Value> *info, int32_t i, v8::Local<v8::Value> *out) {
|
||||
*out = (*info)[i];
|
||||
}
|
||||
|
||||
@ -178,12 +183,12 @@ extern "C" bool Neon_Convert_ToString(v8::Local<v8::String> *out, v8::Isolate *i
|
||||
return maybe.ToLocal(out);
|
||||
}
|
||||
|
||||
extern "C" bool Neon_Convert_ToObject(v8::Local<v8::Object> *out, v8::Local<v8::Value> *value) {
|
||||
Nan::MaybeLocal<v8::Object> maybe = Nan::To<v8::Object>(*value);
|
||||
extern "C" bool Neon_Convert_ToObject(v8::Local<v8::Object> *out, v8::Isolate *isolate, v8::Local<v8::Value> value) {
|
||||
Nan::MaybeLocal<v8::Object> maybe = Nan::To<v8::Object>(value);
|
||||
return maybe.ToLocal(out);
|
||||
}
|
||||
|
||||
extern "C" bool Neon_Buffer_New(v8::Local<v8::Object> *out, uint32_t size) {
|
||||
extern "C" bool Neon_Buffer_New(v8::Isolate *isolate, v8::Local<v8::Object> *out, uint32_t size) {
|
||||
Nan::MaybeLocal<v8::Object> maybe = Nan::NewBuffer(size);
|
||||
if (!maybe.ToLocal(out)) {
|
||||
return false;
|
||||
@ -194,12 +199,12 @@ extern "C" bool Neon_Buffer_New(v8::Local<v8::Object> *out, uint32_t size) {
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" bool Neon_Buffer_Uninitialized(v8::Local<v8::Object> *out, uint32_t size) {
|
||||
extern "C" bool Neon_Buffer_Uninitialized(v8::Isolate *isolate, v8::Local<v8::Object> *out, uint32_t size) {
|
||||
Nan::MaybeLocal<v8::Object> maybe = Nan::NewBuffer(size);
|
||||
return maybe.ToLocal(out);
|
||||
}
|
||||
|
||||
extern "C" size_t Neon_Buffer_Data(void **base_out, v8::Local<v8::Object> obj) {
|
||||
extern "C" size_t Neon_Buffer_Data(v8::Isolate *isolate, void **base_out, v8::Local<v8::Object> obj) {
|
||||
*base_out = node::Buffer::Data(obj);
|
||||
|
||||
return node::Buffer::Length(obj);
|
||||
@ -214,7 +219,7 @@ extern "C" bool Neon_ArrayBuffer_New(v8::Local<v8::ArrayBuffer> *out, v8::Isolat
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" size_t Neon_ArrayBuffer_Data(void **base_out, v8::Local<v8::ArrayBuffer> buffer) {
|
||||
extern "C" size_t Neon_ArrayBuffer_Data(v8::Isolate *isolate, void **base_out, v8::Local<v8::ArrayBuffer> buffer) {
|
||||
v8::ArrayBuffer::Contents contents = buffer->GetContents();
|
||||
*base_out = contents.Data();
|
||||
|
||||
@ -226,7 +231,7 @@ extern "C" bool Neon_Tag_IsArrayBuffer(v8::Isolate *isolate, v8::Local<v8::Value
|
||||
return value->IsArrayBuffer();
|
||||
}
|
||||
|
||||
extern "C" void Neon_Scope_Escape(v8::Local<v8::Value> *out, Nan::EscapableHandleScope *scope, v8::Local<v8::Value> value) {
|
||||
extern "C" void Neon_Scope_Escape(v8::Isolate *isolate, v8::Local<v8::Value> *out, Nan::EscapableHandleScope *scope, v8::Local<v8::Value> value) {
|
||||
*out = scope->Escape(value);
|
||||
}
|
||||
|
||||
@ -327,21 +332,21 @@ extern "C" void Neon_Class_SetClassMap(v8::Isolate *isolate, void *map, Neon_Dro
|
||||
neon::ClassMapHolder *holder = new neon::ClassMapHolder(map, drop_map);
|
||||
isolate->SetData(NEON_ISOLATE_SLOT, holder);
|
||||
// ISSUE(#77): When workers land in node, this will need to be generalized to a per-worker version.
|
||||
node::AtExit(cleanup_class_map, holder);
|
||||
node::AtExit(node::GetCurrentEnvironment(isolate->GetCurrentContext()), cleanup_class_map, holder);
|
||||
}
|
||||
|
||||
extern "C" void *Neon_Class_GetCallKernel(v8::Local<v8::External> wrapper) {
|
||||
neon::ClassMetadata *metadata = static_cast<neon::ClassMetadata *>(wrapper->Value());
|
||||
extern "C" void *Neon_Class_GetCallKernel(void *wrapper) {
|
||||
neon::ClassMetadata *metadata = static_cast<neon::ClassMetadata *>(wrapper);
|
||||
return metadata->GetCallKernel();
|
||||
}
|
||||
|
||||
extern "C" void *Neon_Class_GetConstructKernel(v8::Local<v8::External> wrapper) {
|
||||
neon::ClassMetadata *metadata = static_cast<neon::ClassMetadata *>(wrapper->Value());
|
||||
extern "C" void *Neon_Class_GetConstructKernel(void *wrapper) {
|
||||
neon::ClassMetadata *metadata = static_cast<neon::ClassMetadata *>(wrapper);
|
||||
return metadata->GetConstructKernel();
|
||||
}
|
||||
|
||||
extern "C" void *Neon_Class_GetAllocateKernel(v8::Local<v8::External> wrapper) {
|
||||
neon::BaseClassMetadata *metadata = static_cast<neon::BaseClassMetadata *>(wrapper->Value());
|
||||
extern "C" void *Neon_Class_GetAllocateKernel(void *wrapper) {
|
||||
neon::BaseClassMetadata *metadata = static_cast<neon::BaseClassMetadata *>(wrapper);
|
||||
return metadata->GetAllocateKernel();
|
||||
}
|
||||
|
||||
@ -433,8 +438,8 @@ extern "C" bool Neon_Fun_New(v8::Local<v8::Function> *out, v8::Isolate *isolate,
|
||||
return maybe_result.ToLocal(out);
|
||||
}
|
||||
|
||||
extern "C" void *Neon_Fun_GetDynamicCallback(v8::Local<v8::External> data) {
|
||||
return data->Value();
|
||||
extern "C" void *Neon_Fun_GetDynamicCallback(v8::Isolate *isolate, void *data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
extern "C" bool Neon_Fun_Call(v8::Local<v8::Value> *out, v8::Isolate *isolate, v8::Local<v8::Function> fun, v8::Local<v8::Value> self, int32_t argc, v8::Local<v8::Value> argv[]) {
|
||||
@ -536,3 +541,26 @@ extern "C" void Neon_EventHandler_Delete(void * thread_safe_cb) {
|
||||
neon::EventHandler *cb = static_cast<neon::EventHandler*>(thread_safe_cb);
|
||||
cb->close();
|
||||
}
|
||||
|
||||
extern "C" try_catch_control_t Neon_TryCatch_With(Neon_TryCatchGlue glue_fn, void *rust_thunk, void *cx, void *ok, v8::Local<v8::Value> *err, void **unwind_value) {
|
||||
Nan::TryCatch try_catch;
|
||||
|
||||
try_catch_control_t ctrl = glue_fn(rust_thunk, cx, ok, unwind_value);
|
||||
|
||||
if (ctrl == CONTROL_PANICKED) {
|
||||
return CONTROL_PANICKED;
|
||||
}
|
||||
|
||||
if (!try_catch.HasCaught()) {
|
||||
// It's possible, if unlikely, that a Neon user might return `Err(Throw)` even
|
||||
// though the VM is not actually in a throwing state. In this case we return
|
||||
// `CONTROL_UNEXPECTED_ERR` to signal that Rust should panic.
|
||||
if (ctrl == CONTROL_THREW) {
|
||||
return CONTROL_UNEXPECTED_ERR;
|
||||
}
|
||||
return CONTROL_RETURNED;
|
||||
} else {
|
||||
*err = try_catch.Exception();
|
||||
return CONTROL_THREW;
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,22 +5,30 @@
|
||||
#include <stdint.h>
|
||||
#include <v8.h>
|
||||
|
||||
// corresponding Rust struct `CCallback` defined in fun.rs
|
||||
// corresponding Rust struct `CCallback` defined in lib.rs
|
||||
typedef struct {
|
||||
void* static_callback;
|
||||
void* dynamic_callback;
|
||||
} callback_t;
|
||||
|
||||
// corresponding Rust enum `TryCatchControl` defined in lib.rs
|
||||
typedef enum : uint8_t {
|
||||
CONTROL_RETURNED = 0,
|
||||
CONTROL_THREW = 1,
|
||||
CONTROL_PANICKED = 2,
|
||||
CONTROL_UNEXPECTED_ERR = 3
|
||||
} try_catch_control_t;
|
||||
|
||||
extern "C" {
|
||||
|
||||
void Neon_Call_SetReturn(v8::FunctionCallbackInfo<v8::Value> *info, v8::Local<v8::Value> value);
|
||||
void *Neon_Call_GetIsolate(v8::FunctionCallbackInfo<v8::Value> *info);
|
||||
void *Neon_Call_CurrentIsolate();
|
||||
bool Neon_Call_IsConstruct(v8::FunctionCallbackInfo<v8::Value> *info);
|
||||
void Neon_Call_This(v8::FunctionCallbackInfo<v8::Value> *info, v8::Local<v8::Object> *out);
|
||||
void Neon_Call_Data(v8::FunctionCallbackInfo<v8::Value> *info, v8::Local<v8::Value> *out);
|
||||
int32_t Neon_Call_Length(v8::FunctionCallbackInfo<v8::Value> *info);
|
||||
void Neon_Call_Get(v8::FunctionCallbackInfo<v8::Value> *info, int32_t i, v8::Local<v8::Value> *out);
|
||||
void Neon_Call_This(v8::Isolate *isolate, v8::FunctionCallbackInfo<v8::Value> *info, v8::Local<v8::Object> *out);
|
||||
void Neon_Call_Data(v8::Isolate *isolate, v8::FunctionCallbackInfo<v8::Value> *info, void **out);
|
||||
int32_t Neon_Call_Length(v8::Isolate *isolate, v8::FunctionCallbackInfo<v8::Value> *info);
|
||||
void Neon_Call_Get(v8::Isolate *isolate, v8::FunctionCallbackInfo<v8::Value> *info, int32_t i, v8::Local<v8::Value> *out);
|
||||
|
||||
void Neon_Primitive_Number(v8::Local<v8::Number> *out, v8::Isolate *isolate, double value);
|
||||
void Neon_Primitive_Undefined(v8::Local<v8::Primitive> *out, v8::Isolate *isolate);
|
||||
@ -47,20 +55,20 @@ extern "C" {
|
||||
size_t Neon_String_Data(char *out, size_t len, v8::Local<v8::Value> str);
|
||||
|
||||
bool Neon_Convert_ToString(v8::Local<v8::String> *out, v8::Isolate *isolate, v8::Local<v8::Value> value);
|
||||
bool Neon_Convert_ToObject(v8::Local<v8::Object> *out, v8::Local<v8::Value> *value);
|
||||
bool Neon_Convert_ToObject(v8::Local<v8::Object> *out, v8::Isolate *isolate, v8::Local<v8::Value> value);
|
||||
|
||||
bool Neon_Buffer_New(v8::Local<v8::Object> *out, uint32_t size);
|
||||
size_t Neon_Buffer_Data(void **base_out, v8::Local<v8::Object> obj);
|
||||
bool Neon_Buffer_New(v8::Isolate *isolate, v8::Local<v8::Object> *out, uint32_t size);
|
||||
size_t Neon_Buffer_Data(v8::Isolate *isolate, void **base_out, v8::Local<v8::Object> obj);
|
||||
|
||||
bool Neon_ArrayBuffer_New(v8::Local<v8::ArrayBuffer> *out, v8::Isolate *isolate, uint32_t size);
|
||||
bool Neon_ArrayBuffer_Uninitialized(v8::Local<v8::ArrayBuffer> *out, v8::Isolate *isolate, uint32_t size);
|
||||
size_t Neon_ArrayBuffer_Data(void **base_out, v8::Local<v8::ArrayBuffer> buffer);
|
||||
size_t Neon_ArrayBuffer_Data(v8::Isolate *isolate, void **base_out, v8::Local<v8::ArrayBuffer> buffer);
|
||||
|
||||
typedef void(*Neon_ChainedScopeCallback)(void *, void *, void *, void *);
|
||||
typedef void(*Neon_NestedScopeCallback)(void *, void *, void *);
|
||||
typedef void(*Neon_RootScopeCallback)(void *, void *, void *);
|
||||
|
||||
void Neon_Scope_Escape(v8::Local<v8::Value> *out, Nan::EscapableHandleScope *scope, v8::Local<v8::Value> value);
|
||||
void Neon_Scope_Escape(v8::Isolate *isolate, v8::Local<v8::Value> *out, Nan::EscapableHandleScope *scope, v8::Local<v8::Value> value);
|
||||
void Neon_Scope_Nested(void *out, void *closure, Neon_NestedScopeCallback callback, void *realm);
|
||||
void Neon_Scope_Chained(void *out, void *closure, Neon_ChainedScopeCallback callback, void *parent_scope);
|
||||
void Neon_Scope_Enter(v8::HandleScope *scope, v8::Isolate *isolate);
|
||||
@ -75,7 +83,7 @@ extern "C" {
|
||||
|
||||
bool Neon_Fun_New(v8::Local<v8::Function> *out, v8::Isolate *isolate, callback_t callback);
|
||||
bool Neon_Fun_Template_New(v8::Local<v8::FunctionTemplate> *out, v8::Isolate *isolate, callback_t callback);
|
||||
void *Neon_Fun_GetDynamicCallback(v8::Local<v8::External> obj);
|
||||
void *Neon_Fun_GetDynamicCallback(v8::Isolate *isolate, void *obj);
|
||||
bool Neon_Fun_Call(v8::Local<v8::Value> *out, v8::Isolate *isolate, v8::Local<v8::Function> fun, v8::Local<v8::Value> self, int32_t argc, v8::Local<v8::Value> argv[]);
|
||||
bool Neon_Fun_Construct(v8::Local<v8::Object> *out, v8::Isolate *isolate, v8::Local<v8::Function> fun, int32_t argc, v8::Local<v8::Value> argv[]);
|
||||
|
||||
@ -95,9 +103,9 @@ extern "C" {
|
||||
callback_t call,
|
||||
Neon_DropCallback drop);
|
||||
// FIXME: get rid of all the "kernel" nomenclature
|
||||
void *Neon_Class_GetCallKernel(v8::Local<v8::External> wrapper);
|
||||
void *Neon_Class_GetConstructKernel(v8::Local<v8::External> wrapper);
|
||||
void *Neon_Class_GetAllocateKernel(v8::Local<v8::External> wrapper);
|
||||
void *Neon_Class_GetCallKernel(void *wrapper);
|
||||
void *Neon_Class_GetConstructKernel(void *wrapper);
|
||||
void *Neon_Class_GetAllocateKernel(void *wrapper);
|
||||
bool Neon_Class_Constructor(v8::Local<v8::Function> *out, v8::Local<v8::FunctionTemplate> ft);
|
||||
bool Neon_Class_HasInstance(void *metadata, v8::Local<v8::Value> v);
|
||||
bool Neon_Class_SetName(v8::Isolate *isolate, void *metadata, const char *name, uint32_t byte_length);
|
||||
@ -130,7 +138,7 @@ extern "C" {
|
||||
bool Neon_Mem_SameHandle(v8::Local<v8::Value> v1, v8::Local<v8::Value> v2);
|
||||
|
||||
typedef void* (*Neon_TaskPerformCallback)(void *);
|
||||
typedef void (*Neon_TaskCompleteCallback)(void *, v8::Local<v8::Value> *out);
|
||||
typedef void (*Neon_TaskCompleteCallback)(void *, void *, v8::Local<v8::Value> *out);
|
||||
|
||||
void Neon_Task_Schedule(void *task, Neon_TaskPerformCallback perform, Neon_TaskCompleteCallback complete, v8::Local<v8::Function> callback);
|
||||
|
||||
@ -139,6 +147,20 @@ extern "C" {
|
||||
void* Neon_EventHandler_New(v8::Isolate *isolate, v8::Local<v8::Value> self, v8::Local<v8::Function> callback);
|
||||
void Neon_EventHandler_Schedule(void* thread_safe_cb, void* rust_callback, Neon_EventHandler handler);
|
||||
void Neon_EventHandler_Delete(void* thread_safe_cb);
|
||||
|
||||
// The `ok` out-parameter can be assumed to be initialized if and only if this function
|
||||
// returns `CONTROL_RETURNED`.
|
||||
// The `unwind_value` out-parameter can be assumed to be initialized if and only if this
|
||||
// function returns `CONTROL_PANICKED`.
|
||||
typedef try_catch_control_t (*Neon_TryCatchGlue)(void *rust_thunk, void *cx, void *ok, void **unwind_value);
|
||||
|
||||
// The `ok` out-parameter can be assumed to be initialized if and only if this function
|
||||
// returns `CONTROL_RETURNED`.
|
||||
// The `err` out-parameter can be assumed to be initialized if and only if this function
|
||||
// returns `CONTROL_THREW`.
|
||||
// The `unwind_value` out-parameter can be assumed to be initialized if and only if this
|
||||
// function returns `CONTROL_PANICKED`.
|
||||
try_catch_control_t Neon_TryCatch_With(Neon_TryCatchGlue glue, void *rust_thunk, void *cx, void *ok, v8::Local<v8::Value> *err, void **unwind_value);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -25,6 +25,12 @@ namespace neon {
|
||||
context_.Reset(isolate, isolate->GetCurrentContext());
|
||||
}
|
||||
|
||||
~EventHandler() {
|
||||
self_.Reset();
|
||||
callback_.Reset();
|
||||
context_.Reset();
|
||||
}
|
||||
|
||||
void schedule(void *rust_callback, Neon_EventHandler handler) {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
@ -62,7 +62,7 @@ public:
|
||||
|
||||
v8::Local<v8::Value> completion;
|
||||
|
||||
complete_(result_, &completion);
|
||||
complete_(rust_task_, result_, &completion);
|
||||
|
||||
if (trycatch.HasCaught()) {
|
||||
argv[0] = trycatch.Exception();
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
use std::os::raw::c_void;
|
||||
use std::mem;
|
||||
use std::os::raw::c_void;
|
||||
use std::ptr::null_mut;
|
||||
|
||||
/// A V8 `Local` handle.
|
||||
@ -9,14 +9,14 @@ use std::ptr::null_mut;
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Local {
|
||||
pub handle: *mut c_void
|
||||
pub handle: *mut c_void,
|
||||
}
|
||||
|
||||
/// Represents the details of how the function was called from JavaScript.
|
||||
///
|
||||
/// It contains the arguments used to invoke the function, the isolate reference, the `this` object
|
||||
/// the function is bound to and a mechanism to return a value to the caller.
|
||||
pub type FunctionCallbackInfo = c_void;
|
||||
pub type FunctionCallbackInfo = *const c_void;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
@ -38,11 +38,19 @@ const HANDLE_SCOPE_SIZE: usize = 24;
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct HandleScope {
|
||||
pub align_to_pointer: [*mut c_void; 0],
|
||||
pub fields: [u8; HANDLE_SCOPE_SIZE]
|
||||
pub fields: [u8; HANDLE_SCOPE_SIZE],
|
||||
}
|
||||
|
||||
impl HandleScope {
|
||||
pub fn new() -> HandleScope { unsafe { mem::zeroed() } }
|
||||
pub fn new() -> HandleScope {
|
||||
unsafe { mem::zeroed() }
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for HandleScope {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
const ESCAPABLE_HANDLE_SCOPE_SIZE: usize = 32;
|
||||
@ -56,73 +64,131 @@ const ESCAPABLE_HANDLE_SCOPE_SIZE: usize = 32;
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct EscapableHandleScope {
|
||||
pub align_to_pointer: [*mut c_void; 0],
|
||||
pub fields: [u8; ESCAPABLE_HANDLE_SCOPE_SIZE]
|
||||
pub fields: [u8; ESCAPABLE_HANDLE_SCOPE_SIZE],
|
||||
}
|
||||
|
||||
impl EscapableHandleScope {
|
||||
pub fn new() -> EscapableHandleScope { unsafe { mem::zeroed() } }
|
||||
pub fn new() -> EscapableHandleScope {
|
||||
unsafe { mem::zeroed() }
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for EscapableHandleScope {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct CCallback {
|
||||
pub static_callback: *mut c_void,
|
||||
pub dynamic_callback: *mut c_void
|
||||
pub dynamic_callback: *mut c_void,
|
||||
}
|
||||
|
||||
impl Default for CCallback {
|
||||
fn default() -> Self {
|
||||
CCallback {
|
||||
static_callback: null_mut(),
|
||||
dynamic_callback: null_mut()
|
||||
dynamic_callback: null_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
pub enum TryCatchControl {
|
||||
Returned = 0,
|
||||
Threw = 1,
|
||||
Panicked = 2,
|
||||
UnexpectedErr = 3,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct InheritedHandleScope;
|
||||
|
||||
/// A Rust extern "glue function" for C++ to invoke a Rust closure with a `TryCatch`
|
||||
/// live on the stack.
|
||||
/// The `result` argument can be assumed to be initialized if and only if the glue
|
||||
/// function returns `TryCatchControl::Returned`.
|
||||
/// The `unwind_value` argument can be assumed to be initialized if and only if the
|
||||
/// glue function returns `TryCatchControl::Panicked`.
|
||||
pub type TryCatchGlue = extern "C" fn(
|
||||
rust_thunk: *mut c_void,
|
||||
cx: *mut c_void,
|
||||
result: *mut c_void,
|
||||
unwind_value: *mut *mut c_void,
|
||||
) -> TryCatchControl;
|
||||
|
||||
extern "C" {
|
||||
|
||||
pub fn Neon_Array_New(out: &mut Local, isolate: Isolate, length: u32);
|
||||
pub fn Neon_Array_Length(isolate: Isolate, array: Local) -> u32;
|
||||
|
||||
pub fn Neon_ArrayBuffer_New(out: &mut Local, isolate: Isolate, size: u32) -> bool;
|
||||
pub fn Neon_ArrayBuffer_Data<'a, 'b>(base_out: &'a mut *mut c_void, obj: Local) -> usize;
|
||||
pub fn Neon_ArrayBuffer_Data<'a, 'b>(
|
||||
isolate: Isolate,
|
||||
base_out: &'a mut *mut c_void,
|
||||
obj: Local,
|
||||
) -> usize;
|
||||
|
||||
pub fn Neon_Buffer_New(out: &mut Local, size: u32) -> bool;
|
||||
pub fn Neon_Buffer_Uninitialized(out: &mut Local, size: u32) -> bool;
|
||||
pub fn Neon_Buffer_Data<'a, 'b>(base_out: &'a mut *mut c_void, obj: Local) -> usize;
|
||||
pub fn Neon_Buffer_New(isolate: Isolate, out: &mut Local, size: u32) -> bool;
|
||||
pub fn Neon_Buffer_Uninitialized(isolate: Isolate, out: &mut Local, size: u32) -> bool;
|
||||
pub fn Neon_Buffer_Data<'a, 'b>(
|
||||
isolate: Isolate,
|
||||
base_out: &'a mut *mut c_void,
|
||||
obj: Local,
|
||||
) -> usize;
|
||||
|
||||
pub fn Neon_Call_SetReturn(info: &FunctionCallbackInfo, value: Local);
|
||||
pub fn Neon_Call_GetIsolate(info: &FunctionCallbackInfo) -> Isolate;
|
||||
pub fn Neon_Call_SetReturn(info: FunctionCallbackInfo, value: Local);
|
||||
pub fn Neon_Call_GetIsolate(info: FunctionCallbackInfo) -> Isolate;
|
||||
pub fn Neon_Call_CurrentIsolate() -> Isolate;
|
||||
pub fn Neon_Call_IsConstruct(info: &FunctionCallbackInfo) -> bool;
|
||||
pub fn Neon_Call_This(info: &FunctionCallbackInfo, out: &mut Local);
|
||||
pub fn Neon_Call_Data(info: &FunctionCallbackInfo, out: &mut Local);
|
||||
pub fn Neon_Call_Length(info: &FunctionCallbackInfo) -> i32;
|
||||
pub fn Neon_Call_Get(info: &FunctionCallbackInfo, i: i32, out: &mut Local);
|
||||
pub fn Neon_Call_IsConstruct(info: FunctionCallbackInfo) -> bool;
|
||||
pub fn Neon_Call_This(isolate: Isolate, info: FunctionCallbackInfo, out: &mut Local);
|
||||
pub fn Neon_Call_Data(isolate: Isolate, info: FunctionCallbackInfo, out: &mut *mut c_void);
|
||||
pub fn Neon_Call_Length(isolate: Isolate, info: FunctionCallbackInfo) -> i32;
|
||||
pub fn Neon_Call_Get(isolate: Isolate, info: FunctionCallbackInfo, i: i32, out: &mut Local);
|
||||
|
||||
pub fn Neon_Class_GetClassMap(isolate: Isolate) -> *mut c_void;
|
||||
pub fn Neon_Class_SetClassMap(isolate: Isolate, map: *mut c_void, free_map: *mut c_void);
|
||||
pub fn Neon_Class_CreateBase(isolate: Isolate,
|
||||
allocate: CCallback,
|
||||
construct: CCallback,
|
||||
call: CCallback,
|
||||
drop: extern "C" fn(*mut c_void)) -> *mut c_void;
|
||||
pub fn Neon_Class_GetName<'a>(base_out: &'a mut *mut u8, isolate: Isolate, metadata: *const c_void) -> usize;
|
||||
pub fn Neon_Class_SetName(isolate: Isolate, metadata: *mut c_void, name: *const u8, byte_length: u32) -> bool;
|
||||
pub fn Neon_Class_CreateBase(
|
||||
isolate: Isolate,
|
||||
allocate: CCallback,
|
||||
construct: CCallback,
|
||||
call: CCallback,
|
||||
drop: extern "C" fn(*mut c_void),
|
||||
) -> *mut c_void;
|
||||
pub fn Neon_Class_GetName<'a>(
|
||||
base_out: &'a mut *mut u8,
|
||||
isolate: Isolate,
|
||||
metadata: *const c_void,
|
||||
) -> usize;
|
||||
pub fn Neon_Class_SetName(
|
||||
isolate: Isolate,
|
||||
metadata: *mut c_void,
|
||||
name: *const u8,
|
||||
byte_length: u32,
|
||||
) -> bool;
|
||||
pub fn Neon_Class_ThrowCallError(isolate: Isolate, metadata: *mut c_void);
|
||||
pub fn Neon_Class_ThrowThisError(isolate: Isolate, metadata: *mut c_void);
|
||||
pub fn Neon_Class_AddMethod(isolate: Isolate, metadata: *mut c_void, name: *const u8, byte_length: u32, method: Local) -> bool;
|
||||
pub fn Neon_Class_MetadataToConstructor(out: &mut Local, isolate: Isolate, metadata: *mut c_void) -> bool;
|
||||
pub fn Neon_Class_GetAllocateKernel(obj: Local) -> *mut c_void;
|
||||
pub fn Neon_Class_GetConstructKernel(obj: Local) -> *mut c_void;
|
||||
pub fn Neon_Class_GetCallKernel(obj: Local) -> *mut c_void;
|
||||
pub fn Neon_Class_AddMethod(
|
||||
isolate: Isolate,
|
||||
metadata: *mut c_void,
|
||||
name: *const u8,
|
||||
byte_length: u32,
|
||||
method: Local,
|
||||
) -> bool;
|
||||
pub fn Neon_Class_MetadataToConstructor(
|
||||
out: &mut Local,
|
||||
isolate: Isolate,
|
||||
metadata: *mut c_void,
|
||||
) -> bool;
|
||||
pub fn Neon_Class_GetAllocateKernel(data: *mut c_void) -> *mut c_void;
|
||||
pub fn Neon_Class_GetConstructKernel(data: *mut c_void) -> *mut c_void;
|
||||
pub fn Neon_Class_GetCallKernel(data: *mut c_void) -> *mut c_void;
|
||||
pub fn Neon_Class_Constructor(out: &mut Local, ft: Local) -> bool;
|
||||
pub fn Neon_Class_HasInstance(metadata: *mut c_void, v: Local) -> bool;
|
||||
pub fn Neon_Class_GetInstanceInternals(obj: Local) -> *mut c_void;
|
||||
|
||||
pub fn Neon_Convert_ToObject(out: &mut Local, value: &Local) -> bool;
|
||||
pub fn Neon_Convert_ToObject(out: &mut Local, isolate: Isolate, value: Local) -> bool;
|
||||
pub fn Neon_Convert_ToString(out: &mut Local, isolate: Isolate, value: Local) -> bool;
|
||||
|
||||
pub fn Neon_Error_Throw(val: Local);
|
||||
@ -133,23 +199,53 @@ extern "C" {
|
||||
|
||||
pub fn Neon_Fun_New(out: &mut Local, isolate: Isolate, callback: CCallback) -> bool;
|
||||
pub fn Neon_Fun_Template_New(out: &mut Local, isolate: Isolate, callback: CCallback) -> bool;
|
||||
pub fn Neon_Fun_GetDynamicCallback(obj: Local) -> *mut c_void;
|
||||
pub fn Neon_Fun_Call(out: &mut Local, isolate: Isolate, fun: Local, this: Local, argc: i32, argv: *mut c_void) -> bool;
|
||||
pub fn Neon_Fun_Construct(out: &mut Local, isolate: Isolate, fun: Local, argc: i32, argv: *mut c_void) -> bool;
|
||||
pub fn Neon_Fun_GetDynamicCallback(isolate: Isolate, data: *mut c_void) -> *mut c_void;
|
||||
pub fn Neon_Fun_Call(
|
||||
out: &mut Local,
|
||||
isolate: Isolate,
|
||||
fun: Local,
|
||||
this: Local,
|
||||
argc: i32,
|
||||
argv: *mut c_void,
|
||||
) -> bool;
|
||||
pub fn Neon_Fun_Construct(
|
||||
out: &mut Local,
|
||||
isolate: Isolate,
|
||||
fun: Local,
|
||||
argc: i32,
|
||||
argv: *mut c_void,
|
||||
) -> bool;
|
||||
|
||||
pub fn Neon_Mem_SameHandle(h1: Local, h2: Local) -> bool;
|
||||
|
||||
pub fn Neon_Module_ExecKernel(kernel: *mut c_void, callback: extern fn(*mut c_void, *mut c_void, *mut c_void, *mut c_void), exports: Local, scope: *mut c_void, vm: *mut c_void);
|
||||
pub fn Neon_Module_ExecKernel(
|
||||
kernel: *mut c_void,
|
||||
callback: extern "C" fn(*mut c_void, *mut c_void, *mut c_void, *mut c_void),
|
||||
exports: Local,
|
||||
scope: *mut c_void,
|
||||
vm: *mut c_void,
|
||||
);
|
||||
pub fn Neon_Module_ExecCallback(callback: CCallback, exports: Local, vm: *mut c_void);
|
||||
pub fn Neon_Module_GetVersion() -> i32;
|
||||
|
||||
pub fn Neon_Object_New(out: &mut Local, isolate: Isolate);
|
||||
pub fn Neon_Object_GetOwnPropertyNames(out: &mut Local, isolate: Isolate, object: Local) -> bool;
|
||||
pub fn Neon_Object_GetOwnPropertyNames(
|
||||
out: &mut Local,
|
||||
isolate: Isolate,
|
||||
object: Local,
|
||||
) -> bool;
|
||||
pub fn Neon_Object_GetIsolate(obj: Local) -> Isolate;
|
||||
pub fn Neon_Object_Get_Index(out: &mut Local, object: Local, index: u32) -> bool;
|
||||
pub fn Neon_Object_Set_Index(out: &mut bool, object: Local, index: u32, val: Local) -> bool;
|
||||
pub fn Neon_Object_Get_String(out: &mut Local, object: Local, key: *const u8, len: i32) -> bool;
|
||||
pub fn Neon_Object_Set_String(out: &mut bool, object: Local, key: *const u8, len: i32, val: Local) -> bool;
|
||||
pub fn Neon_Object_Get_String(out: &mut Local, object: Local, key: *const u8, len: i32)
|
||||
-> bool;
|
||||
pub fn Neon_Object_Set_String(
|
||||
out: &mut bool,
|
||||
object: Local,
|
||||
key: *const u8,
|
||||
len: i32,
|
||||
val: Local,
|
||||
) -> bool;
|
||||
pub fn Neon_Object_Get(out: &mut Local, object: Local, key: Local) -> bool;
|
||||
pub fn Neon_Object_Set(out: &mut bool, object: Local, key: Local, val: Local) -> bool;
|
||||
|
||||
@ -164,9 +260,24 @@ extern "C" {
|
||||
pub fn Neon_Primitive_Number(out: &mut Local, isolate: Isolate, v: f64);
|
||||
pub fn Neon_Primitive_NumberValue(p: Local) -> f64;
|
||||
|
||||
pub fn Neon_Scope_Escape(out: &mut Local, scope: *mut EscapableHandleScope, value: Local);
|
||||
pub fn Neon_Scope_Chained(out: *mut c_void, closure: *mut c_void, callback: extern fn(&mut c_void, *mut c_void, *mut c_void, *mut c_void), parent_scope: *mut c_void);
|
||||
pub fn Neon_Scope_Nested(out: *mut c_void, closure: *mut c_void, callback: extern fn(&mut c_void, *mut c_void, *mut c_void), realm: *mut c_void);
|
||||
pub fn Neon_Scope_Escape(
|
||||
isolate: Isolate,
|
||||
out: &mut Local,
|
||||
scope: *mut EscapableHandleScope,
|
||||
value: Local,
|
||||
);
|
||||
pub fn Neon_Scope_Chained(
|
||||
out: *mut c_void,
|
||||
closure: *mut c_void,
|
||||
callback: extern "C" fn(&mut c_void, *mut c_void, *mut c_void, *mut c_void),
|
||||
parent_scope: *mut c_void,
|
||||
);
|
||||
pub fn Neon_Scope_Nested(
|
||||
out: *mut c_void,
|
||||
closure: *mut c_void,
|
||||
callback: extern "C" fn(&mut c_void, *mut c_void, *mut c_void),
|
||||
realm: *mut c_void,
|
||||
);
|
||||
pub fn Neon_Scope_Enter(scope: &mut HandleScope, isolate: Isolate);
|
||||
pub fn Neon_Scope_Exit(scope: &mut HandleScope);
|
||||
pub fn Neon_Scope_Enter_Escapable(scope: &mut EscapableHandleScope, isolate: Isolate);
|
||||
@ -193,13 +304,32 @@ extern "C" {
|
||||
pub fn Neon_Tag_IsBuffer(isolate: Isolate, obj: Local) -> bool;
|
||||
pub fn Neon_Tag_IsArrayBuffer(isolate: Isolate, obj: Local) -> bool;
|
||||
|
||||
pub fn Neon_Task_Schedule(task: *mut c_void,
|
||||
perform: unsafe extern fn(*mut c_void) -> *mut c_void,
|
||||
complete: unsafe extern fn(*mut c_void, &mut Local),
|
||||
callback: Local);
|
||||
pub fn Neon_Task_Schedule(
|
||||
task: *mut c_void,
|
||||
perform: unsafe extern "C" fn(*mut c_void) -> *mut c_void,
|
||||
complete: unsafe extern "C" fn(*mut c_void, *mut c_void, &mut Local),
|
||||
callback: Local,
|
||||
);
|
||||
|
||||
pub fn Neon_EventHandler_New(isolate: Isolate, this: Local, callback: Local) -> *mut c_void;
|
||||
pub fn Neon_EventHandler_Schedule(thread_safe_cb: *mut c_void, rust_callback: *mut c_void,
|
||||
complete: unsafe extern fn(Local, Local, *mut c_void));
|
||||
pub fn Neon_EventHandler_Schedule(
|
||||
thread_safe_cb: *mut c_void,
|
||||
rust_callback: *mut c_void,
|
||||
complete: unsafe extern "C" fn(Local, Local, *mut c_void),
|
||||
);
|
||||
pub fn Neon_EventHandler_Delete(thread_safe_cb: *mut c_void);
|
||||
|
||||
/// Invokes a Rust closure with a `TryCatch` live on the stack.
|
||||
/// The `result` value can be assumed to be initialized if and only if this function
|
||||
/// does not return `TryCatchControl::Panicked`.
|
||||
/// The `unwind_value` value can be assumed to be initialized if and only if this
|
||||
/// function returns `TryCatchControl::Panicked`.
|
||||
pub fn Neon_TryCatch_With(
|
||||
glue: TryCatchGlue,
|
||||
rust_thunk: *mut c_void,
|
||||
cx: *mut c_void,
|
||||
ok: *mut c_void,
|
||||
err: *mut Local,
|
||||
unwind_value: *mut *mut c_void,
|
||||
) -> TryCatchControl;
|
||||
}
|
||||
|
||||
6
create-neon/.mocharc.json
Normal file
6
create-neon/.mocharc.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"extension": ["ts"],
|
||||
"spec": "test/**/*.ts",
|
||||
"require": "ts-node/register",
|
||||
"timeout": 5000
|
||||
}
|
||||
11
create-neon/README.md
Normal file
11
create-neon/README.md
Normal file
@ -0,0 +1,11 @@
|
||||
# Create Neon
|
||||
|
||||
The `create-neon` tool bootstraps [Neon](https://neon-bindings.com) projects, which allows developers to build binary Node modules written in [Rust](https://www.rust-lang.org).
|
||||
|
||||
## Usage
|
||||
|
||||
You can conveniently use this tool with the [`npm init`](https://docs.npmjs.com/cli/v7/commands/npm-init) syntax:
|
||||
|
||||
```sh
|
||||
$ npm init neon my-project
|
||||
```
|
||||
5
create-neon/data/templates/.gitignore.hbs
Normal file
5
create-neon/data/templates/.gitignore.hbs
Normal file
@ -0,0 +1,5 @@
|
||||
target
|
||||
index.node
|
||||
**/node_modules
|
||||
**/.DS_Store
|
||||
npm-debug.log*
|
||||
22
create-neon/data/templates/Cargo.toml.hbs
Normal file
22
create-neon/data/templates/Cargo.toml.hbs
Normal file
@ -0,0 +1,22 @@
|
||||
[package]
|
||||
name = "{{package.name}}"
|
||||
version = "{{package.version}}"
|
||||
{{#if package.description}}
|
||||
description = {{package.quotedDescription}}
|
||||
{{/if}}
|
||||
{{#if package.author}}
|
||||
authors = [{{package.quotedAuthor}}]
|
||||
{{/if}}
|
||||
{{#if package.license}}
|
||||
license = "{{package.license}}"
|
||||
{{/if}}
|
||||
edition = "2018"
|
||||
exclude = ["index.node"]
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies.neon]
|
||||
version = "{{versions.neon}}"
|
||||
default-features = false
|
||||
features = ["napi-{{versions.napi}}"]
|
||||
109
create-neon/data/templates/README.md.hbs
Normal file
109
create-neon/data/templates/README.md.hbs
Normal file
@ -0,0 +1,109 @@
|
||||
# {{package.name}}
|
||||
|
||||
{{#if package.description}}
|
||||
**{{package.name}}:** {{package.description}}
|
||||
|
||||
{{/if}}
|
||||
This project was bootstrapped by [create-neon](https://www.npmjs.com/package/create-neon).
|
||||
|
||||
## Installing {{package.name}}
|
||||
|
||||
Installing {{package.name}} requires a [supported version of Node and Rust](https://github.com/neon-bindings/neon#platform-support).
|
||||
|
||||
You can install the project with npm. In the project directory, run:
|
||||
|
||||
```sh
|
||||
$ npm install
|
||||
```
|
||||
|
||||
This fully installs the project, including installing any dependencies and running the build.
|
||||
|
||||
## Building {{package.name}}
|
||||
|
||||
If you have already installed the project and only want to run the build, run:
|
||||
|
||||
```sh
|
||||
$ npm run build
|
||||
```
|
||||
|
||||
This command uses the [cargo-cp-artifact](https://github.com/neon-bindings/cargo-cp-artifact) utility to run the Rust build and copy the built library into `./index.node`.
|
||||
|
||||
## Exploring {{package.name}}
|
||||
|
||||
After building {{package.name}}, you can explore its exports at the Node REPL:
|
||||
|
||||
```sh
|
||||
$ npm install
|
||||
$ node
|
||||
> require('.').hello()
|
||||
"hello node"
|
||||
```
|
||||
|
||||
## Available Scripts
|
||||
|
||||
In the project directory, you can run:
|
||||
|
||||
### `npm install`
|
||||
|
||||
Installs the project, including running `npm run build`.
|
||||
|
||||
### `npm build`
|
||||
|
||||
Builds the Node addon (`index.node`) from source.
|
||||
|
||||
### `npm test`
|
||||
|
||||
Runs the unit tests by calling `cargo test`. You can learn more about [adding tests to your Rust code](https://doc.rust-lang.org/book/ch11-01-writing-tests.html) from the [Rust book](https://doc.rust-lang.org/book/).
|
||||
|
||||
## Project Layout
|
||||
|
||||
The directory structure of this project is:
|
||||
|
||||
```
|
||||
{{package.name}}/
|
||||
├── Cargo.toml
|
||||
├── README.md
|
||||
├── index.node
|
||||
├── package.json
|
||||
├── src/
|
||||
| └── lib.rs
|
||||
└── target/
|
||||
```
|
||||
|
||||
### Cargo.toml
|
||||
|
||||
The Cargo [manifest file](https://doc.rust-lang.org/cargo/reference/manifest.html), which informs the `cargo` command.
|
||||
|
||||
### README.md
|
||||
|
||||
This file.
|
||||
|
||||
### index.node
|
||||
|
||||
The Node addon—i.e., a binary Node module—generated by building the project. This is the main module for this package, as dictated by the `"main"` key in `package.json`.
|
||||
|
||||
Under the hood, a [Node addon](https://nodejs.org/api/addons.html) is a [dynamically-linked shared object](https://en.wikipedia.org/wiki/Library_(computing)#Shared_libraries). The `"build"` script produces this file by copying it from within the `target/` directory, which is where the Rust build produces the shared object.
|
||||
|
||||
### package.json
|
||||
|
||||
The npm [manifest file](https://docs.npmjs.com/cli/v7/configuring-npm/package-json), which informs the `npm` command.
|
||||
|
||||
### src/
|
||||
|
||||
The directory tree containing the Rust source code for the project.
|
||||
|
||||
### src/lib.rs
|
||||
|
||||
The Rust library's main module.
|
||||
|
||||
### target/
|
||||
|
||||
Binary artifacts generated by the Rust build.
|
||||
|
||||
## Learn More
|
||||
|
||||
To learn more about Neon, see the [Neon documentation](https://neon-bindings.com).
|
||||
|
||||
To learn more about Rust, see the [Rust documentation](https://www.rust-lang.org).
|
||||
|
||||
To learn more about Node, see the [Node documentation](https://nodejs.org).
|
||||
11
create-neon/data/templates/lib.rs.hbs
Normal file
11
create-neon/data/templates/lib.rs.hbs
Normal file
@ -0,0 +1,11 @@
|
||||
use neon::prelude::*;
|
||||
|
||||
fn hello(mut cx: FunctionContext) -> JsResult<JsString> {
|
||||
Ok(cx.string("hello node"))
|
||||
}
|
||||
|
||||
#[neon::main]
|
||||
fn main(mut cx: ModuleContext) -> NeonResult<()> {
|
||||
cx.export_function("hello", hello)?;
|
||||
Ok(())
|
||||
}
|
||||
5
create-neon/data/versions.json
Normal file
5
create-neon/data/versions.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"neon": "0.8",
|
||||
"napi": "6",
|
||||
"cargo-cp-artifact": "0.1"
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user