mirror of
https://github.com/nodejs/node.git
synced 2025-05-05 17:10:40 +00:00
build,test: make building addon tests less fragile
* Get rid of recursive `make` when building the node binary. An earlier commit makes GYP write out rules that we can use for proper dependency tracking. * Use module name 'binding' in addons.md and addons-napi/*/binding.gyp. This massively simplifies the logic for generating the build rules. * Check in auto-generated add-on tests from `doc/api/addons.md`. The files change rarely and generating them dynamically causes no end of race conditions and special-casing during the build. PR-URL: https://github.com/nodejs/node/pull/17407 Reviewed-By: Richard Lau <riclau@uk.ibm.com>
This commit is contained in:
parent
c6682636be
commit
d9b59def72
1
.gitignore
vendored
1
.gitignore
vendored
@ -74,7 +74,6 @@ ipch/
|
||||
/npm.wxs
|
||||
/tools/msvs/npm.wixobj
|
||||
/tools/msvs/genfiles/
|
||||
/test/addons/??_*/
|
||||
email.md
|
||||
deps/v8-*
|
||||
deps/icu
|
||||
|
262
Makefile
262
Makefile
@ -1,3 +1,4 @@
|
||||
-include .deps # Generated by GYP.
|
||||
-include config.mk
|
||||
|
||||
BUILDTYPE ?= Release
|
||||
@ -65,9 +66,9 @@ V ?= 1
|
||||
# BUILDTYPE=Debug builds both release and debug builds. If you want to compile
|
||||
# just the debug build, run `make -C out BUILDTYPE=Debug` instead.
|
||||
ifeq ($(BUILDTYPE),Release)
|
||||
all: out/Makefile $(NODE_EXE) ## Default target, builds node in out/Release/node.
|
||||
all: $(NODE_EXE) ## Default target, builds node in out/Release/node.
|
||||
else
|
||||
all: out/Makefile $(NODE_EXE) $(NODE_G_EXE)
|
||||
all: $(NODE_EXE) $(NODE_G_EXE)
|
||||
endif
|
||||
|
||||
.PHONY: help
|
||||
@ -77,32 +78,24 @@ help: ## Print help for targets with comments.
|
||||
@grep -E '^[a-zA-Z0-9._-]+:.*?## .*$$' Makefile | sort | \
|
||||
awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-15s\033[0m %s\n", $$1, $$2}'
|
||||
|
||||
# The .PHONY is needed to ensure that we recursively use the out/Makefile
|
||||
# to check for changes.
|
||||
.PHONY: $(NODE_EXE) $(NODE_G_EXE)
|
||||
$(NODE_EXE): out/Release/node
|
||||
ln -fs $< $@
|
||||
|
||||
# The -r/-L check stops it recreating the link if it is already in place,
|
||||
# otherwise $(NODE_EXE) being a .PHONY target means it is always re-run.
|
||||
# Without the check there is a race condition between the link being deleted
|
||||
# and recreated which can break the addons build when running test-ci
|
||||
# See comments on the build-addons target for some more info
|
||||
$(NODE_EXE): config.gypi out/Makefile
|
||||
$(NODE_G_EXE): out/Debug/node
|
||||
ln -fs $< $@
|
||||
|
||||
out/Release/node: out/Makefile $(ALL_DEPS)
|
||||
$(MAKE) -C out BUILDTYPE=Release V=$(V)
|
||||
if [ ! -r $@ -o ! -L $@ ]; then ln -fs out/Release/$(NODE_EXE) $@; fi
|
||||
|
||||
$(NODE_G_EXE): config.gypi out/Makefile
|
||||
out/Debug/node: out/Makefile $(ALL_DEPS)
|
||||
$(MAKE) -C out BUILDTYPE=Debug V=$(V)
|
||||
if [ ! -r $@ -o ! -L $@ ]; then ln -fs out/Debug/$(NODE_EXE) $@; fi
|
||||
|
||||
out/Makefile: common.gypi deps/uv/uv.gyp deps/http_parser/http_parser.gyp \
|
||||
out/Makefile .deps: deps/uv/uv.gyp deps/http_parser/http_parser.gyp \
|
||||
deps/zlib/zlib.gyp deps/v8/gypfiles/toolchain.gypi \
|
||||
deps/v8/gypfiles/features.gypi deps/v8/src/v8.gyp node.gyp \
|
||||
config.gypi
|
||||
common.gypi config.gypi
|
||||
$(PYTHON) tools/gyp_node.py -f make
|
||||
|
||||
config.gypi: configure
|
||||
$(error Missing or stale $@, please run ./$<)
|
||||
|
||||
.PHONY: install
|
||||
install: all ## Installs node into $PREFIX (default=/usr/local).
|
||||
$(PYTHON) tools/install.py $@ '$(DESTDIR)' '$(PREFIX)'
|
||||
@ -232,9 +225,7 @@ v8:
|
||||
|
||||
.PHONY: test
|
||||
# This does not run tests of third-party libraries inside deps.
|
||||
test: all ## Runs default tests, linters, and builds docs.
|
||||
$(MAKE) -s build-addons
|
||||
$(MAKE) -s build-addons-napi
|
||||
test: all build-addons ## Runs default tests, linters, and builds docs.
|
||||
$(MAKE) -s doc-only
|
||||
$(MAKE) -s lint
|
||||
$(MAKE) -s cctest
|
||||
@ -244,18 +235,14 @@ test: all ## Runs default tests, linters, and builds docs.
|
||||
$(CI_DOC)
|
||||
|
||||
.PHONY: test-only
|
||||
test-only: all ## For a quick test, does not run linter or build docs.
|
||||
$(MAKE) build-addons
|
||||
$(MAKE) build-addons-napi
|
||||
test-only: all build-addons ## For a quick test, does not run linter or build docs.
|
||||
$(MAKE) cctest
|
||||
$(PYTHON) tools/test.py --mode=release -J \
|
||||
$(CI_JS_SUITES) \
|
||||
$(CI_NATIVE_SUITES)
|
||||
|
||||
# Used by `make coverage-test`
|
||||
test-cov: all
|
||||
$(MAKE) build-addons
|
||||
$(MAKE) build-addons-napi
|
||||
test-cov: all build-addons
|
||||
# $(MAKE) cctest
|
||||
$(PYTHON) tools/test.py --mode=release -J \
|
||||
$(CI_JS_SUITES) \
|
||||
@ -271,115 +258,53 @@ test-valgrind: all
|
||||
test-check-deopts: all
|
||||
$(PYTHON) tools/test.py --mode=release --check-deopts parallel sequential -J
|
||||
|
||||
benchmark/misc/function_call/build/Release/binding.node: all \
|
||||
benchmark/misc/function_call/binding.cc \
|
||||
benchmark/misc/function_call/binding.gyp
|
||||
$(NODE) deps/npm/node_modules/node-gyp/bin/node-gyp rebuild \
|
||||
--python="$(PYTHON)" \
|
||||
--directory="$(shell pwd)/benchmark/misc/function_call" \
|
||||
--nodedir="$(shell pwd)"
|
||||
|
||||
# Implicitly depends on $(NODE_EXE). We don't depend on it explicitly because
|
||||
# it always triggers a rebuild due to it being a .PHONY rule. See the comment
|
||||
# near the build-addons rule for more background.
|
||||
test/gc/build/Release/binding.node: test/gc/binding.cc test/gc/binding.gyp
|
||||
$(NODE) deps/npm/node_modules/node-gyp/bin/node-gyp rebuild \
|
||||
--python="$(PYTHON)" \
|
||||
--directory="$(shell pwd)/test/gc" \
|
||||
--nodedir="$(shell pwd)"
|
||||
|
||||
DOCBUILDSTAMP_PREREQS = tools/doc/addon-verify.js doc/api/addons.md
|
||||
ADDON_PREREQS := \
|
||||
common.gypi \
|
||||
config.gypi \
|
||||
deps/npm/node_modules/node-gyp/package.json \
|
||||
src/node.h \
|
||||
src/node_api.h \
|
||||
src/node_api_types.h \
|
||||
src/node_buffer.h \
|
||||
src/node_object_wrap.h \
|
||||
src/node_version.h \
|
||||
$(wildcard deps/openssl/openssl/include/openssl/*.h) \
|
||||
$(wildcard deps/uv/include/*.h) \
|
||||
$(wildcard deps/v8/include/*.h) \
|
||||
$(wildcard deps/zlib/*.h) \
|
||||
|
||||
ifeq ($(OSTYPE),aix)
|
||||
DOCBUILDSTAMP_PREREQS := $(DOCBUILDSTAMP_PREREQS) out/$(BUILDTYPE)/node.exp
|
||||
ADDON_PREREQS := $(ADDON_PREREQS) out/$(BUILDTYPE)/node.exp
|
||||
endif
|
||||
|
||||
test/addons/.docbuildstamp: $(DOCBUILDSTAMP_PREREQS)
|
||||
$(RM) -r test/addons/??_*/
|
||||
[ -x $(NODE) ] && $(NODE) $< || node $<
|
||||
touch $@
|
||||
|
||||
ADDONS_BINDING_GYPS := \
|
||||
$(filter-out test/addons/??_*/binding.gyp, \
|
||||
ADDON_DIRS := \
|
||||
$(dir benchmark/misc/function_call/ test/gc/ \
|
||||
$(wildcard test/addons-napi/*/binding.gyp) \
|
||||
$(wildcard test/addons/*/binding.gyp))
|
||||
|
||||
ADDONS_BINDING_SOURCES := \
|
||||
$(filter-out test/addons/??_*/*.cc, $(wildcard test/addons/*/*.cc)) \
|
||||
$(filter-out test/addons/??_*/*.h, $(wildcard test/addons/*/*.h))
|
||||
ADDON_FILES := \
|
||||
$(foreach d, $(ADDON_DIRS), $(d)build/$(BUILDTYPE)/binding.node)
|
||||
|
||||
# Implicitly depends on $(NODE_EXE), see the build-addons rule for rationale.
|
||||
# Depends on node-gyp package.json so that build-addons is (re)executed when
|
||||
# node-gyp is updated as part of an npm update.
|
||||
test/addons/.buildstamp: config.gypi \
|
||||
deps/npm/node_modules/node-gyp/package.json \
|
||||
$(ADDONS_BINDING_GYPS) $(ADDONS_BINDING_SOURCES) \
|
||||
deps/uv/include/*.h deps/v8/include/*.h \
|
||||
src/node.h src/node_buffer.h src/node_object_wrap.h src/node_version.h \
|
||||
test/addons/.docbuildstamp
|
||||
# Cannot use $(wildcard test/addons/*/) here, it's evaluated before
|
||||
# embedded addons have been generated from the documentation.
|
||||
# Ignore folders without binding.gyp
|
||||
# (https://github.com/nodejs/node/issues/14843)
|
||||
@for dirname in test/addons/*/; do \
|
||||
if [ ! -f "$$PWD/$${dirname}binding.gyp" ]; then \
|
||||
continue; fi ; \
|
||||
printf "\nBuilding addon $$PWD/$$dirname\n" ; \
|
||||
env MAKEFLAGS="-j1" $(NODE) deps/npm/node_modules/node-gyp/bin/node-gyp \
|
||||
--loglevel=$(LOGLEVEL) rebuild \
|
||||
--python="$(PYTHON)" \
|
||||
--directory="$$PWD/$$dirname" \
|
||||
--nodedir="$$PWD" || exit 1 ; \
|
||||
done
|
||||
touch $@
|
||||
NODE_GYP := \
|
||||
env MAKEFLAGS="-j1" \
|
||||
$(NODE) deps/npm/node_modules/node-gyp/bin/node-gyp \
|
||||
--loglevel="$(LOGLEVEL)" --nodedir="$(CURDIR)" --python="$(PYTHON)"
|
||||
|
||||
define do_addon
|
||||
$(1)build/Makefile: $(1)binding.gyp common.gypi
|
||||
$(NODE_GYP) --directory=$(1) configure
|
||||
$(1)build/Release/.buildstamp: $(1)build/Makefile $(2) $(ADDON_PREREQS)
|
||||
$(NODE_GYP) --directory=$(1) build
|
||||
@touch $$@
|
||||
$(1)build/Release/binding.node: $(1)build/Release/.buildstamp
|
||||
endef
|
||||
|
||||
$(foreach x, $(ADDON_DIRS), \
|
||||
$(eval $(call do_addon,$(x),$(wildcard $(x)/*.{c,cc,h}))))
|
||||
|
||||
.PHONY: build-addons
|
||||
# .buildstamp needs $(NODE_EXE) but cannot depend on it
|
||||
# directly because it calls make recursively. The parent make cannot know
|
||||
# if the subprocess touched anything so it pessimistically assumes that
|
||||
# .buildstamp is out of date and need a rebuild.
|
||||
# Just goes to show that recursive make really is harmful...
|
||||
# TODO(bnoordhuis) Force rebuild after gyp update.
|
||||
build-addons: | $(NODE_EXE) test/addons/.buildstamp
|
||||
|
||||
ADDONS_NAPI_BINDING_GYPS := \
|
||||
$(filter-out test/addons-napi/??_*/binding.gyp, \
|
||||
$(wildcard test/addons-napi/*/binding.gyp))
|
||||
|
||||
ADDONS_NAPI_BINDING_SOURCES := \
|
||||
$(filter-out test/addons-napi/??_*/*.cc, $(wildcard test/addons-napi/*/*.cc)) \
|
||||
$(filter-out test/addons-napi/??_*/*.h, $(wildcard test/addons-napi/*/*.h))
|
||||
|
||||
# Implicitly depends on $(NODE_EXE), see the build-addons-napi rule for rationale.
|
||||
test/addons-napi/.buildstamp: config.gypi \
|
||||
deps/npm/node_modules/node-gyp/package.json \
|
||||
$(ADDONS_NAPI_BINDING_GYPS) $(ADDONS_NAPI_BINDING_SOURCES) \
|
||||
deps/uv/include/*.h deps/v8/include/*.h \
|
||||
src/node.h src/node_buffer.h src/node_object_wrap.h src/node_version.h \
|
||||
src/node_api.h src/node_api_types.h
|
||||
# Cannot use $(wildcard test/addons-napi/*/) here, it's evaluated before
|
||||
# embedded addons have been generated from the documentation.
|
||||
# Ignore folders without binding.gyp
|
||||
# (https://github.com/nodejs/node/issues/14843)
|
||||
@for dirname in test/addons-napi/*/; do \
|
||||
if [ ! -f "$$PWD/$${dirname}binding.gyp" ]; then \
|
||||
continue; fi ; \
|
||||
printf "\nBuilding addon $$PWD/$$dirname\n" ; \
|
||||
env MAKEFLAGS="-j1" $(NODE) deps/npm/node_modules/node-gyp/bin/node-gyp \
|
||||
--loglevel=$(LOGLEVEL) rebuild \
|
||||
--python="$(PYTHON)" \
|
||||
--directory="$$PWD/$$dirname" \
|
||||
--nodedir="$$PWD" || exit 1 ; \
|
||||
done
|
||||
touch $@
|
||||
|
||||
.PHONY: build-addons-napi
|
||||
# .buildstamp needs $(NODE_EXE) but cannot depend on it
|
||||
# directly because it calls make recursively. The parent make cannot know
|
||||
# if the subprocess touched anything so it pessimistically assumes that
|
||||
# .buildstamp is out of date and need a rebuild.
|
||||
# Just goes to show that recursive make really is harmful...
|
||||
# TODO(bnoordhuis) Force rebuild after gyp or node-gyp update.
|
||||
build-addons-napi: | $(NODE_EXE) test/addons-napi/.buildstamp
|
||||
build-addons: $(NODE)
|
||||
@$(MAKE) -s $(ADDON_FILES)
|
||||
|
||||
.PHONY: clear-stalled
|
||||
clear-stalled:
|
||||
@ -398,15 +323,11 @@ test-gc: all test/gc/build/Release/binding.node
|
||||
test-gc-clean:
|
||||
$(RM) -r test/gc/build
|
||||
|
||||
test-build: | all build-addons build-addons-napi
|
||||
|
||||
test-build-addons-napi: all build-addons-napi
|
||||
|
||||
.PHONY: test-all
|
||||
test-all: test-build test/gc/build/Release/binding.node ## Run everything in test/.
|
||||
test-all: test/gc/build/Release/binding.node ## Run everything in test/.
|
||||
$(PYTHON) tools/test.py --mode=debug,release
|
||||
|
||||
test-all-valgrind: test-build
|
||||
test-all-valgrind: build-addons
|
||||
$(PYTHON) tools/test.py --mode=debug,release --valgrind
|
||||
|
||||
CI_NATIVE_SUITES ?= addons addons-napi
|
||||
@ -417,7 +338,7 @@ CI_DOC := doctool
|
||||
# Build and test addons without building anything else
|
||||
# Related CI job: node-test-commit-arm-fanned
|
||||
test-ci-native: LOGLEVEL := info
|
||||
test-ci-native: | test/addons/.buildstamp test/addons-napi/.buildstamp
|
||||
test-ci-native: $(ADDON_FILES)
|
||||
$(PYTHON) tools/test.py $(PARALLEL_ARGS) -p tap --logfile test.tap \
|
||||
--mode=release --flaky-tests=$(FLAKY_TESTS) \
|
||||
$(TEST_CI_ARGS) $(CI_NATIVE_SUITES)
|
||||
@ -439,7 +360,7 @@ test-ci-js: | clear-stalled
|
||||
.PHONY: test-ci
|
||||
# Related CI jobs: most CI tests, excluding node-test-commit-arm-fanned
|
||||
test-ci: LOGLEVEL := info
|
||||
test-ci: | clear-stalled build-addons build-addons-napi doc-only
|
||||
test-ci: build-addons | clear-stalled doc-only
|
||||
out/Release/cctest --gtest_output=tap:cctest.tap
|
||||
$(PYTHON) tools/test.py $(PARALLEL_ARGS) -p tap --logfile test.tap \
|
||||
--mode=release --flaky-tests=$(FLAKY_TESTS) \
|
||||
@ -468,13 +389,13 @@ build-ci:
|
||||
run-ci: build-ci
|
||||
$(MAKE) test-ci
|
||||
|
||||
test-release: test-build
|
||||
test-release: build-addons
|
||||
$(PYTHON) tools/test.py --mode=release
|
||||
|
||||
test-debug: test-build
|
||||
test-debug: build-addons
|
||||
$(PYTHON) tools/test.py --mode=debug
|
||||
|
||||
test-message: test-build
|
||||
test-message: all
|
||||
$(PYTHON) tools/test.py message
|
||||
|
||||
test-simple: | cctest # Depends on 'all'.
|
||||
@ -514,23 +435,21 @@ test-npm-publish: $(NODE_EXE)
|
||||
npm_package_config_publishtest=true $(NODE) deps/npm/test/run.js
|
||||
|
||||
.PHONY: test-addons-napi
|
||||
test-addons-napi: test-build-addons-napi
|
||||
test-addons-napi: build-addons
|
||||
$(PYTHON) tools/test.py --mode=release addons-napi
|
||||
|
||||
.PHONY: test-addons-napi-clean
|
||||
test-addons-napi-clean:
|
||||
$(RM) -r test/addons-napi/*/build
|
||||
$(RM) test/addons-napi/.buildstamp
|
||||
|
||||
.PHONY: test-addons
|
||||
test-addons: test-build test-addons-napi
|
||||
test-addons: build-addons
|
||||
$(PYTHON) tools/test.py --mode=release addons
|
||||
|
||||
.PHONY: test-addons-clean
|
||||
test-addons-clean:
|
||||
$(RM) -r test/addons/??_*/
|
||||
$(RM) -r test/addons/*/build
|
||||
$(RM) test/addons/.buildstamp test/addons/.docbuildstamp
|
||||
$(MAKE) test-addons-napi-clean
|
||||
|
||||
test-timers:
|
||||
@ -543,9 +462,7 @@ test-timers-clean:
|
||||
test-async-hooks:
|
||||
$(PYTHON) tools/test.py --mode=release async-hooks
|
||||
|
||||
test-with-async-hooks:
|
||||
$(MAKE) build-addons
|
||||
$(MAKE) build-addons-napi
|
||||
test-with-async-hooks: build-addons
|
||||
$(MAKE) cctest
|
||||
NODE_TEST_WITH_ASYNC_HOOKS=1 $(PYTHON) tools/test.py --mode=release -J \
|
||||
$(CI_JS_SUITES) \
|
||||
@ -1113,36 +1030,32 @@ lint-js-ci:
|
||||
jslint-ci: lint-js-ci
|
||||
@echo "Please use lint-js-ci instead of jslint-ci"
|
||||
|
||||
LINT_CPP_ADDON_DOC_FILES = $(wildcard test/addons/??_*/*.cc test/addons/??_*/*.h)
|
||||
LINT_CPP_EXCLUDE ?=
|
||||
LINT_CPP_EXCLUDE += src/node_root_certs.h
|
||||
LINT_CPP_EXCLUDE += $(LINT_CPP_ADDON_DOC_FILES)
|
||||
LINT_CPP_EXCLUDE += $(wildcard test/addons-napi/??_*/*.cc test/addons-napi/??_*/*.h)
|
||||
# These files were copied more or less verbatim from V8.
|
||||
LINT_CPP_EXCLUDE += src/tracing/trace_event.h src/tracing/trace_event_common.h
|
||||
|
||||
LINT_CPP_FILES = $(filter-out $(LINT_CPP_EXCLUDE), $(wildcard \
|
||||
benchmark/misc/function_call/binding.cc \
|
||||
src/*.c \
|
||||
src/*.cc \
|
||||
src/*.h \
|
||||
src/*/*.c \
|
||||
src/*/*.cc \
|
||||
src/*/*.h \
|
||||
test/addons/*/*.cc \
|
||||
test/addons/*/*.h \
|
||||
test/cctest/*.cc \
|
||||
test/cctest/*.h \
|
||||
test/addons-napi/*/*.cc \
|
||||
test/addons-napi/*/*.h \
|
||||
test/gc/binding.cc \
|
||||
tools/icu/*.cc \
|
||||
tools/icu/*.h \
|
||||
))
|
||||
|
||||
# Code blocks don't have newline at the end,
|
||||
# and the actual filename is generated so it won't match header guards
|
||||
ADDON_DOC_LINT_FLAGS=-whitespace/ending_newline,-build/header_guard
|
||||
LINT_CPP_FILES := \
|
||||
$(filter-out \
|
||||
$(LINT_CPP_EXCLUDE), \
|
||||
$(wildcard \
|
||||
benchmark/misc/function_call/binding.cc \
|
||||
src/*.c \
|
||||
src/*.cc \
|
||||
src/*.h \
|
||||
src/*/*.c \
|
||||
src/*/*.cc \
|
||||
src/*/*.h \
|
||||
test/addons/*/*.cc \
|
||||
test/addons/*/*.h \
|
||||
test/cctest/*.cc \
|
||||
test/cctest/*.h \
|
||||
test/addons-napi/*/*.cc \
|
||||
test/addons-napi/*/*.h \
|
||||
test/gc/binding.cc \
|
||||
tools/icu/*.cc \
|
||||
tools/icu/*.h \
|
||||
))
|
||||
|
||||
.PHONY: lint-cpp
|
||||
# Lints the C++ code with cpplint.py and check-imports.py.
|
||||
@ -1154,10 +1067,6 @@ tools/.cpplintstamp: $(LINT_CPP_FILES)
|
||||
@$(PYTHON) tools/check-imports.py
|
||||
@touch $@
|
||||
|
||||
lint-addon-docs: test/addons/.docbuildstamp
|
||||
@echo "Running C++ linter on addon docs..."
|
||||
@$(PYTHON) tools/cpplint.py --filter=$(ADDON_DOC_LINT_FLAGS) $(LINT_CPP_ADDON_DOC_FILES)
|
||||
|
||||
cpplint: lint-cpp
|
||||
@echo "Please use lint-cpp instead of cpplint"
|
||||
|
||||
@ -1168,12 +1077,11 @@ lint: ## Run JS, C++, MD and doc linters.
|
||||
@EXIT_STATUS=0 ; \
|
||||
$(MAKE) lint-js || EXIT_STATUS=$$? ; \
|
||||
$(MAKE) lint-cpp || EXIT_STATUS=$$? ; \
|
||||
$(MAKE) lint-addon-docs || EXIT_STATUS=$$? ; \
|
||||
exit $$EXIT_STATUS
|
||||
CONFLICT_RE=^>>>>>>> [0-9A-Fa-f]+|^<<<<<<< [A-Za-z]+
|
||||
|
||||
# Related CI job: node-test-linter
|
||||
lint-ci: lint-js-ci lint-cpp lint-md lint-addon-docs
|
||||
lint-ci: lint-js-ci lint-cpp lint-md
|
||||
@if ! ( grep -IEqrs "$(CONFLICT_RE)" benchmark deps doc lib src test tools ) \
|
||||
&& ! ( find . -maxdepth 1 -type f | xargs grep -IEqs "$(CONFLICT_RE)" ); then \
|
||||
exit 0 ; \
|
||||
|
@ -1,3 +1,6 @@
|
||||
<!--
|
||||
Run `node tools/doc/addon-verify.js` when you change examples in this document.
|
||||
-->
|
||||
# C++ Addons
|
||||
|
||||
<!--introduced_in=v0.10.0-->
|
||||
@ -94,12 +97,12 @@ The `module_name` must match the filename of the final binary (excluding
|
||||
the .node suffix).
|
||||
|
||||
In the `hello.cc` example, then, the initialization function is `init` and the
|
||||
Addon module name is `addon`.
|
||||
Addon module name is `binding`.
|
||||
|
||||
### Building
|
||||
|
||||
Once the source code has been written, it must be compiled into the binary
|
||||
`addon.node` file. To do so, create a file called `binding.gyp` in the
|
||||
`binding.node` file. To do so, create a file called `binding.gyp` in the
|
||||
top-level of the project describing the build configuration of the module
|
||||
using a JSON-like format. This file is used by [node-gyp][] -- a tool written
|
||||
specifically to compile Node.js Addons.
|
||||
@ -108,7 +111,7 @@ specifically to compile Node.js Addons.
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "addon",
|
||||
"target_name": "binding",
|
||||
"sources": [ "hello.cc" ]
|
||||
}
|
||||
]
|
||||
@ -128,21 +131,21 @@ generate the appropriate project build files for the current platform. This
|
||||
will generate either a `Makefile` (on Unix platforms) or a `vcxproj` file
|
||||
(on Windows) in the `build/` directory.
|
||||
|
||||
Next, invoke the `node-gyp build` command to generate the compiled `addon.node`
|
||||
file. This will be put into the `build/Release/` directory.
|
||||
Next, invoke the `node-gyp build` command to generate the compiled
|
||||
`binding.node` file. This will be put into the `build/Release/` directory.
|
||||
|
||||
When using `npm install` to install a Node.js Addon, npm uses its own bundled
|
||||
version of `node-gyp` to perform this same set of actions, generating a
|
||||
compiled version of the Addon for the user's platform on demand.
|
||||
|
||||
Once built, the binary Addon can be used from within Node.js by pointing
|
||||
[`require()`][require] to the built `addon.node` module:
|
||||
[`require()`][require] to the built `binding.node` module:
|
||||
|
||||
```js
|
||||
// hello.js
|
||||
const addon = require('./build/Release/addon');
|
||||
const binding = require('./build/Release/binding');
|
||||
|
||||
console.log(addon.hello());
|
||||
console.log(binding.hello());
|
||||
// Prints: 'world'
|
||||
```
|
||||
|
||||
@ -159,9 +162,9 @@ similar to:
|
||||
|
||||
```js
|
||||
try {
|
||||
return require('./build/Release/addon.node');
|
||||
return require('./build/Release/binding.node');
|
||||
} catch (err) {
|
||||
return require('./build/Debug/addon.node');
|
||||
return require('./build/Debug/binding.node');
|
||||
}
|
||||
```
|
||||
|
||||
@ -195,9 +198,9 @@ When calling [`require()`][require], the `.node` extension can usually be
|
||||
omitted and Node.js will still find and initialize the Addon. One caveat,
|
||||
however, is that Node.js will first attempt to locate and load modules or
|
||||
JavaScript files that happen to share the same base name. For instance, if
|
||||
there is a file `addon.js` in the same directory as the binary `addon.node`,
|
||||
then [`require('addon')`][require] will give precedence to the `addon.js` file
|
||||
and load it instead.
|
||||
there is a file `binding.js` in the same directory as the binary `binding.node`,
|
||||
then [`require('binding')`][require] will give precedence to the `binding.js`
|
||||
file and load it instead.
|
||||
|
||||
## Native Abstractions for Node.js
|
||||
|
||||
@ -284,8 +287,8 @@ Each of these examples using the following `binding.gyp` file:
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "addon",
|
||||
"sources": [ "addon.cc" ]
|
||||
"target_name": "binding",
|
||||
"sources": [ "binding.cc" ]
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -295,7 +298,7 @@ In cases where there is more than one `.cc` file, simply add the additional
|
||||
filename to the `sources` array. For example:
|
||||
|
||||
```json
|
||||
"sources": ["addon.cc", "myexample.cc"]
|
||||
"sources": ["binding.cc", "myexample.cc"]
|
||||
```
|
||||
|
||||
Once the `binding.gyp` file is ready, the example Addons can be configured and
|
||||
@ -317,7 +320,7 @@ The following example illustrates how to read function arguments passed from
|
||||
JavaScript and how to return a result:
|
||||
|
||||
```cpp
|
||||
// addon.cc
|
||||
// binding.cc
|
||||
#include <node.h>
|
||||
|
||||
namespace demo {
|
||||
@ -374,9 +377,9 @@ Once compiled, the example Addon can be required and used from within Node.js:
|
||||
|
||||
```js
|
||||
// test.js
|
||||
const addon = require('./build/Release/addon');
|
||||
const binding = require('./build/Release/binding');
|
||||
|
||||
console.log('This should be eight:', addon.add(3, 5));
|
||||
console.log('This should be eight:', binding.add(3, 5));
|
||||
```
|
||||
|
||||
|
||||
@ -387,7 +390,7 @@ function and execute them from there. The following example illustrates how
|
||||
to invoke such callbacks:
|
||||
|
||||
```cpp
|
||||
// addon.cc
|
||||
// binding.cc
|
||||
#include <node.h>
|
||||
|
||||
namespace demo {
|
||||
@ -427,9 +430,9 @@ To test it, run the following JavaScript:
|
||||
|
||||
```js
|
||||
// test.js
|
||||
const addon = require('./build/Release/addon');
|
||||
const binding = require('./build/Release/binding');
|
||||
|
||||
addon((msg) => {
|
||||
binding((msg) => {
|
||||
console.log(msg);
|
||||
// Prints: 'hello world'
|
||||
});
|
||||
@ -444,7 +447,7 @@ illustrated in the following example. An object is created and returned with a
|
||||
property `msg` that echoes the string passed to `createObject()`:
|
||||
|
||||
```cpp
|
||||
// addon.cc
|
||||
// binding.cc
|
||||
#include <node.h>
|
||||
|
||||
namespace demo {
|
||||
@ -478,10 +481,10 @@ To test it in JavaScript:
|
||||
|
||||
```js
|
||||
// test.js
|
||||
const addon = require('./build/Release/addon');
|
||||
const binding = require('./build/Release/binding');
|
||||
|
||||
const obj1 = addon('hello');
|
||||
const obj2 = addon('world');
|
||||
const obj1 = binding('hello');
|
||||
const obj2 = binding('world');
|
||||
console.log(obj1.msg, obj2.msg);
|
||||
// Prints: 'hello world'
|
||||
```
|
||||
@ -493,7 +496,7 @@ Another common scenario is creating JavaScript functions that wrap C++
|
||||
functions and returning those back to JavaScript:
|
||||
|
||||
```cpp
|
||||
// addon.cc
|
||||
// binding.cc
|
||||
#include <node.h>
|
||||
|
||||
namespace demo {
|
||||
@ -537,9 +540,9 @@ To test:
|
||||
|
||||
```js
|
||||
// test.js
|
||||
const addon = require('./build/Release/addon');
|
||||
const binding = require('./build/Release/binding');
|
||||
|
||||
const fn = addon();
|
||||
const fn = binding();
|
||||
console.log(fn());
|
||||
// Prints: 'hello world'
|
||||
```
|
||||
@ -551,7 +554,7 @@ It is also possible to wrap C++ objects/classes in a way that allows new
|
||||
instances to be created using the JavaScript `new` operator:
|
||||
|
||||
```cpp
|
||||
// addon.cc
|
||||
// binding.cc
|
||||
#include <node.h>
|
||||
#include "myobject.h"
|
||||
|
||||
@ -686,9 +689,9 @@ To build this example, the `myobject.cc` file must be added to the
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "addon",
|
||||
"target_name": "binding",
|
||||
"sources": [
|
||||
"addon.cc",
|
||||
"binding.cc",
|
||||
"myobject.cc"
|
||||
]
|
||||
}
|
||||
@ -700,9 +703,9 @@ Test it with:
|
||||
|
||||
```js
|
||||
// test.js
|
||||
const addon = require('./build/Release/addon');
|
||||
const binding = require('./build/Release/binding');
|
||||
|
||||
const obj = new addon.MyObject(10);
|
||||
const obj = new binding.MyObject(10);
|
||||
console.log(obj.plusOne());
|
||||
// Prints: 11
|
||||
console.log(obj.plusOne());
|
||||
@ -717,15 +720,15 @@ Alternatively, it is possible to use a factory pattern to avoid explicitly
|
||||
creating object instances using the JavaScript `new` operator:
|
||||
|
||||
```js
|
||||
const obj = addon.createObject();
|
||||
const obj = binding.createObject();
|
||||
// instead of:
|
||||
// const obj = new addon.Object();
|
||||
// const obj = new binding.Object();
|
||||
```
|
||||
|
||||
First, the `createObject()` method is implemented in `addon.cc`:
|
||||
First, the `createObject()` method is implemented in `binding.cc`:
|
||||
|
||||
```cpp
|
||||
// addon.cc
|
||||
// binding.cc
|
||||
#include <node.h>
|
||||
#include "myobject.h"
|
||||
|
||||
@ -881,9 +884,9 @@ Once again, to build this example, the `myobject.cc` file must be added to the
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "addon",
|
||||
"target_name": "binding",
|
||||
"sources": [
|
||||
"addon.cc",
|
||||
"binding.cc",
|
||||
"myobject.cc"
|
||||
]
|
||||
}
|
||||
@ -895,7 +898,7 @@ Test it with:
|
||||
|
||||
```js
|
||||
// test.js
|
||||
const createObject = require('./build/Release/addon');
|
||||
const createObject = require('./build/Release/binding');
|
||||
|
||||
const obj = createObject(10);
|
||||
console.log(obj.plusOne());
|
||||
@ -923,7 +926,7 @@ wrapped objects around by unwrapping them with the Node.js helper function
|
||||
that can take two `MyObject` objects as input arguments:
|
||||
|
||||
```cpp
|
||||
// addon.cc
|
||||
// binding.cc
|
||||
#include <node.h>
|
||||
#include <node_object_wrap.h>
|
||||
#include "myobject.h"
|
||||
@ -1077,11 +1080,11 @@ Test it with:
|
||||
|
||||
```js
|
||||
// test.js
|
||||
const addon = require('./build/Release/addon');
|
||||
const binding = require('./build/Release/binding');
|
||||
|
||||
const obj1 = addon.createObject(10);
|
||||
const obj2 = addon.createObject(20);
|
||||
const result = addon.add(obj1, obj2);
|
||||
const obj1 = binding.createObject(10);
|
||||
const obj2 = binding.createObject(20);
|
||||
const result = binding.add(obj1, obj2);
|
||||
|
||||
console.log(result);
|
||||
// Prints: 30
|
||||
@ -1106,10 +1109,10 @@ and a pointer to untyped context data to be passed to that callback.
|
||||
|
||||
Callbacks are run in last-in first-out order.
|
||||
|
||||
The following `addon.cc` implements AtExit:
|
||||
The following `binding.cc` implements AtExit:
|
||||
|
||||
```cpp
|
||||
// addon.cc
|
||||
// binding.cc
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <node.h>
|
||||
@ -1161,7 +1164,7 @@ Test in JavaScript by running:
|
||||
|
||||
```js
|
||||
// test.js
|
||||
require('./build/Release/addon');
|
||||
require('./build/Release/binding');
|
||||
```
|
||||
|
||||
[Embedder's Guide]: https://github.com/v8/v8/wiki/Embedder's%20Guide
|
||||
|
12
node.gyp
12
node.gyp
@ -533,14 +533,6 @@
|
||||
# node_dtrace_ustack.o not supported on mac and linux
|
||||
# node_dtrace_provider.o All except OS X. "dtrace -G" is not
|
||||
# used on OS X.
|
||||
#
|
||||
# Note that node_dtrace_provider.cc and node_dtrace_ustack.cc do not
|
||||
# actually exist. They're listed here to trick GYP into linking the
|
||||
# corresponding object files into the final "node" executable. These
|
||||
# object files are generated by "dtrace -G" using custom actions
|
||||
# below, and the GYP-generated Makefiles will properly build them when
|
||||
# needed.
|
||||
#
|
||||
'sources': [ 'src/node_dtrace.cc' ],
|
||||
'conditions': [
|
||||
[ 'OS=="linux"', {
|
||||
@ -550,8 +542,8 @@
|
||||
}],
|
||||
[ 'OS!="mac" and OS!="linux"', {
|
||||
'sources': [
|
||||
'src/node_dtrace_ustack.cc',
|
||||
'src/node_dtrace_provider.cc',
|
||||
'<(OBJ_DIR)/<(node_lib_target_name)/src/node_dtrace_provider.o',
|
||||
'<(OBJ_DIR)/<(node_lib_target_name)/src/node_dtrace_ustack.o',
|
||||
]
|
||||
}
|
||||
] ]
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "test_array",
|
||||
"target_name": "binding",
|
||||
"sources": [ "test_array.c" ]
|
||||
}
|
||||
]
|
||||
|
@ -3,7 +3,7 @@ const common = require('../../common');
|
||||
const assert = require('assert');
|
||||
|
||||
// Testing api calls for arrays
|
||||
const test_array = require(`./build/${common.buildType}/test_array`);
|
||||
const test_array = require(`./build/${common.buildType}/binding`);
|
||||
|
||||
const array = [
|
||||
1,
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "test_async",
|
||||
"target_name": "binding",
|
||||
"sources": [ "test_async.cc" ]
|
||||
}
|
||||
]
|
||||
|
@ -2,7 +2,7 @@
|
||||
const common = require('../../common');
|
||||
const assert = require('assert');
|
||||
const async_hooks = require('async_hooks');
|
||||
const test_async = require(`./build/${common.buildType}/test_async`);
|
||||
const test_async = require(`./build/${common.buildType}/binding`);
|
||||
|
||||
const events = [];
|
||||
let testId;
|
||||
|
@ -2,7 +2,7 @@
|
||||
const common = require('../../common');
|
||||
const assert = require('assert');
|
||||
const child_process = require('child_process');
|
||||
const test_async = require(`./build/${common.buildType}/test_async`);
|
||||
const test_async = require(`./build/${common.buildType}/binding`);
|
||||
|
||||
const testException = 'test_async_cb_exception';
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "test_buffer",
|
||||
"target_name": "binding",
|
||||
"sources": [ "test_buffer.c" ]
|
||||
}
|
||||
]
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Flags: --expose-gc
|
||||
|
||||
const common = require('../../common');
|
||||
const binding = require(`./build/${common.buildType}/test_buffer`);
|
||||
const binding = require(`./build/${common.buildType}/binding`);
|
||||
const assert = require('assert');
|
||||
|
||||
assert.strictEqual(binding.newBuffer().toString(), binding.theText);
|
||||
|
@ -1,12 +1,8 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "test_constructor",
|
||||
"target_name": "binding",
|
||||
"sources": [ "test_constructor.c" ]
|
||||
},
|
||||
{
|
||||
"target_name": "test_constructor_name",
|
||||
"sources": [ "test_constructor_name.c" ]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ const common = require('../../common');
|
||||
const assert = require('assert');
|
||||
|
||||
// Testing api calls for a constructor that defines properties
|
||||
const TestConstructor = require(`./build/${common.buildType}/test_constructor`);
|
||||
const TestConstructor = require(`./build/${common.buildType}/binding`);
|
||||
const test_object = new TestConstructor();
|
||||
|
||||
assert.strictEqual(test_object.echo('hello'), 'hello');
|
||||
|
8
test/addons-napi/test_constructor_name/binding.gyp
Normal file
8
test/addons-napi/test_constructor_name/binding.gyp
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "binding",
|
||||
"sources": [ "test_constructor_name.c" ]
|
||||
}
|
||||
]
|
||||
}
|
@ -3,6 +3,5 @@ const common = require('../../common');
|
||||
const assert = require('assert');
|
||||
|
||||
// Testing api calls for a constructor that defines properties
|
||||
const TestConstructor =
|
||||
require(`./build/${common.buildType}/test_constructor_name`);
|
||||
const TestConstructor = require(`./build/${common.buildType}/binding`);
|
||||
assert.strictEqual(TestConstructor.name, 'MyObject');
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "test_conversions",
|
||||
"target_name": "binding",
|
||||
"sources": [ "test_conversions.c" ]
|
||||
}
|
||||
]
|
||||
|
@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
const common = require('../../common');
|
||||
const assert = require('assert');
|
||||
const test = require(`./build/${common.buildType}/test_conversions`);
|
||||
const test = require(`./build/${common.buildType}/binding`);
|
||||
|
||||
const boolExpected = /boolean was expected/;
|
||||
const numberExpected = /number was expected/;
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "test_dataview",
|
||||
"target_name": "binding",
|
||||
"sources": [ "test_dataview.c" ]
|
||||
}
|
||||
]
|
||||
|
@ -3,7 +3,7 @@ const common = require('../../common');
|
||||
const assert = require('assert');
|
||||
|
||||
// Testing api calls for arrays
|
||||
const test_dataview = require(`./build/${common.buildType}/test_dataview`);
|
||||
const test_dataview = require(`./build/${common.buildType}/binding`);
|
||||
|
||||
// Test for creating dataview
|
||||
{
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "store_env",
|
||||
"target_name": "binding",
|
||||
"sources": [ "store_env.c" ]
|
||||
},
|
||||
{
|
||||
|
@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../../common');
|
||||
const storeEnv = require(`./build/${common.buildType}/store_env`);
|
||||
const storeEnv = require(`./build/${common.buildType}/binding`);
|
||||
const compareEnv = require(`./build/${common.buildType}/compare_env`);
|
||||
const assert = require('assert');
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "test_error",
|
||||
"target_name": "binding",
|
||||
"sources": [ "test_error.cc" ]
|
||||
}
|
||||
]
|
||||
|
@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../../common');
|
||||
const test_error = require(`./build/${common.buildType}/test_error`);
|
||||
const test_error = require(`./build/${common.buildType}/binding`);
|
||||
const assert = require('assert');
|
||||
const theError = new Error('Some error');
|
||||
const theTypeError = new TypeError('Some type error');
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "test_exception",
|
||||
"target_name": "binding",
|
||||
"sources": [ "test_exception.c" ]
|
||||
}
|
||||
]
|
||||
|
@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../../common');
|
||||
const test_exception = require(`./build/${common.buildType}/test_exception`);
|
||||
const test_exception = require(`./build/${common.buildType}/binding`);
|
||||
const assert = require('assert');
|
||||
const theError = new Error('Some error');
|
||||
function throwTheError() {
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "test_fatal",
|
||||
"target_name": "binding",
|
||||
"sources": [ "test_fatal.c" ]
|
||||
}
|
||||
]
|
||||
|
@ -2,7 +2,7 @@
|
||||
const common = require('../../common');
|
||||
const assert = require('assert');
|
||||
const child_process = require('child_process');
|
||||
const test_fatal = require(`./build/${common.buildType}/test_fatal`);
|
||||
const test_fatal = require(`./build/${common.buildType}/binding`);
|
||||
|
||||
// Test in a child process because the test code will trigger a fatal error
|
||||
// that crashes the process.
|
||||
|
@ -2,7 +2,7 @@
|
||||
const common = require('../../common');
|
||||
const assert = require('assert');
|
||||
const child_process = require('child_process');
|
||||
const test_fatal = require(`./build/${common.buildType}/test_fatal`);
|
||||
const test_fatal = require(`./build/${common.buildType}/binding`);
|
||||
|
||||
// Test in a child process because the test code will trigger a fatal error
|
||||
// that crashes the process.
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "test_function",
|
||||
"target_name": "binding",
|
||||
"sources": [ "test_function.c" ]
|
||||
}
|
||||
]
|
||||
|
@ -3,7 +3,7 @@ const common = require('../../common');
|
||||
const assert = require('assert');
|
||||
|
||||
// testing api calls for function
|
||||
const test_function = require(`./build/${common.buildType}/test_function`);
|
||||
const test_function = require(`./build/${common.buildType}/binding`);
|
||||
|
||||
|
||||
function func1() {
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "test_general",
|
||||
"target_name": "binding",
|
||||
"sources": [ "test_general.c" ]
|
||||
}
|
||||
]
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Flags: --expose-gc
|
||||
|
||||
const common = require('../../common');
|
||||
const test_general = require(`./build/${common.buildType}/test_general`);
|
||||
const test_general = require(`./build/${common.buildType}/binding`);
|
||||
const assert = require('assert');
|
||||
|
||||
const val1 = '1';
|
||||
|
@ -2,7 +2,7 @@
|
||||
const common = require('../../common');
|
||||
const assert = require('assert');
|
||||
|
||||
const test_globals = require(`./build/${common.buildType}/test_general`);
|
||||
const test_globals = require(`./build/${common.buildType}/binding`);
|
||||
|
||||
assert.strictEqual(test_globals.getUndefined(), undefined);
|
||||
assert.strictEqual(test_globals.getNull(), null);
|
||||
|
@ -6,7 +6,7 @@ const assert = require('assert');
|
||||
|
||||
// addon is referenced through the eval expression in testFile
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const addon = require(`./build/${common.buildType}/test_general`);
|
||||
const addon = require(`./build/${common.buildType}/binding`);
|
||||
const path = require('path');
|
||||
|
||||
// This test depends on a number of V8 tests.
|
||||
|
@ -5,7 +5,7 @@ const assert = require('assert');
|
||||
|
||||
// addon is referenced through the eval expression in testFile
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const addon = require(`./build/${common.buildType}/test_general`);
|
||||
const addon = require(`./build/${common.buildType}/binding`);
|
||||
|
||||
const testCase = '(41.92 + 0.08);';
|
||||
const expected = 42;
|
||||
|
@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../../common');
|
||||
const addon = require(`./build/${common.buildType}/test_general`);
|
||||
const addon = require(`./build/${common.buildType}/binding`);
|
||||
const assert = require('assert');
|
||||
|
||||
addon.createNapiError();
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "test_handle_scope",
|
||||
"target_name": "binding",
|
||||
"sources": [ "test_handle_scope.c" ]
|
||||
}
|
||||
]
|
||||
|
@ -3,8 +3,7 @@ const common = require('../../common');
|
||||
const assert = require('assert');
|
||||
|
||||
// testing handle scope api calls
|
||||
const testHandleScope =
|
||||
require(`./build/${common.buildType}/test_handle_scope`);
|
||||
const testHandleScope = require(`./build/${common.buildType}/binding`);
|
||||
|
||||
testHandleScope.NewScope();
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "test_number",
|
||||
"target_name": "binding",
|
||||
"sources": [ "test_number.c" ]
|
||||
}
|
||||
]
|
||||
|
@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
const common = require('../../common');
|
||||
const assert = require('assert');
|
||||
const test_number = require(`./build/${common.buildType}/test_number`);
|
||||
const test_number = require(`./build/${common.buildType}/binding`);
|
||||
|
||||
|
||||
// testing api calls for number
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "test_object",
|
||||
"target_name": "binding",
|
||||
"sources": [ "test_object.c" ]
|
||||
}
|
||||
]
|
||||
|
@ -3,7 +3,7 @@ const common = require('../../common');
|
||||
const assert = require('assert');
|
||||
|
||||
// Testing api calls for objects
|
||||
const test_object = require(`./build/${common.buildType}/test_object`);
|
||||
const test_object = require(`./build/${common.buildType}/binding`);
|
||||
|
||||
|
||||
const object = {
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "test_promise",
|
||||
"target_name": "binding",
|
||||
"sources": [ "test_promise.c" ]
|
||||
}
|
||||
]
|
||||
|
@ -5,7 +5,7 @@ const common = require('../../common');
|
||||
// This tests the promise-related n-api calls
|
||||
|
||||
const assert = require('assert');
|
||||
const test_promise = require(`./build/${common.buildType}/test_promise`);
|
||||
const test_promise = require(`./build/${common.buildType}/binding`);
|
||||
|
||||
common.crashOnUnhandledRejection();
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "test_properties",
|
||||
"target_name": "binding",
|
||||
"sources": [ "test_properties.c" ]
|
||||
}
|
||||
]
|
||||
|
@ -5,7 +5,7 @@ const readonlyErrorRE =
|
||||
/^TypeError: Cannot assign to read only property '.*' of object '#<Object>'$/;
|
||||
|
||||
// Testing api calls for defining properties
|
||||
const test_object = require(`./build/${common.buildType}/test_properties`);
|
||||
const test_object = require(`./build/${common.buildType}/binding`);
|
||||
|
||||
assert.strictEqual(test_object.echo('hello'), 'hello');
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "test_reference",
|
||||
"target_name": "binding",
|
||||
"sources": [ "test_reference.c" ]
|
||||
}
|
||||
]
|
||||
|
@ -4,7 +4,7 @@
|
||||
const common = require('../../common');
|
||||
const assert = require('assert');
|
||||
|
||||
const test_reference = require(`./build/${common.buildType}/test_reference`);
|
||||
const test_reference = require(`./build/${common.buildType}/binding`);
|
||||
|
||||
// This test script uses external values with finalizer callbacks
|
||||
// in order to track when values get garbage-collected. Each invocation
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "test_string",
|
||||
"target_name": "binding",
|
||||
"sources": [ "test_string.c" ]
|
||||
}
|
||||
]
|
||||
|
@ -3,7 +3,7 @@ const common = require('../../common');
|
||||
const assert = require('assert');
|
||||
|
||||
// testing api calls for string
|
||||
const test_string = require(`./build/${common.buildType}/test_string`);
|
||||
const test_string = require(`./build/${common.buildType}/binding`);
|
||||
|
||||
const empty = '';
|
||||
assert.strictEqual(test_string.TestLatin1(empty), empty);
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "test_symbol",
|
||||
"target_name": "binding",
|
||||
"sources": [ "test_symbol.c" ]
|
||||
}
|
||||
]
|
||||
|
@ -3,7 +3,7 @@ const common = require('../../common');
|
||||
const assert = require('assert');
|
||||
|
||||
// testing api calls for symbol
|
||||
const test_symbol = require(`./build/${common.buildType}/test_symbol`);
|
||||
const test_symbol = require(`./build/${common.buildType}/binding`);
|
||||
|
||||
const sym = test_symbol.New('test');
|
||||
assert.strictEqual(sym.toString(), 'Symbol(test)');
|
||||
|
@ -3,7 +3,7 @@ const common = require('../../common');
|
||||
const assert = require('assert');
|
||||
|
||||
// testing api calls for symbol
|
||||
const test_symbol = require(`./build/${common.buildType}/test_symbol`);
|
||||
const test_symbol = require(`./build/${common.buildType}/binding`);
|
||||
|
||||
const fooSym = test_symbol.New('foo');
|
||||
const myObj = {};
|
||||
|
@ -3,7 +3,7 @@ const common = require('../../common');
|
||||
const assert = require('assert');
|
||||
|
||||
// testing api calls for symbol
|
||||
const test_symbol = require(`./build/${common.buildType}/test_symbol`);
|
||||
const test_symbol = require(`./build/${common.buildType}/binding`);
|
||||
|
||||
assert.notStrictEqual(test_symbol.New(), test_symbol.New());
|
||||
assert.notStrictEqual(test_symbol.New('foo'), test_symbol.New('foo'));
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "test_typedarray",
|
||||
"target_name": "binding",
|
||||
"sources": [ "test_typedarray.c" ]
|
||||
}
|
||||
]
|
||||
|
@ -3,7 +3,7 @@ const common = require('../../common');
|
||||
const assert = require('assert');
|
||||
|
||||
// Testing api calls for arrays
|
||||
const test_typedarray = require(`./build/${common.buildType}/test_typedarray`);
|
||||
const test_typedarray = require(`./build/${common.buildType}/binding`);
|
||||
|
||||
const byteArray = new Uint8Array(3);
|
||||
byteArray[0] = 0;
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "test_uv_loop",
|
||||
"target_name": "binding",
|
||||
"sources": [ "test_uv_loop.cc" ]
|
||||
}
|
||||
]
|
||||
|
@ -1,5 +1,5 @@
|
||||
'use strict';
|
||||
const common = require('../../common');
|
||||
const { SetImmediate } = require(`./build/${common.buildType}/test_uv_loop`);
|
||||
const { SetImmediate } = require(`./build/${common.buildType}/binding`);
|
||||
|
||||
SetImmediate(common.mustCall());
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "test_warning",
|
||||
"target_name": "binding",
|
||||
"sources": [ "test_warning.c" ]
|
||||
},
|
||||
{
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
if (process.argv[2] === 'child') {
|
||||
const common = require('../../common');
|
||||
console.log(require(`./build/${common.buildType}/test_warning`));
|
||||
console.log(require(`./build/${common.buildType}/binding`));
|
||||
console.log(require(`./build/${common.buildType}/test_warning2`));
|
||||
} else {
|
||||
const run = require('child_process').spawnSync;
|
||||
|
2
test/addons/.gitignore
vendored
2
test/addons/.gitignore
vendored
@ -1,5 +1,3 @@
|
||||
.buildstamp
|
||||
.docbuildstamp
|
||||
Makefile
|
||||
*.Makefile
|
||||
*.mk
|
||||
|
52
test/addons/01_function_arguments/binding.cc
Normal file
52
test/addons/01_function_arguments/binding.cc
Normal file
@ -0,0 +1,52 @@
|
||||
// Auto-generated by `node tools/doc/addon-verify.js`
|
||||
// binding.cc
|
||||
#include <node.h>
|
||||
|
||||
namespace demo {
|
||||
|
||||
using v8::Exception;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::Isolate;
|
||||
using v8::Local;
|
||||
using v8::Number;
|
||||
using v8::Object;
|
||||
using v8::String;
|
||||
using v8::Value;
|
||||
|
||||
// This is the implementation of the "add" method
|
||||
// Input arguments are passed using the
|
||||
// const FunctionCallbackInfo<Value>& args struct
|
||||
void Add(const FunctionCallbackInfo<Value>& args) {
|
||||
Isolate* isolate = args.GetIsolate();
|
||||
|
||||
// Check the number of arguments passed.
|
||||
if (args.Length() < 2) {
|
||||
// Throw an Error that is passed back to JavaScript
|
||||
isolate->ThrowException(Exception::TypeError(
|
||||
String::NewFromUtf8(isolate, "Wrong number of arguments")));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the argument types
|
||||
if (!args[0]->IsNumber() || !args[1]->IsNumber()) {
|
||||
isolate->ThrowException(Exception::TypeError(
|
||||
String::NewFromUtf8(isolate, "Wrong arguments")));
|
||||
return;
|
||||
}
|
||||
|
||||
// Perform the operation
|
||||
double value = args[0]->NumberValue() + args[1]->NumberValue();
|
||||
Local<Number> num = Number::New(isolate, value);
|
||||
|
||||
// Set the return value (using the passed in
|
||||
// FunctionCallbackInfo<Value>&)
|
||||
args.GetReturnValue().Set(num);
|
||||
}
|
||||
|
||||
void Init(Local<Object> exports) {
|
||||
NODE_SET_METHOD(exports, "add", Add);
|
||||
}
|
||||
|
||||
NODE_MODULE(NODE_GYP_MODULE_NAME, Init)
|
||||
|
||||
} // namespace demo
|
2
test/addons/01_function_arguments/binding.gyp
Normal file
2
test/addons/01_function_arguments/binding.gyp
Normal file
@ -0,0 +1,2 @@
|
||||
# Auto-generated by `node tools/doc/addon-verify.js`
|
||||
{"targets":[{"target_name":"binding","defines":["V8_DEPRECATION_WARNINGS=1"],"sources":["binding.cc","test.js"]}]}
|
7
test/addons/01_function_arguments/test.js
Normal file
7
test/addons/01_function_arguments/test.js
Normal file
@ -0,0 +1,7 @@
|
||||
// Auto-generated by `node tools/doc/addon-verify.js`
|
||||
'use strict';
|
||||
const common = require('../../common');
|
||||
// test.js
|
||||
const binding = require(`./build/${common.buildType}/binding`);
|
||||
|
||||
console.log('This should be eight:', binding.add(3, 5));
|
30
test/addons/02_callbacks/binding.cc
Normal file
30
test/addons/02_callbacks/binding.cc
Normal file
@ -0,0 +1,30 @@
|
||||
// Auto-generated by `node tools/doc/addon-verify.js`
|
||||
// binding.cc
|
||||
#include <node.h>
|
||||
|
||||
namespace demo {
|
||||
|
||||
using v8::Function;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::Isolate;
|
||||
using v8::Local;
|
||||
using v8::Null;
|
||||
using v8::Object;
|
||||
using v8::String;
|
||||
using v8::Value;
|
||||
|
||||
void RunCallback(const FunctionCallbackInfo<Value>& args) {
|
||||
Isolate* isolate = args.GetIsolate();
|
||||
Local<Function> cb = Local<Function>::Cast(args[0]);
|
||||
const unsigned argc = 1;
|
||||
Local<Value> argv[argc] = { String::NewFromUtf8(isolate, "hello world") };
|
||||
cb->Call(Null(isolate), argc, argv);
|
||||
}
|
||||
|
||||
void Init(Local<Object> exports, Local<Object> module) {
|
||||
NODE_SET_METHOD(module, "exports", RunCallback);
|
||||
}
|
||||
|
||||
NODE_MODULE(NODE_GYP_MODULE_NAME, Init)
|
||||
|
||||
} // namespace demo
|
2
test/addons/02_callbacks/binding.gyp
Normal file
2
test/addons/02_callbacks/binding.gyp
Normal file
@ -0,0 +1,2 @@
|
||||
# Auto-generated by `node tools/doc/addon-verify.js`
|
||||
{"targets":[{"target_name":"binding","defines":["V8_DEPRECATION_WARNINGS=1"],"sources":["binding.cc","test.js"]}]}
|
10
test/addons/02_callbacks/test.js
Normal file
10
test/addons/02_callbacks/test.js
Normal file
@ -0,0 +1,10 @@
|
||||
// Auto-generated by `node tools/doc/addon-verify.js`
|
||||
'use strict';
|
||||
const common = require('../../common');
|
||||
// test.js
|
||||
const binding = require(`./build/${common.buildType}/binding`);
|
||||
|
||||
binding((msg) => {
|
||||
console.log(msg);
|
||||
// Prints: 'hello world'
|
||||
});
|
29
test/addons/03_object_factory/binding.cc
Normal file
29
test/addons/03_object_factory/binding.cc
Normal file
@ -0,0 +1,29 @@
|
||||
// Auto-generated by `node tools/doc/addon-verify.js`
|
||||
// binding.cc
|
||||
#include <node.h>
|
||||
|
||||
namespace demo {
|
||||
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::Isolate;
|
||||
using v8::Local;
|
||||
using v8::Object;
|
||||
using v8::String;
|
||||
using v8::Value;
|
||||
|
||||
void CreateObject(const FunctionCallbackInfo<Value>& args) {
|
||||
Isolate* isolate = args.GetIsolate();
|
||||
|
||||
Local<Object> obj = Object::New(isolate);
|
||||
obj->Set(String::NewFromUtf8(isolate, "msg"), args[0]->ToString());
|
||||
|
||||
args.GetReturnValue().Set(obj);
|
||||
}
|
||||
|
||||
void Init(Local<Object> exports, Local<Object> module) {
|
||||
NODE_SET_METHOD(module, "exports", CreateObject);
|
||||
}
|
||||
|
||||
NODE_MODULE(NODE_GYP_MODULE_NAME, Init)
|
||||
|
||||
} // namespace demo
|
2
test/addons/03_object_factory/binding.gyp
Normal file
2
test/addons/03_object_factory/binding.gyp
Normal file
@ -0,0 +1,2 @@
|
||||
# Auto-generated by `node tools/doc/addon-verify.js`
|
||||
{"targets":[{"target_name":"binding","defines":["V8_DEPRECATION_WARNINGS=1"],"sources":["binding.cc","test.js"]}]}
|
10
test/addons/03_object_factory/test.js
Normal file
10
test/addons/03_object_factory/test.js
Normal file
@ -0,0 +1,10 @@
|
||||
// Auto-generated by `node tools/doc/addon-verify.js`
|
||||
'use strict';
|
||||
const common = require('../../common');
|
||||
// test.js
|
||||
const binding = require(`./build/${common.buildType}/binding`);
|
||||
|
||||
const obj1 = binding('hello');
|
||||
const obj2 = binding('world');
|
||||
console.log(obj1.msg, obj2.msg);
|
||||
// Prints: 'hello world'
|
39
test/addons/04_function_factory/binding.cc
Normal file
39
test/addons/04_function_factory/binding.cc
Normal file
@ -0,0 +1,39 @@
|
||||
// Auto-generated by `node tools/doc/addon-verify.js`
|
||||
// binding.cc
|
||||
#include <node.h>
|
||||
|
||||
namespace demo {
|
||||
|
||||
using v8::Function;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::FunctionTemplate;
|
||||
using v8::Isolate;
|
||||
using v8::Local;
|
||||
using v8::Object;
|
||||
using v8::String;
|
||||
using v8::Value;
|
||||
|
||||
void MyFunction(const FunctionCallbackInfo<Value>& args) {
|
||||
Isolate* isolate = args.GetIsolate();
|
||||
args.GetReturnValue().Set(String::NewFromUtf8(isolate, "hello world"));
|
||||
}
|
||||
|
||||
void CreateFunction(const FunctionCallbackInfo<Value>& args) {
|
||||
Isolate* isolate = args.GetIsolate();
|
||||
|
||||
Local<FunctionTemplate> tpl = FunctionTemplate::New(isolate, MyFunction);
|
||||
Local<Function> fn = tpl->GetFunction();
|
||||
|
||||
// omit this to make it anonymous
|
||||
fn->SetName(String::NewFromUtf8(isolate, "theFunction"));
|
||||
|
||||
args.GetReturnValue().Set(fn);
|
||||
}
|
||||
|
||||
void Init(Local<Object> exports, Local<Object> module) {
|
||||
NODE_SET_METHOD(module, "exports", CreateFunction);
|
||||
}
|
||||
|
||||
NODE_MODULE(NODE_GYP_MODULE_NAME, Init)
|
||||
|
||||
} // namespace demo
|
2
test/addons/04_function_factory/binding.gyp
Normal file
2
test/addons/04_function_factory/binding.gyp
Normal file
@ -0,0 +1,2 @@
|
||||
# Auto-generated by `node tools/doc/addon-verify.js`
|
||||
{"targets":[{"target_name":"binding","defines":["V8_DEPRECATION_WARNINGS=1"],"sources":["binding.cc","test.js"]}]}
|
9
test/addons/04_function_factory/test.js
Normal file
9
test/addons/04_function_factory/test.js
Normal file
@ -0,0 +1,9 @@
|
||||
// Auto-generated by `node tools/doc/addon-verify.js`
|
||||
'use strict';
|
||||
const common = require('../../common');
|
||||
// test.js
|
||||
const binding = require(`./build/${common.buildType}/binding`);
|
||||
|
||||
const fn = binding();
|
||||
console.log(fn());
|
||||
// Prints: 'hello world'
|
17
test/addons/05_wrapping_c_objects/binding.cc
Normal file
17
test/addons/05_wrapping_c_objects/binding.cc
Normal file
@ -0,0 +1,17 @@
|
||||
// Auto-generated by `node tools/doc/addon-verify.js`
|
||||
// binding.cc
|
||||
#include <node.h>
|
||||
#include "myobject.h"
|
||||
|
||||
namespace demo {
|
||||
|
||||
using v8::Local;
|
||||
using v8::Object;
|
||||
|
||||
void InitAll(Local<Object> exports) {
|
||||
MyObject::Init(exports);
|
||||
}
|
||||
|
||||
NODE_MODULE(NODE_GYP_MODULE_NAME, InitAll)
|
||||
|
||||
} // namespace demo
|
2
test/addons/05_wrapping_c_objects/binding.gyp
Normal file
2
test/addons/05_wrapping_c_objects/binding.gyp
Normal file
@ -0,0 +1,2 @@
|
||||
# Auto-generated by `node tools/doc/addon-verify.js`
|
||||
{"targets":[{"target_name":"binding","defines":["V8_DEPRECATION_WARNINGS=1"],"sources":["binding.cc","myobject.h","myobject.cc","test.js"]}]}
|
73
test/addons/05_wrapping_c_objects/myobject.cc
Normal file
73
test/addons/05_wrapping_c_objects/myobject.cc
Normal file
@ -0,0 +1,73 @@
|
||||
// Auto-generated by `node tools/doc/addon-verify.js`
|
||||
// myobject.cc
|
||||
#include "myobject.h"
|
||||
|
||||
namespace demo {
|
||||
|
||||
using v8::Context;
|
||||
using v8::Function;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::FunctionTemplate;
|
||||
using v8::Isolate;
|
||||
using v8::Local;
|
||||
using v8::Number;
|
||||
using v8::Object;
|
||||
using v8::Persistent;
|
||||
using v8::String;
|
||||
using v8::Value;
|
||||
|
||||
Persistent<Function> MyObject::constructor;
|
||||
|
||||
MyObject::MyObject(double value) : value_(value) {
|
||||
}
|
||||
|
||||
MyObject::~MyObject() {
|
||||
}
|
||||
|
||||
void MyObject::Init(Local<Object> exports) {
|
||||
Isolate* isolate = exports->GetIsolate();
|
||||
|
||||
// Prepare constructor template
|
||||
Local<FunctionTemplate> tpl = FunctionTemplate::New(isolate, New);
|
||||
tpl->SetClassName(String::NewFromUtf8(isolate, "MyObject"));
|
||||
tpl->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
|
||||
// Prototype
|
||||
NODE_SET_PROTOTYPE_METHOD(tpl, "plusOne", PlusOne);
|
||||
|
||||
constructor.Reset(isolate, tpl->GetFunction());
|
||||
exports->Set(String::NewFromUtf8(isolate, "MyObject"),
|
||||
tpl->GetFunction());
|
||||
}
|
||||
|
||||
void MyObject::New(const FunctionCallbackInfo<Value>& args) {
|
||||
Isolate* isolate = args.GetIsolate();
|
||||
|
||||
if (args.IsConstructCall()) {
|
||||
// Invoked as constructor: `new MyObject(...)`
|
||||
double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
|
||||
MyObject* obj = new MyObject(value);
|
||||
obj->Wrap(args.This());
|
||||
args.GetReturnValue().Set(args.This());
|
||||
} else {
|
||||
// Invoked as plain function `MyObject(...)`, turn into construct call.
|
||||
const int argc = 1;
|
||||
Local<Value> argv[argc] = { args[0] };
|
||||
Local<Context> context = isolate->GetCurrentContext();
|
||||
Local<Function> cons = Local<Function>::New(isolate, constructor);
|
||||
Local<Object> result =
|
||||
cons->NewInstance(context, argc, argv).ToLocalChecked();
|
||||
args.GetReturnValue().Set(result);
|
||||
}
|
||||
}
|
||||
|
||||
void MyObject::PlusOne(const FunctionCallbackInfo<Value>& args) {
|
||||
Isolate* isolate = args.GetIsolate();
|
||||
|
||||
MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.Holder());
|
||||
obj->value_ += 1;
|
||||
|
||||
args.GetReturnValue().Set(Number::New(isolate, obj->value_));
|
||||
}
|
||||
|
||||
} // namespace demo
|
27
test/addons/05_wrapping_c_objects/myobject.h
Normal file
27
test/addons/05_wrapping_c_objects/myobject.h
Normal file
@ -0,0 +1,27 @@
|
||||
// Auto-generated by `node tools/doc/addon-verify.js`
|
||||
// myobject.h
|
||||
#ifndef MYOBJECT_H // NOLINT(build/header_guard)
|
||||
#define MYOBJECT_H // NOLINT(build/header_guard)
|
||||
|
||||
#include <node.h>
|
||||
#include <node_object_wrap.h>
|
||||
|
||||
namespace demo {
|
||||
|
||||
class MyObject : public node::ObjectWrap {
|
||||
public:
|
||||
static void Init(v8::Local<v8::Object> exports);
|
||||
|
||||
private:
|
||||
explicit MyObject(double value = 0);
|
||||
~MyObject();
|
||||
|
||||
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void PlusOne(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static v8::Persistent<v8::Function> constructor;
|
||||
double value_;
|
||||
};
|
||||
|
||||
} // namespace demo
|
||||
|
||||
#endif // NOLINT(build/header_guard)
|
13
test/addons/05_wrapping_c_objects/test.js
Normal file
13
test/addons/05_wrapping_c_objects/test.js
Normal file
@ -0,0 +1,13 @@
|
||||
// Auto-generated by `node tools/doc/addon-verify.js`
|
||||
'use strict';
|
||||
const common = require('../../common');
|
||||
// test.js
|
||||
const binding = require(`./build/${common.buildType}/binding`);
|
||||
|
||||
const obj = new binding.MyObject(10);
|
||||
console.log(obj.plusOne());
|
||||
// Prints: 11
|
||||
console.log(obj.plusOne());
|
||||
// Prints: 12
|
||||
console.log(obj.plusOne());
|
||||
// Prints: 13
|
27
test/addons/06_factory_of_wrapped_objects/binding.cc
Normal file
27
test/addons/06_factory_of_wrapped_objects/binding.cc
Normal file
@ -0,0 +1,27 @@
|
||||
// Auto-generated by `node tools/doc/addon-verify.js`
|
||||
// binding.cc
|
||||
#include <node.h>
|
||||
#include "myobject.h"
|
||||
|
||||
namespace demo {
|
||||
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::Isolate;
|
||||
using v8::Local;
|
||||
using v8::Object;
|
||||
using v8::String;
|
||||
using v8::Value;
|
||||
|
||||
void CreateObject(const FunctionCallbackInfo<Value>& args) {
|
||||
MyObject::NewInstance(args);
|
||||
}
|
||||
|
||||
void InitAll(Local<Object> exports, Local<Object> module) {
|
||||
MyObject::Init(exports->GetIsolate());
|
||||
|
||||
NODE_SET_METHOD(module, "exports", CreateObject);
|
||||
}
|
||||
|
||||
NODE_MODULE(NODE_GYP_MODULE_NAME, InitAll)
|
||||
|
||||
} // namespace demo
|
2
test/addons/06_factory_of_wrapped_objects/binding.gyp
Normal file
2
test/addons/06_factory_of_wrapped_objects/binding.gyp
Normal file
@ -0,0 +1,2 @@
|
||||
# Auto-generated by `node tools/doc/addon-verify.js`
|
||||
{"targets":[{"target_name":"binding","defines":["V8_DEPRECATION_WARNINGS=1"],"sources":["binding.cc","myobject.h","myobject.cc","test.js"]}]}
|
83
test/addons/06_factory_of_wrapped_objects/myobject.cc
Normal file
83
test/addons/06_factory_of_wrapped_objects/myobject.cc
Normal file
@ -0,0 +1,83 @@
|
||||
// Auto-generated by `node tools/doc/addon-verify.js`
|
||||
// myobject.cc
|
||||
#include <node.h>
|
||||
#include "myobject.h"
|
||||
|
||||
namespace demo {
|
||||
|
||||
using v8::Context;
|
||||
using v8::Function;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::FunctionTemplate;
|
||||
using v8::Isolate;
|
||||
using v8::Local;
|
||||
using v8::Number;
|
||||
using v8::Object;
|
||||
using v8::Persistent;
|
||||
using v8::String;
|
||||
using v8::Value;
|
||||
|
||||
Persistent<Function> MyObject::constructor;
|
||||
|
||||
MyObject::MyObject(double value) : value_(value) {
|
||||
}
|
||||
|
||||
MyObject::~MyObject() {
|
||||
}
|
||||
|
||||
void MyObject::Init(Isolate* isolate) {
|
||||
// Prepare constructor template
|
||||
Local<FunctionTemplate> tpl = FunctionTemplate::New(isolate, New);
|
||||
tpl->SetClassName(String::NewFromUtf8(isolate, "MyObject"));
|
||||
tpl->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
|
||||
// Prototype
|
||||
NODE_SET_PROTOTYPE_METHOD(tpl, "plusOne", PlusOne);
|
||||
|
||||
constructor.Reset(isolate, tpl->GetFunction());
|
||||
}
|
||||
|
||||
void MyObject::New(const FunctionCallbackInfo<Value>& args) {
|
||||
Isolate* isolate = args.GetIsolate();
|
||||
|
||||
if (args.IsConstructCall()) {
|
||||
// Invoked as constructor: `new MyObject(...)`
|
||||
double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
|
||||
MyObject* obj = new MyObject(value);
|
||||
obj->Wrap(args.This());
|
||||
args.GetReturnValue().Set(args.This());
|
||||
} else {
|
||||
// Invoked as plain function `MyObject(...)`, turn into construct call.
|
||||
const int argc = 1;
|
||||
Local<Value> argv[argc] = { args[0] };
|
||||
Local<Function> cons = Local<Function>::New(isolate, constructor);
|
||||
Local<Context> context = isolate->GetCurrentContext();
|
||||
Local<Object> instance =
|
||||
cons->NewInstance(context, argc, argv).ToLocalChecked();
|
||||
args.GetReturnValue().Set(instance);
|
||||
}
|
||||
}
|
||||
|
||||
void MyObject::NewInstance(const FunctionCallbackInfo<Value>& args) {
|
||||
Isolate* isolate = args.GetIsolate();
|
||||
|
||||
const unsigned argc = 1;
|
||||
Local<Value> argv[argc] = { args[0] };
|
||||
Local<Function> cons = Local<Function>::New(isolate, constructor);
|
||||
Local<Context> context = isolate->GetCurrentContext();
|
||||
Local<Object> instance =
|
||||
cons->NewInstance(context, argc, argv).ToLocalChecked();
|
||||
|
||||
args.GetReturnValue().Set(instance);
|
||||
}
|
||||
|
||||
void MyObject::PlusOne(const FunctionCallbackInfo<Value>& args) {
|
||||
Isolate* isolate = args.GetIsolate();
|
||||
|
||||
MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.Holder());
|
||||
obj->value_ += 1;
|
||||
|
||||
args.GetReturnValue().Set(Number::New(isolate, obj->value_));
|
||||
}
|
||||
|
||||
} // namespace demo
|
28
test/addons/06_factory_of_wrapped_objects/myobject.h
Normal file
28
test/addons/06_factory_of_wrapped_objects/myobject.h
Normal file
@ -0,0 +1,28 @@
|
||||
// Auto-generated by `node tools/doc/addon-verify.js`
|
||||
// myobject.h
|
||||
#ifndef MYOBJECT_H // NOLINT(build/header_guard)
|
||||
#define MYOBJECT_H // NOLINT(build/header_guard)
|
||||
|
||||
#include <node.h>
|
||||
#include <node_object_wrap.h>
|
||||
|
||||
namespace demo {
|
||||
|
||||
class MyObject : public node::ObjectWrap {
|
||||
public:
|
||||
static void Init(v8::Isolate* isolate);
|
||||
static void NewInstance(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
|
||||
private:
|
||||
explicit MyObject(double value = 0);
|
||||
~MyObject();
|
||||
|
||||
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void PlusOne(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static v8::Persistent<v8::Function> constructor;
|
||||
double value_;
|
||||
};
|
||||
|
||||
} // namespace demo
|
||||
|
||||
#endif // NOLINT(build/header_guard)
|
21
test/addons/06_factory_of_wrapped_objects/test.js
Normal file
21
test/addons/06_factory_of_wrapped_objects/test.js
Normal file
@ -0,0 +1,21 @@
|
||||
// Auto-generated by `node tools/doc/addon-verify.js`
|
||||
'use strict';
|
||||
const common = require('../../common');
|
||||
// test.js
|
||||
const createObject = require(`./build/${common.buildType}/binding`);
|
||||
|
||||
const obj = createObject(10);
|
||||
console.log(obj.plusOne());
|
||||
// Prints: 11
|
||||
console.log(obj.plusOne());
|
||||
// Prints: 12
|
||||
console.log(obj.plusOne());
|
||||
// Prints: 13
|
||||
|
||||
const obj2 = createObject(20);
|
||||
console.log(obj2.plusOne());
|
||||
// Prints: 21
|
||||
console.log(obj2.plusOne());
|
||||
// Prints: 22
|
||||
console.log(obj2.plusOne());
|
||||
// Prints: 23
|
42
test/addons/07_passing_wrapped_objects_around/binding.cc
Normal file
42
test/addons/07_passing_wrapped_objects_around/binding.cc
Normal file
@ -0,0 +1,42 @@
|
||||
// Auto-generated by `node tools/doc/addon-verify.js`
|
||||
// binding.cc
|
||||
#include <node.h>
|
||||
#include <node_object_wrap.h>
|
||||
#include "myobject.h"
|
||||
|
||||
namespace demo {
|
||||
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::Isolate;
|
||||
using v8::Local;
|
||||
using v8::Number;
|
||||
using v8::Object;
|
||||
using v8::String;
|
||||
using v8::Value;
|
||||
|
||||
void CreateObject(const FunctionCallbackInfo<Value>& args) {
|
||||
MyObject::NewInstance(args);
|
||||
}
|
||||
|
||||
void Add(const FunctionCallbackInfo<Value>& args) {
|
||||
Isolate* isolate = args.GetIsolate();
|
||||
|
||||
MyObject* obj1 = node::ObjectWrap::Unwrap<MyObject>(
|
||||
args[0]->ToObject());
|
||||
MyObject* obj2 = node::ObjectWrap::Unwrap<MyObject>(
|
||||
args[1]->ToObject());
|
||||
|
||||
double sum = obj1->value() + obj2->value();
|
||||
args.GetReturnValue().Set(Number::New(isolate, sum));
|
||||
}
|
||||
|
||||
void InitAll(Local<Object> exports) {
|
||||
MyObject::Init(exports->GetIsolate());
|
||||
|
||||
NODE_SET_METHOD(exports, "createObject", CreateObject);
|
||||
NODE_SET_METHOD(exports, "add", Add);
|
||||
}
|
||||
|
||||
NODE_MODULE(NODE_GYP_MODULE_NAME, InitAll)
|
||||
|
||||
} // namespace demo
|
@ -0,0 +1,2 @@
|
||||
# Auto-generated by `node tools/doc/addon-verify.js`
|
||||
{"targets":[{"target_name":"binding","defines":["V8_DEPRECATION_WARNINGS=1"],"sources":["binding.cc","myobject.h","myobject.cc","test.js"]}]}
|
70
test/addons/07_passing_wrapped_objects_around/myobject.cc
Normal file
70
test/addons/07_passing_wrapped_objects_around/myobject.cc
Normal file
@ -0,0 +1,70 @@
|
||||
// Auto-generated by `node tools/doc/addon-verify.js`
|
||||
// myobject.cc
|
||||
#include <node.h>
|
||||
#include "myobject.h"
|
||||
|
||||
namespace demo {
|
||||
|
||||
using v8::Context;
|
||||
using v8::Function;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::FunctionTemplate;
|
||||
using v8::Isolate;
|
||||
using v8::Local;
|
||||
using v8::Object;
|
||||
using v8::Persistent;
|
||||
using v8::String;
|
||||
using v8::Value;
|
||||
|
||||
Persistent<Function> MyObject::constructor;
|
||||
|
||||
MyObject::MyObject(double value) : value_(value) {
|
||||
}
|
||||
|
||||
MyObject::~MyObject() {
|
||||
}
|
||||
|
||||
void MyObject::Init(Isolate* isolate) {
|
||||
// Prepare constructor template
|
||||
Local<FunctionTemplate> tpl = FunctionTemplate::New(isolate, New);
|
||||
tpl->SetClassName(String::NewFromUtf8(isolate, "MyObject"));
|
||||
tpl->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
|
||||
constructor.Reset(isolate, tpl->GetFunction());
|
||||
}
|
||||
|
||||
void MyObject::New(const FunctionCallbackInfo<Value>& args) {
|
||||
Isolate* isolate = args.GetIsolate();
|
||||
|
||||
if (args.IsConstructCall()) {
|
||||
// Invoked as constructor: `new MyObject(...)`
|
||||
double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
|
||||
MyObject* obj = new MyObject(value);
|
||||
obj->Wrap(args.This());
|
||||
args.GetReturnValue().Set(args.This());
|
||||
} else {
|
||||
// Invoked as plain function `MyObject(...)`, turn into construct call.
|
||||
const int argc = 1;
|
||||
Local<Value> argv[argc] = { args[0] };
|
||||
Local<Context> context = isolate->GetCurrentContext();
|
||||
Local<Function> cons = Local<Function>::New(isolate, constructor);
|
||||
Local<Object> instance =
|
||||
cons->NewInstance(context, argc, argv).ToLocalChecked();
|
||||
args.GetReturnValue().Set(instance);
|
||||
}
|
||||
}
|
||||
|
||||
void MyObject::NewInstance(const FunctionCallbackInfo<Value>& args) {
|
||||
Isolate* isolate = args.GetIsolate();
|
||||
|
||||
const unsigned argc = 1;
|
||||
Local<Value> argv[argc] = { args[0] };
|
||||
Local<Function> cons = Local<Function>::New(isolate, constructor);
|
||||
Local<Context> context = isolate->GetCurrentContext();
|
||||
Local<Object> instance =
|
||||
cons->NewInstance(context, argc, argv).ToLocalChecked();
|
||||
|
||||
args.GetReturnValue().Set(instance);
|
||||
}
|
||||
|
||||
} // namespace demo
|
28
test/addons/07_passing_wrapped_objects_around/myobject.h
Normal file
28
test/addons/07_passing_wrapped_objects_around/myobject.h
Normal file
@ -0,0 +1,28 @@
|
||||
// Auto-generated by `node tools/doc/addon-verify.js`
|
||||
// myobject.h
|
||||
#ifndef MYOBJECT_H // NOLINT(build/header_guard)
|
||||
#define MYOBJECT_H // NOLINT(build/header_guard)
|
||||
|
||||
#include <node.h>
|
||||
#include <node_object_wrap.h>
|
||||
|
||||
namespace demo {
|
||||
|
||||
class MyObject : public node::ObjectWrap {
|
||||
public:
|
||||
static void Init(v8::Isolate* isolate);
|
||||
static void NewInstance(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
inline double value() const { return value_; }
|
||||
|
||||
private:
|
||||
explicit MyObject(double value = 0);
|
||||
~MyObject();
|
||||
|
||||
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static v8::Persistent<v8::Function> constructor;
|
||||
double value_;
|
||||
};
|
||||
|
||||
} // namespace demo
|
||||
|
||||
#endif // NOLINT(build/header_guard)
|
12
test/addons/07_passing_wrapped_objects_around/test.js
Normal file
12
test/addons/07_passing_wrapped_objects_around/test.js
Normal file
@ -0,0 +1,12 @@
|
||||
// Auto-generated by `node tools/doc/addon-verify.js`
|
||||
'use strict';
|
||||
const common = require('../../common');
|
||||
// test.js
|
||||
const binding = require(`./build/${common.buildType}/binding`);
|
||||
|
||||
const obj1 = binding.createObject(10);
|
||||
const obj2 = binding.createObject(20);
|
||||
const result = binding.add(obj1, obj2);
|
||||
|
||||
console.log(result);
|
||||
// Prints: 30
|
47
test/addons/08_void_atexitcallback_args/binding.cc
Normal file
47
test/addons/08_void_atexitcallback_args/binding.cc
Normal file
@ -0,0 +1,47 @@
|
||||
// Auto-generated by `node tools/doc/addon-verify.js`
|
||||
// binding.cc
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <node.h>
|
||||
|
||||
namespace demo {
|
||||
|
||||
using node::AtExit;
|
||||
using v8::HandleScope;
|
||||
using v8::Isolate;
|
||||
using v8::Local;
|
||||
using v8::Object;
|
||||
|
||||
static char cookie[] = "yum yum";
|
||||
static int at_exit_cb1_called = 0;
|
||||
static int at_exit_cb2_called = 0;
|
||||
|
||||
static void at_exit_cb1(void* arg) {
|
||||
Isolate* isolate = static_cast<Isolate*>(arg);
|
||||
HandleScope scope(isolate);
|
||||
Local<Object> obj = Object::New(isolate);
|
||||
assert(!obj.IsEmpty()); // assert VM is still alive
|
||||
assert(obj->IsObject());
|
||||
at_exit_cb1_called++;
|
||||
}
|
||||
|
||||
static void at_exit_cb2(void* arg) {
|
||||
assert(arg == static_cast<void*>(cookie));
|
||||
at_exit_cb2_called++;
|
||||
}
|
||||
|
||||
static void sanity_check(void*) {
|
||||
assert(at_exit_cb1_called == 1);
|
||||
assert(at_exit_cb2_called == 2);
|
||||
}
|
||||
|
||||
void init(Local<Object> exports) {
|
||||
AtExit(at_exit_cb2, cookie);
|
||||
AtExit(at_exit_cb2, cookie);
|
||||
AtExit(at_exit_cb1, exports->GetIsolate());
|
||||
AtExit(sanity_check);
|
||||
}
|
||||
|
||||
NODE_MODULE(NODE_GYP_MODULE_NAME, init)
|
||||
|
||||
} // namespace demo
|
2
test/addons/08_void_atexitcallback_args/binding.gyp
Normal file
2
test/addons/08_void_atexitcallback_args/binding.gyp
Normal file
@ -0,0 +1,2 @@
|
||||
# Auto-generated by `node tools/doc/addon-verify.js`
|
||||
{"targets":[{"target_name":"binding","defines":["V8_DEPRECATION_WARNINGS=1"],"sources":["binding.cc","test.js"]}]}
|
5
test/addons/08_void_atexitcallback_args/test.js
Normal file
5
test/addons/08_void_atexitcallback_args/test.js
Normal file
@ -0,0 +1,5 @@
|
||||
// Auto-generated by `node tools/doc/addon-verify.js`
|
||||
'use strict';
|
||||
const common = require('../../common');
|
||||
// test.js
|
||||
require(`./build/${common.buildType}/binding`);
|
6
test/addons/openssl-client-cert-engine/binding.cc
Normal file
6
test/addons/openssl-client-cert-engine/binding.cc
Normal file
@ -0,0 +1,6 @@
|
||||
#include "node.h"
|
||||
#include "v8.h"
|
||||
|
||||
inline void Initialize(v8::Local<v8::Object>) {}
|
||||
|
||||
NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize)
|
@ -1,5 +1,9 @@
|
||||
{
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'binding',
|
||||
'sources': [ 'binding.cc' ],
|
||||
},
|
||||
{
|
||||
'target_name': 'testengine',
|
||||
'type': 'none',
|
||||
|
@ -5,6 +5,7 @@ const fs = require('fs');
|
||||
const path = require('path');
|
||||
const marked = require('marked');
|
||||
|
||||
const auto = 'Auto-generated by `node tools/doc/addon-verify.js`';
|
||||
const rootDir = path.resolve(__dirname, '..', '..');
|
||||
const doc = path.resolve(rootDir, 'doc', 'api', 'addons.md');
|
||||
const verifyDir = path.resolve(rootDir, 'test', 'addons');
|
||||
@ -49,12 +50,20 @@ for (const header in addons) {
|
||||
|
||||
files = Object.entries(files).map(([name, content]) => {
|
||||
if (name === 'test.js') content = boilerplate(name, content);
|
||||
content = `// ${auto}\n${content}`;
|
||||
if (name.endsWith('.h')) {
|
||||
content = content.replace(/(#(ifndef|define) \w+_H)/g,
|
||||
'$1 // NOLINT(build/header_guard)');
|
||||
content = content.replace(/(#endif)$/,
|
||||
'$1 // NOLINT(build/header_guard)');
|
||||
}
|
||||
if (!content.endsWith('\n')) content += '\n'; // Pacify linter.
|
||||
return { name, content, path: path.resolve(dir, name) };
|
||||
});
|
||||
|
||||
files.push({
|
||||
path: path.resolve(dir, 'binding.gyp'),
|
||||
content: JSON.stringify({
|
||||
content: `# ${auto}\n` + JSON.stringify({
|
||||
targets: [
|
||||
{
|
||||
target_name: 'binding',
|
||||
|
Loading…
Reference in New Issue
Block a user