diff --git a/.eslintrc.js b/.eslintrc.js index f59f65f8065c58..8279dfc9c4ab41 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -59,7 +59,7 @@ module.exports = { ], rules: { // ESLint built-in rules - // http://eslint.org/docs/rules + // https://eslint.org/docs/rules/ 'accessor-pairs': 'error', 'array-callback-return': 'error', 'arrow-parens': ['error', 'always'], diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000000000..6fb4f7dc493b6a --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,76 @@ +# Node.js Project Codeowners + +# 1. Codeowners must always be teams, never individuals +# 2. Each codeowner team should contain at least one TSC member +# 3. PRs touching any code with a codeowner must be signed off by at least one +# person on the code owner team. + +./.github/CODEOWNERS @nodejs/tsc + +# net + +# ./deps/cares @nodejs/net +# ./doc/api/dns.md @nodejs/net +# ./doc/api/dgram.md @nodejs/net +# ./doc/api/net.md @nodejs/net +# ./lib/dgram.js @nodejs/net +# ./lib/dns.js @nodejs/net +# ./lib/net.js @nodejs/net @nodejs/quic +# ./lib/internal/dgram.js @nodejs/net +# ./lib/internal/dns/* @nodejs/net +# ./lib/internal/net.js @nodejs/net +# ./lib/internal/socket_list.js @nodejs/net +# ./lib/internal/js_stream_socket.js @nodejs/net +# ./src/cares_wrap.h @nodejs/net +# ./src/connect_wrap.* @nodejs/net +# ./src/connection_wrap.* @nodejs/net +# ./src/node_sockaddr* @nodejs/net +# ./src/tcp_wrap.* @nodejs/net +# ./src/udp_wrap.* @nodejs/net + +# tls/crypto + +# ./lib/internal/crypto/* @nodejs/crypto +# ./lib/internal/tls.js @nodejs/crypto @nodejs/net +# ./lib/crypto.js @nodejs/crypto +# ./lib/tls.js @nodejs/crypto @nodejs/net +# ./src/node_crypto* @nodejs/crypto +# ./src/node_crypto_common* @nodejs/crypto @nodejs/quic + +# http + +# ./deps/llhttp/* @nodejs/http @nodejs/net +# ./doc/api/http.md @nodejs/http @nodejs/net +# ./doc/api/http2.md @nodejs/http @nodejs/net +# ./lib/_http_* @nodejs/http @nodejs/net +# ./lib/http.js @nodejs/http @nodejs/net +# ./lib/https.js @nodejs/crypto @nodejs/net @nodejs/http +# ./src/node_http_common* @nodejs/http @nodejs/http2 @nodejs/quic @nodejs/net +# ./src/node_http_parser.cc @nodejs/http @nodejs/net + +# http2 + +# ./deps/nghttp2/* @nodejs/http2 @nodejs/net +# ./doc/api/http2.md @nodejs/http2 @nodejs/net +# ./lib/http2.js @nodejs/http2 @nodejs/net +# ./lib/internal/http2/* @nodejs/http2 @nodejs/net +# ./src/node_http2* @nodejs/http2 @nodejs/net +# ./src/node_mem* @nodejs/http2 + +# quic + +./deps/ngtcp2/* @nodejs/quic +./deps/nghttp3/* @nodejs/quic +./doc/api/quic.md @nodejs/quic +./lib/internal/quic/* @nodejs/quic +./src/node_bob* @nodejs/quic +./src/quic/* @nodejs/quic + +# modules + +# ./doc/api/modules.md @nodejs/modules +# ./doc/api/esm.md @nodejs/modules +# ./lib/module.js @nodejs/modules +# ./lib/internal/modules/* @nodejs/modules +# ./lib/internal/bootstrap/loaders.js @nodejs/modules +# ./src/module_wrap* @nodejs/modules @nodejs/vm diff --git a/.github/ISSUE_TEMPLATE/4-report-a-flaky-test.md b/.github/ISSUE_TEMPLATE/4-report-a-flaky-test.md new file mode 100644 index 00000000000000..544c9d5f47b0f5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/4-report-a-flaky-test.md @@ -0,0 +1,34 @@ +--- +name: Report a flaky test +about: Report a flaky test in our CI +labels: "CI / flaky test" + +--- + + + +* **Test**: +* **Platform**: +* **Console Output:** +``` +REPLACE ME +``` +* **Build Links**: diff --git a/.github/SUPPORT.md b/.github/SUPPORT.md index 1a086bd2cc59a7..48ad8a90cb77c5 100644 --- a/.github/SUPPORT.md +++ b/.github/SUPPORT.md @@ -17,7 +17,7 @@ resources: * [Questions tagged 'node.js' on Stack Overflow](https://stackoverflow.com/questions/tagged/node.js) * [#node.js channel on chat.freenode.net](https://webchat.freenode.net?channels=node.js&uio=d4) * [Node.js Slack Community](https://node-js.slack.com/) - * To register: [nodeslackers.com](http://www.nodeslackers.com/) + * To register: [nodeslackers.com](https://www.nodeslackers.com/) GitHub issues are for tracking enhancements and bugs, not general support. diff --git a/.github/workflows/build-tarball.yml b/.github/workflows/build-tarball.yml index b706e7ef855de6..3a3138a677b1d6 100644 --- a/.github/workflows/build-tarball.yml +++ b/.github/workflows/build-tarball.yml @@ -63,7 +63,7 @@ jobs: - name: Test run: | cd $TAR_DIR - make run-ci -j2 V=1 + make run-ci -j2 V=1 TEST_CI_ARGS="-p dots" test-tarball-windows: needs: build-tarball runs-on: windows-latest @@ -138,4 +138,4 @@ jobs: - name: Test run: | cd $TAR_DIR - make run-ci -j8 V=1 \ No newline at end of file + make run-ci -j8 V=1 TEST_CI_ARGS="-p dots" diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml index 9b4ebca75c86ca..4453db5c751c7f 100644 --- a/.github/workflows/linters.yml +++ b/.github/workflows/linters.yml @@ -26,7 +26,7 @@ jobs: - name: Set up Python ${{ env.PYTHON_VERSION }} uses: actions/setup-python@v1 with: - PYTHON_VERSION: ${{ env.PYTHON_VERSION }} + python-version: ${{ env.PYTHON_VERSION }} - name: Environment Information run: npx envinfo - name: Lint C/C++ files @@ -64,7 +64,7 @@ jobs: - name: Set up Python ${{ env.PYTHON_VERSION }} uses: actions/setup-python@v1 with: - PYTHON_VERSION: ${{ env.PYTHON_VERSION }} + python-version: ${{ env.PYTHON_VERSION }} - name: Environment Information run: npx envinfo - name: Lint Python diff --git a/.github/workflows/test-asan.yml b/.github/workflows/test-asan.yml index 56ad55f6735804..54d6cae049badb 100644 --- a/.github/workflows/test-asan.yml +++ b/.github/workflows/test-asan.yml @@ -1,6 +1,12 @@ name: test-asan -on: [push, pull_request] +on: + push: + paths-ignore: + - 'doc/**' + pull_request: + paths-ignore: + - 'doc/**' env: PYTHON_VERSION: 3.8 @@ -24,5 +30,5 @@ jobs: run: npx envinfo - name: Build run: make build-ci -j2 V=1 - - name: Test cctest - run: make cctest -j2 V=1 + - name: Test + run: make run-ci -j2 V=1 TEST_CI_ARGS="-p dots" diff --git a/BUILDING.md b/BUILDING.md index 13caddbdc13e98..0a8f24c694222e 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -695,7 +695,7 @@ that works for both your host and target environments. ### Build with a specific ICU You can find other ICU releases at -[the ICU homepage](http://icu-project.org/download). +[the ICU homepage](http://site.icu-project.org/download). Download the file named something like `icu4c-**##.#**-src.tgz` (or `.zip`). @@ -726,7 +726,7 @@ $ ./configure --with-intl=full-icu --with-icu-source=http://url/to/icu.tgz #### Windows First unpack latest ICU to `deps/icu` -[icu4c-**##.#**-src.tgz](http://icu-project.org/download) (or `.zip`) +[icu4c-**##.#**-src.tgz](http://site.icu-project.org/download) (or `.zip`) as `deps/icu` (You'll have: `deps/icu/source/...`) ```console diff --git a/CHANGELOG.md b/CHANGELOG.md index 5399fb3266e5c6..ee9cf67a351426 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,7 +31,8 @@ release. -14.4.0
+14.5.0
+14.4.0
14.3.0
14.2.0
14.1.0
diff --git a/LICENSE b/LICENSE index b0c33eb5f78f67..0443d15f3c60c2 100644 --- a/LICENSE +++ b/LICENSE @@ -1448,6 +1448,39 @@ The externally maintained libraries used by Node.js are: THE POSSIBILITY OF SUCH DAMAGE. """ +- highlight.js, located at doc/api_assets/highlight.pack.js, is licensed as follows: + """ + BSD 3-Clause License + + Copyright (c) 2006, Ivan Sagalaev. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + """ + - node-heapdump, located at src/heap_utils.cc, is licensed as follows: """ ISC License diff --git a/Makefile b/Makefile index 43d23459284609..89cd8f68885865 100644 --- a/Makefile +++ b/Makefile @@ -17,6 +17,7 @@ GNUMAKEFLAGS += --no-print-directory GCOV ?= gcov PWD = $(CURDIR) BUILD_WITH ?= make +FIND ?= find ifdef JOBS PARALLEL_ARGS = -j $(JOBS) @@ -97,13 +98,12 @@ help: ## Print help for targets with comments. # and recreated which can break the addons build when running test-ci # See comments on the build-addons target for some more info ifeq ($(BUILD_WITH), make) -$(NODE_EXE): config.gypi out/Makefile - $(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 - $(MAKE) -C out BUILDTYPE=Debug V=$(V) - if [ ! -r $@ -o ! -L $@ ]; then ln -fs out/Debug/$(NODE_EXE) $@; fi +$(NODE_EXE): build_type:=Release +$(NODE_G_EXE): build_type:=Debug +$(NODE_EXE) $(NODE_G_EXE): config.gypi out/Makefile + $(MAKE) -C out BUILDTYPE=${build_type} V=$(V) + if [ ! -r $@ -o ! -L $@ ]; then \ + ln -fs out/${build_type}/$(NODE_EXE) $@; fi else ifeq ($(BUILD_WITH), ninja) ifeq ($(V),1) @@ -168,7 +168,7 @@ uninstall: ## Uninstalls node from $PREFIX (default=/usr/local). clean: ## Remove build artifacts. $(RM) -r out/Makefile $(NODE_EXE) $(NODE_G_EXE) out/$(BUILDTYPE)/$(NODE_EXE) \ out/$(BUILDTYPE)/node.exp - @if [ -d out ]; then find out/ -name '*.o' -o -name '*.a' -o -name '*.d' | xargs $(RM) -r; fi + @if [ -d out ]; then $(FIND) out/ -name '*.o' -o -name '*.a' -o -name '*.d' | xargs $(RM) -r; fi $(RM) -r node_modules @if [ -d deps/icu ]; then echo deleting deps/icu; $(RM) -r deps/icu; fi $(RM) test.tap @@ -737,7 +737,7 @@ out/doc/api/assets: # If it's not a source tarball, we need to copy assets from doc/api_assets out/doc/api/assets/%: doc/api_assets/% out/doc/api/assets - @cp $< $@ + @cp $< $@ ; $(RM) out/doc/api/assets/README.md run-npm-ci = $(PWD)/$(NPM) ci @@ -772,6 +772,11 @@ out/doc/api/all.json: $(apidocs_json) tools/doc/alljson.js docopen: $(apidocs_html) @$(PYTHON) -mwebbrowser file://$(PWD)/out/doc/api/all.html +.PHONY: docserve +docserve: $(apidocs_html) + @$(PYTHON) -mwebbrowser http://localhost:8000/all.html + @$(PYTHON) -m http.server -d $(PWD)/out/doc/api + .PHONY: docclean docclean: $(RM) -r out/doc @@ -1199,7 +1204,7 @@ LINT_MD_NEWER = -newer tools/.mdlintstamp endif LINT_MD_TARGETS = doc src lib benchmark test tools/doc tools/icu $(wildcard *.md) -LINT_MD_FILES = $(shell find $(LINT_MD_TARGETS) -type f \ +LINT_MD_FILES = $(shell $(FIND) $(LINT_MD_TARGETS) -type f \ ! -path '*node_modules*' ! -path 'test/fixtures/*' -name '*.md' \ $(LINT_MD_NEWER)) run-lint-md = tools/lint-md.js -q -f --no-stdout $(LINT_MD_FILES) @@ -1322,13 +1327,13 @@ else CPPLINT_QUIET = --quiet endif .PHONY: lint-cpp -# Lints the C++ code with cpplint.py and check-imports.py. +# Lints the C++ code with cpplint.py and checkimports.py. lint-cpp: tools/.cpplintstamp tools/.cpplintstamp: $(LINT_CPP_FILES) @echo "Running C++ linter..." @$(PYTHON) tools/cpplint.py $(CPPLINT_QUIET) $? - @$(PYTHON) tools/check-imports.py + @$(PYTHON) tools/checkimports.py $? @touch $@ .PHONY: lint-addon-docs @@ -1378,7 +1383,7 @@ CONFLICT_RE=^>>>>>>> [0-9A-Fa-f]+|^<<<<<<< [A-Za-z]+ # Related CI job: node-test-linter lint-ci: lint-js-ci lint-cpp lint-py lint-md lint-addon-docs @if ! ( grep -IEqrs "$(CONFLICT_RE)" benchmark deps doc lib src test tools ) \ - && ! ( find . -maxdepth 1 -type f | xargs grep -IEqs "$(CONFLICT_RE)" ); then \ + && ! ( $(FIND) . -maxdepth 1 -type f | xargs grep -IEqs "$(CONFLICT_RE)" ); then \ exit 0 ; \ else \ echo "" >&2 ; \ diff --git a/README.md b/README.md index af3a57ccaac992..fda0fc98ea2340 100644 --- a/README.md +++ b/README.md @@ -152,6 +152,7 @@ For information about the governance of the Node.js project, see ### TSC (Technical Steering Committee) + * [addaleax](https://github.com/addaleax) - **Anna Henningsen** <anna@addaleax.net> (she/her) * [apapirovski](https://github.com/apapirovski) - @@ -545,6 +546,7 @@ For information about the governance of the Node.js project, see **Vse Mozhet Byt** <vsemozhetbyt@gmail.com> (he/him) * [whitlockjc](https://github.com/whitlockjc) - **Jeremy Whitlock** <jwhitlock@apache.org> + Collaborators follow the [Collaborator Guide](./doc/guides/collaborator-guide.md) in maintaining the Node.js project. @@ -572,7 +574,7 @@ Primary GPG keys for Node.js Releasers (some Releasers sign with subkeys): To import the full set of trusted release keys: -```shell +```bash gpg --keyserver pool.sks-keyservers.net --recv-keys 4ED778F539E3634C779C87C6D7062848A1AB005C gpg --keyserver pool.sks-keyservers.net --recv-keys 94AE36675C464D64BAFA68DD7434390BDBE9B9C5 gpg --keyserver pool.sks-keyservers.net --recv-keys 71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 @@ -608,6 +610,6 @@ Other keys used to sign some previous releases: [Code of Conduct]: https://github.com/nodejs/admin/blob/master/CODE_OF_CONDUCT.md [Contributing to the project]: CONTRIBUTING.md [Node.js Website]: https://nodejs.org/ -[OpenJS Foundation]: http://openjs.foundation/ +[OpenJS Foundation]: https://openjsf.org/ [Working Groups]: https://github.com/nodejs/TSC/blob/master/WORKING_GROUPS.md [Strategic Initiatives]: https://github.com/nodejs/TSC/blob/master/Strategic-Initiatives.md diff --git a/benchmark/async_hooks/async-resource-vs-destroy.js b/benchmark/async_hooks/async-resource-vs-destroy.js index 52e5e543a6a08d..09898bbe52f939 100644 --- a/benchmark/async_hooks/async-resource-vs-destroy.js +++ b/benchmark/async_hooks/async-resource-vs-destroy.js @@ -138,6 +138,7 @@ function getServeAwait(getCLS, setCLS) { setCLS(Math.random()); await sleep(10); await read(__filename); + if (res.destroyed) return; res.setHeader('content-type', 'application/json'); res.end(JSON.stringify({ cls: getCLS() })); }; @@ -148,6 +149,7 @@ function getServeCallbacks(getCLS, setCLS) { setCLS(Math.random()); setTimeout(() => { readFile(__filename, () => { + if (res.destroyed) return; res.setHeader('content-type', 'application/json'); res.end(JSON.stringify({ cls: getCLS() })); }); diff --git a/benchmark/es/spread-assign.js b/benchmark/es/spread-assign.js index 970512aa6b93d4..c34bb93e762d12 100644 --- a/benchmark/es/spread-assign.js +++ b/benchmark/es/spread-assign.js @@ -15,7 +15,7 @@ function main({ n, context, count, rest, method }) { for (let n = 0; n < count; n++) src[`p${n}`] = n; - let obj; // eslint-disable-line no-unused-vars + let obj; switch (method) { case '_extend': @@ -33,7 +33,7 @@ function main({ n, context, count, rest, method }) { case 'spread': bench.start(); for (let i = 0; i < n; i++) - obj = { ...src }; + obj = { ...src }; // eslint-disable-line no-unused-vars bench.end(n); break; default: diff --git a/benchmark/events/ee-emit.js b/benchmark/events/ee-emit.js index 39bcbb937d6c56..ec35277a9c0214 100644 --- a/benchmark/events/ee-emit.js +++ b/benchmark/events/ee-emit.js @@ -10,6 +10,7 @@ const bench = common.createBenchmark(main, { function main({ n, argc, listeners }) { const ee = new EventEmitter(); + ee.setMaxListeners(listeners + 1); for (let k = 0; k < listeners; k += 1) ee.on('dummy', () => {}); diff --git a/benchmark/events/ee-listeners-many.js b/benchmark/events/ee-listeners-many.js deleted file mode 100644 index bd3f3538d63c92..00000000000000 --- a/benchmark/events/ee-listeners-many.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict'; -const common = require('../common.js'); -const EventEmitter = require('events').EventEmitter; - -const bench = common.createBenchmark(main, { n: [5e6] }); - -function main({ n }) { - const ee = new EventEmitter(); - ee.setMaxListeners(101); - - for (let k = 0; k < 50; k += 1) { - ee.on('dummy0', () => {}); - ee.on('dummy1', () => {}); - } - - bench.start(); - for (let i = 0; i < n; i += 1) { - const dummy = (i % 2 === 0) ? 'dummy0' : 'dummy1'; - ee.listeners(dummy); - } - bench.end(n); -} diff --git a/benchmark/events/ee-listeners.js b/benchmark/events/ee-listeners.js index 867393efffcb04..9de8d04a175b4b 100644 --- a/benchmark/events/ee-listeners.js +++ b/benchmark/events/ee-listeners.js @@ -2,20 +2,34 @@ const common = require('../common.js'); const EventEmitter = require('events').EventEmitter; -const bench = common.createBenchmark(main, { n: [5e6] }); +const bench = common.createBenchmark(main, { + n: [5e6], + listeners: [5, 50], + raw: ['true', 'false'] +}); -function main({ n }) { +function main({ n, listeners, raw }) { const ee = new EventEmitter(); + ee.setMaxListeners(listeners * 2 + 1); - for (let k = 0; k < 5; k += 1) { + for (let k = 0; k < listeners; k += 1) { ee.on('dummy0', () => {}); - ee.on('dummy1', () => {}); + ee.once('dummy1', () => {}); } - bench.start(); - for (let i = 0; i < n; i += 1) { - const dummy = (i % 2 === 0) ? 'dummy0' : 'dummy1'; - ee.listeners(dummy); + if (raw === 'true') { + bench.start(); + for (let i = 0; i < n; i += 1) { + const dummy = (i % 2 === 0) ? 'dummy0' : 'dummy1'; + ee.rawListeners(dummy); + } + bench.end(n); + } else { + bench.start(); + for (let i = 0; i < n; i += 1) { + const dummy = (i % 2 === 0) ? 'dummy0' : 'dummy1'; + ee.listeners(dummy); + } + bench.end(n); } - bench.end(n); } diff --git a/benchmark/events/eventtarget.js b/benchmark/events/eventtarget.js new file mode 100644 index 00000000000000..d2c3ad034ff9b4 --- /dev/null +++ b/benchmark/events/eventtarget.js @@ -0,0 +1,22 @@ +'use strict'; +const common = require('../common.js'); + +const bench = common.createBenchmark(main, { + n: [1e6], + listeners: [1, 5, 10] +}, { flags: ['--expose-internals'] }); + +function main({ n, listeners }) { + const { EventTarget, Event } = require('internal/event_target'); + const target = new EventTarget(); + + for (let n = 0; n < listeners; n++) + target.addEventListener('foo', () => {}); + + bench.start(); + for (let i = 0; i < n; i++) { + target.dispatchEvent(new Event('foo')); + } + bench.end(n); + +} diff --git a/benchmark/http/http_server_for_chunky_client.js b/benchmark/http/http_server_for_chunky_client.js index ef0a23a02928ef..dafaf9122efc86 100644 --- a/benchmark/http/http_server_for_chunky_client.js +++ b/benchmark/http/http_server_for_chunky_client.js @@ -10,7 +10,9 @@ process.env.PIPE_NAME = PIPE; tmpdir.refresh(); -const server = http.createServer((req, res) => { +// For Node.js versions below v13.3.0 this benchmark will require +// the flag --max-http-header-size 64000 in order to work properly +const server = http.createServer({ maxHeaderSize: 64000 }, (req, res) => { const headers = { 'content-type': 'text/plain', 'content-length': '2' @@ -28,7 +30,11 @@ const child = fork( `${__dirname}/_chunky_http_client.js`, process.argv.slice(2) ); -child.on('message', common.sendResult); +child.on('message', (data) => { + if (data.type === 'report') { + common.sendResult(data); + } +}); child.on('close', (code) => { server.close(); assert.strictEqual(code, 0); diff --git a/benchmark/querystring/querystring-stringify.js b/benchmark/querystring/querystring-stringify.js index be81f67fa826d7..d1b724fcf2c14d 100644 --- a/benchmark/querystring/querystring-stringify.js +++ b/benchmark/querystring/querystring-stringify.js @@ -3,7 +3,7 @@ const common = require('../common.js'); const querystring = require('querystring'); const bench = common.createBenchmark(main, { - type: ['noencode', 'encodemany', 'encodelast', 'array'], + type: ['noencode', 'encodemany', 'encodelast', 'array', 'multiprimitives'], n: [1e6], }); @@ -28,7 +28,12 @@ function main({ type, n }) { foo: [], baz: ['bar'], xyzzy: ['bar', 'quux', 'thud'] - } + }, + multiprimitives: { + foo: false, + bar: -13.37, + baz: '', + }, }; const input = inputs[type]; diff --git a/common.gypi b/common.gypi index 5e4f9b6dba1dce..9ebda1c4654617 100644 --- a/common.gypi +++ b/common.gypi @@ -36,7 +36,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.33', + 'v8_embedder_string': '-node.23', ##### V8 defaults for Node.js ##### @@ -57,6 +57,12 @@ # https://github.com/nodejs/node/pull/22920/files#r222779926 'v8_enable_handle_zapping': 0, + # Disable pointer compression. Can be enabled at build time via configure + # options but default values are required here as this file is also used by + # node-gyp to build addons. + 'v8_enable_pointer_compression%': 0, + 'v8_enable_31bit_smis_on_64bit_arch%': 0, + # Disable V8 untrusted code mitigations. # See https://github.com/v8/v8/wiki/Untrusted-code-mitigations 'v8_untrusted_code_mitigations': 0, @@ -193,6 +199,11 @@ ], 'msvs_settings': { 'VCCLCompilerTool': { + 'conditions': [ + ['target_arch=="arm64"', { + 'FloatingPointModel': 1 # /fp:strict + }] + ], 'EnableFunctionLevelLinking': 'true', 'EnableIntrinsicFunctions': 'true', 'FavorSizeOrSpeed': 1, # /Ot, favor speed over size diff --git a/configure b/configure index 71c2fc87ca4cfc..7e8c4cff832ffd 100755 --- a/configure +++ b/configure @@ -5,11 +5,11 @@ # as is the fact that the ] goes on a new line. _=[ 'exec' '/bin/sh' '-c' ''' test ${FORCE_PYTHON2} && exec python2 "$0" "$@" # workaround for gclient -which python3.8 >/dev/null && exec python3.8 "$0" "$@" -which python3.7 >/dev/null && exec python3.7 "$0" "$@" -which python3.6 >/dev/null && exec python3.6 "$0" "$@" -which python3.5 >/dev/null && exec python3.5 "$0" "$@" -which python2.7 >/dev/null && exec python2.7 "$0" "$@" +command -v python3.8 >/dev/null && exec python3.8 "$0" "$@" +command -v python3.7 >/dev/null && exec python3.7 "$0" "$@" +command -v python3.6 >/dev/null && exec python3.6 "$0" "$@" +command -v python3.5 >/dev/null && exec python3.5 "$0" "$@" +command -v python2.7 >/dev/null && exec python2.7 "$0" "$@" exec python "$0" "$@" ''' "$0" "$@" ] diff --git a/configure.py b/configure.py index ac26f62916cd06..749692b9e2d69b 100755 --- a/configure.py +++ b/configure.py @@ -170,6 +170,11 @@ "e.g. /root/x/y.js will be referenced via require('root/x/y'). " "Can be used multiple times") +parser.add_option('--openssl-default-cipher-list', + action='store', + dest='openssl_default_cipher_list', + help='Use the specified cipher list as the default cipher list') + parser.add_option("--openssl-no-asm", action="store_true", dest="openssl_no_asm", @@ -646,6 +651,14 @@ default=False, help='compile V8 with debug checks and runtime debugging features enabled') +parser.add_option('--v8-lite-mode', + action='store_true', + dest='v8_lite_mode', + default=False, + help='compile V8 in lite mode for constrained environments (lowers V8 '+ + 'memory footprint, but also implies no just-in-time compilation ' + + 'support, thus much slower execution)') + parser.add_option('--node-builtin-modules-path', action='store', dest='node_builtin_modules_path', @@ -792,7 +805,7 @@ def get_nasm_version(asm): def get_llvm_version(cc): return get_version_helper( - cc, r"(^(?:FreeBSD )?clang version|based on LLVM) ([0-9]+\.[0-9]+)") + cc, r"(^(?:.+ )?clang version|based on LLVM) ([0-9]+\.[0-9]+)") def get_xcode_version(cc): return get_version_helper( @@ -999,12 +1012,14 @@ def configure_arm(o): o['variables']['arm_fpu'] = options.arm_fpu or arm_fpu -def configure_mips(o): +def configure_mips(o, target_arch): can_use_fpu_instructions = (options.mips_float_abi != 'soft') o['variables']['v8_can_use_fpu_instructions'] = b(can_use_fpu_instructions) o['variables']['v8_use_mips_abi_hardfloat'] = b(can_use_fpu_instructions) o['variables']['mips_arch_variant'] = options.mips_arch_variant o['variables']['mips_fpu_mode'] = options.mips_fpu_mode + host_byteorder = 'little' if target_arch in ('mipsel', 'mips64el') else 'big' + o['variables']['v8_host_byteorder'] = host_byteorder def gcc_version_ge(version_checked): @@ -1041,6 +1056,8 @@ def configure_node(o): cross_compiling = (options.cross_compiling if options.cross_compiling is not None else target_arch != host_arch) + if cross_compiling: + os.environ['GYP_CROSSCOMPILE'] = "1" if options.unused_without_snapshot: warn('building --without-snapshot is no longer possible') @@ -1062,7 +1079,7 @@ def configure_node(o): if target_arch == 'arm': configure_arm(o) elif target_arch in ('mips', 'mipsel', 'mips64el'): - configure_mips(o) + configure_mips(o, target_arch) if flavor == 'aix': o['variables']['node_target_type'] = 'static_library' @@ -1244,6 +1261,7 @@ def configure_library(lib, output, pkgname=None): def configure_v8(o): + o['variables']['v8_enable_lite_mode'] = 1 if options.v8_lite_mode else 0 o['variables']['v8_enable_gdbjit'] = 1 if options.gdb else 0 o['variables']['v8_no_strict_aliasing'] = 1 # Work around compiler bugs. o['variables']['v8_optimized_debug'] = 0 if options.v8_non_optimized_debug else 1 @@ -1291,6 +1309,8 @@ def without_ssl_error(option): without_ssl_error('--openssl-no-asm') if options.openssl_fips: without_ssl_error('--openssl-fips') + if options.openssl_default_cipher_list: + without_ssl_error('--openssl-default-cipher-list') return if options.use_openssl_ca_store: @@ -1300,6 +1320,9 @@ def without_ssl_error(option): variables['node_without_node_options'] = b(options.without_node_options) if options.without_node_options: o['defines'] += ['NODE_WITHOUT_NODE_OPTIONS'] + if options.openssl_default_cipher_list: + variables['openssl_default_cipher_list'] = \ + options.openssl_default_cipher_list if not options.shared_openssl and not options.openssl_no_asm: is_x86 = 'x64' in variables['target_arch'] or 'ia32' in variables['target_arch'] @@ -1794,6 +1817,10 @@ def make_bin_override(): if options.use_ninja: config['BUILD_WITH'] = 'ninja' +# On Windows there is another find.exe in C:\Windows\System32 +if sys.platform == 'win32': + config['FIND'] = '/usr/bin/find' + config_lines = ['='.join((k,v)) for k,v in config.items()] # Add a blank string to get a blank line at the end. config_lines += [''] diff --git a/deps/icu-small/source/data/in/icudt67l.dat.bz2 b/deps/icu-small/source/data/in/icudt67l.dat.bz2 index 7c63c0bd468f85..60bc3e084f4322 100644 Binary files a/deps/icu-small/source/data/in/icudt67l.dat.bz2 and b/deps/icu-small/source/data/in/icudt67l.dat.bz2 differ diff --git a/deps/node-inspect/.github/workflows/ci.yml b/deps/node-inspect/.github/workflows/ci.yml new file mode 100644 index 00000000000000..968316a34779a5 --- /dev/null +++ b/deps/node-inspect/.github/workflows/ci.yml @@ -0,0 +1,31 @@ +name: Node CI + +on: [push, pull_request] + +jobs: + build: + + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + node-version: + # See https://github.com/nodejs/node-inspect/pull/78 + # - 10.x + - 12.x + - 13.x + + steps: + - uses: actions/checkout@v2 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - name: npm install, build, and test + run: | + npm install + npm run build --if-present + npm test + env: + CI: true diff --git a/deps/node-inspect/lib/_inspect.js b/deps/node-inspect/lib/_inspect.js index 4d931f7a2bc664..aac278db0a891e 100644 --- a/deps/node-inspect/lib/_inspect.js +++ b/deps/node-inspect/lib/_inspect.js @@ -30,15 +30,15 @@ const runAsStandalone = typeof __dirname !== 'undefined'; const [ InspectClient, createRepl ] = runAsStandalone ? // This copy of node-inspect is on-disk, relative paths make sense. - [ - require('./internal/inspect_client'), - require('./internal/inspect_repl') - ] : + [ + require('./internal/inspect_client'), + require('./internal/inspect_repl') + ] : // This copy of node-inspect is built into the node executable. - [ - require('node-inspect/lib/internal/inspect_client'), - require('node-inspect/lib/internal/inspect_repl') - ]; + [ + require('node-inspect/lib/internal/inspect_client'), + require('node-inspect/lib/internal/inspect_repl') + ]; const debuglog = util.debuglog('inspect'); @@ -49,8 +49,8 @@ class StartupError extends Error { } } -function portIsFree(host, port, timeout = 2000) { - if (port === 0) return Promise.resolve(); // Binding to a random port. +function portIsFree(host, port, timeout = 9999) { + if (port === 0) return Promise.resolve(); // Binding to a random port. const retryDelay = 150; let didTimeOut = false; @@ -96,9 +96,9 @@ function runScript(script, scriptArgs, inspectHost, inspectPort, childPrint) { return new Promise((resolve) => { const needDebugBrk = process.version.match(/^v(6|7)\./); const args = (needDebugBrk ? - ['--inspect', `--debug-brk=${inspectPort}`] : - [`--inspect-brk=${inspectPort}`]) - .concat([script], scriptArgs); + ['--inspect', `--debug-brk=${inspectPort}`] : + [`--inspect-brk=${inspectPort}`]) + .concat([script], scriptArgs); const child = spawn(process.execPath, args); child.stdout.setEncoding('utf8'); child.stderr.setEncoding('utf8'); @@ -154,11 +154,11 @@ class NodeInspector { if (options.script) { this._runScript = runScript.bind(null, - options.script, - options.scriptArgs, - options.host, - options.port, - this.childPrint.bind(this)); + options.script, + options.scriptArgs, + options.host, + options.port, + this.childPrint.bind(this)); } else { this._runScript = () => Promise.resolve([null, options.port, options.host]); @@ -333,8 +333,8 @@ function parseArgv([target, ...args]) { } function startInspect(argv = process.argv.slice(2), - stdin = process.stdin, - stdout = process.stdout) { + stdin = process.stdin, + stdout = process.stdout) { /* eslint-disable no-console */ if (argv.length < 1) { const invokedAs = runAsStandalone ? diff --git a/deps/node-inspect/lib/internal/inspect_repl.js b/deps/node-inspect/lib/internal/inspect_repl.js index d9d3f89f03a408..bfbedf66a71b79 100644 --- a/deps/node-inspect/lib/internal/inspect_repl.js +++ b/deps/node-inspect/lib/internal/inspect_repl.js @@ -85,9 +85,16 @@ function extractFunctionName(description) { return fnNameMatch ? `: ${fnNameMatch[1]}` : ''; } -const NATIVES = process.binding('natives'); +const PUBLIC_BUILTINS = require('module').builtinModules; +const NATIVES = PUBLIC_BUILTINS ? process.binding('natives') : {}; function isNativeUrl(url) { - return url.replace('.js', '') in NATIVES || url === 'bootstrap_node.js'; + url = url.replace(/\.js$/, ''); + if (PUBLIC_BUILTINS) { + if (url.startsWith('internal/') || PUBLIC_BUILTINS.includes(url)) + return true; + } + + return url in NATIVES || url === 'bootstrap_node'; } function getRelativePath(filenameOrURL) { @@ -775,6 +782,14 @@ function createRepl(inspector) { } Debugger.on('paused', ({ callFrames, reason /* , hitBreakpoints */ }) => { + if (process.env.NODE_INSPECT_RESUME_ON_START === '1' && + reason === 'Break on start') { + debuglog('Paused on start, but NODE_INSPECT_RESUME_ON_START' + + ' environment variable is set to 1, resuming'); + inspector.client.callMethod('Debugger.resume'); + return; + } + // Save execution context's data currentBacktrace = Backtrace.from(callFrames); selectedFrame = currentBacktrace[0]; diff --git a/deps/node-inspect/package.json b/deps/node-inspect/package.json index c64582703cc6d9..925fb03f21a53d 100644 --- a/deps/node-inspect/package.json +++ b/deps/node-inspect/package.json @@ -1,6 +1,6 @@ { "name": "node-inspect", - "version": "1.11.6", + "version": "2.0.0", "description": "Node Inspect", "license": "MIT", "main": "lib/_inspect.js", @@ -27,7 +27,7 @@ }, "dependencies": {}, "devDependencies": { - "eslint": "^3.10.2", + "eslint": "^6.8.0", "nlm": "^3.0.0", "tap": "^10.7.0" }, diff --git a/deps/node-inspect/test/cli/address.test.js b/deps/node-inspect/test/cli/address.test.js new file mode 100644 index 00000000000000..1dbe4f37b42175 --- /dev/null +++ b/deps/node-inspect/test/cli/address.test.js @@ -0,0 +1,71 @@ +'use strict'; +const { spawn } = require('child_process'); +const Path = require('path'); +const { test } = require('tap'); + +const startCLI = require('./start-cli'); + +// NOTE(oyyd): We might want to import this regexp from "lib/_inspect.js"? +const kDebuggerMsgReg = /Debugger listening on ws:\/\/\[?(.+?)\]?:(\d+)\//; + +function launchTarget(...args) { + const childProc = spawn(process.execPath, args); + return new Promise((resolve, reject) => { + const onExit = () => { + reject(new Error('Child process exits unexpectly')); + }; + childProc.on('exit', onExit); + childProc.stderr.setEncoding('utf8'); + childProc.stderr.on('data', (data) => { + const ret = kDebuggerMsgReg.exec(data); + childProc.removeListener('exit', onExit); + if (ret) { + resolve({ + childProc, + host: ret[1], + port: ret[2], + }); + } + }); + }); +} + +// process.debugPort is our proxy for "the version of node used to run this +// test suite doesn't support SIGUSR1 for enabling --inspect for a process". +const defaultsToOldProtocol = process.debugPort === 5858; + +test('examples/alive.js', { skip: defaultsToOldProtocol }, (t) => { + const script = Path.join('examples', 'alive.js'); + let cli = null; + let target = null; + + function cleanup(error) { + if (cli) { + cli.quit(); + cli = null; + } + if (target) { + target.kill(); + target = null; + } + if (error) throw error; + } + + return launchTarget('--inspect=0', script) + .then(({ childProc, host, port }) => { + target = childProc; + cli = startCLI([`${host || '127.0.0.1'}:${port}`]); + return cli.waitForPrompt(); + }) + .then(() => cli.command('sb("alive.js", 3)')) + .then(() => cli.waitFor(/break/)) + .then(() => cli.waitForPrompt()) + .then(() => { + t.match( + cli.output, + '> 3 ++x;', + 'marks the 3rd line'); + }) + .then(() => cleanup()) + .then(null, cleanup); +}); diff --git a/deps/node-inspect/test/cli/invalid-args.test.js b/deps/node-inspect/test/cli/invalid-args.test.js index c1aaeb6a9ce750..86428a3ec27030 100644 --- a/deps/node-inspect/test/cli/invalid-args.test.js +++ b/deps/node-inspect/test/cli/invalid-args.test.js @@ -27,7 +27,7 @@ test('launch w/ invalid host:port', (t) => { }); }); -test('launch w/ unavailable port', async (t) => { +test('launch w/ unavailable port', async(t) => { const blocker = createServer((socket) => socket.end()); const port = await new Promise((resolve, reject) => { blocker.on('error', reject); diff --git a/deps/node-inspect/test/cli/launch.test.js b/deps/node-inspect/test/cli/launch.test.js index 087a46c54bb8c6..c4ff3d855a82bc 100644 --- a/deps/node-inspect/test/cli/launch.test.js +++ b/deps/node-inspect/test/cli/launch.test.js @@ -174,3 +174,23 @@ test('run after quit / restart', (t) => { .then(() => cli.quit()) .then(null, onFatal); }); + +test('auto-resume on start if the environment variable is defined', (t) => { + const script = Path.join('examples', 'break.js'); + + const cli = startCLI([script], [], { + env: { NODE_INSPECT_RESUME_ON_START: '1' } + }); + + return cli.waitForInitialBreak() + .then(() => { + t.match( + cli.breakInfo, + { filename: script, line: 10 }, + 'skips to the first breakpoint'); + }) + .then(() => cli.quit()) + .then((code) => { + t.equal(code, 0, 'exits with success'); + }); +}); diff --git a/deps/node-inspect/test/cli/start-cli.js b/deps/node-inspect/test/cli/start-cli.js index e2fa5fe47c9ebe..32c666c7647c68 100644 --- a/deps/node-inspect/test/cli/start-cli.js +++ b/deps/node-inspect/test/cli/start-cli.js @@ -8,8 +8,8 @@ tap.test('startCLI', (t) => t.end()); const CLI = process.env.USE_EMBEDDED_NODE_INSPECT === '1' ? - 'inspect' : - require.resolve('../../cli.js'); + 'inspect' : + require.resolve('../../cli.js'); const BREAK_MESSAGE = new RegExp('(?:' + [ 'assert', 'break', 'break on start', 'debugCommand', @@ -20,8 +20,8 @@ function isPreBreak(output) { return /Break on start/.test(output) && /1 \(function \(exports/.test(output); } -function startCLI(args, flags = []) { - const child = spawn(process.execPath, [...flags, CLI, ...args]); +function startCLI(args, flags = [], spawnOpts = {}) { + const child = spawn(process.execPath, [...flags, CLI, ...args], spawnOpts); let isFirstStdoutChunk = true; const outputBuffer = []; diff --git a/deps/uv/.gitignore b/deps/uv/.gitignore index 83370a7bb0efcd..7eb49322af01f2 100644 --- a/deps/uv/.gitignore +++ b/deps/uv/.gitignore @@ -67,6 +67,7 @@ ipch # Clion / IntelliJ project files /.idea/ +cmake-build-debug/ *.xcodeproj *.xcworkspace diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS index 410d9461ad11d5..222367e41ee06e 100644 --- a/deps/uv/AUTHORS +++ b/deps/uv/AUTHORS @@ -425,3 +425,10 @@ Sk Sajidul Kadir twosee Rikard Falkeborn Yash Ladha +James Ross +Colin Finck +Shohei YOSHIDA +Philip Chimento +Michal Artazov +Jeroen Roovers +MasterDuke17 diff --git a/deps/uv/CMakeLists.txt b/deps/uv/CMakeLists.txt index c82fa2b56d8771..0496d36ae970a1 100644 --- a/deps/uv/CMakeLists.txt +++ b/deps/uv/CMakeLists.txt @@ -24,6 +24,12 @@ cmake_dependent_option(LIBUV_BUILD_BENCH "Build the benchmarks when building unit tests and we are the root project" ON "LIBUV_BUILD_TESTS" OFF) +# Qemu Build +option(QEMU "build for qemu" OFF) +if(QEMU) + add_definitions(-D__QEMU__=1) +endif() + # Compiler check string(CONCAT is-msvc $, @@ -31,6 +37,18 @@ string(CONCAT is-msvc $) check_c_compiler_flag(/W4 UV_LINT_W4) +check_c_compiler_flag(/wd4100 UV_LINT_NO_UNUSED_PARAMETER_MSVC) +check_c_compiler_flag(/wd4127 UV_LINT_NO_CONDITIONAL_CONSTANT_MSVC) +check_c_compiler_flag(/wd4201 UV_LINT_NO_NONSTANDARD_MSVC) +check_c_compiler_flag(/wd4206 UV_LINT_NO_NONSTANDARD_EMPTY_TU_MSVC) +check_c_compiler_flag(/wd4210 UV_LINT_NO_NONSTANDARD_FILE_SCOPE_MSVC) +check_c_compiler_flag(/wd4232 UV_LINT_NO_NONSTANDARD_NONSTATIC_DLIMPORT_MSVC) +check_c_compiler_flag(/wd4456 UV_LINT_NO_HIDES_LOCAL) +check_c_compiler_flag(/wd4457 UV_LINT_NO_HIDES_PARAM) +check_c_compiler_flag(/wd4459 UV_LINT_NO_HIDES_GLOBAL) +check_c_compiler_flag(/wd4706 UV_LINT_NO_CONDITIONAL_ASSIGNMENT_MSVC) +check_c_compiler_flag(/wd4996 UV_LINT_NO_UNSAFE_MSVC) + check_c_compiler_flag(-Wall UV_LINT_WALL) # DO NOT use this under MSVC # TODO: Place these into its own function @@ -38,10 +56,21 @@ check_c_compiler_flag(-Wno-unused-parameter UV_LINT_NO_UNUSED_PARAMETER) check_c_compiler_flag(-Wstrict-prototypes UV_LINT_STRICT_PROTOTYPES) check_c_compiler_flag(-Wextra UV_LINT_EXTRA) -set(lint-no-unused-parameter $<$:-Wno-unused-parameter>) +set(lint-no-unused-parameter $<$:-Wno-unused-parameter>) set(lint-strict-prototypes $<$:-Wstrict-prototypes>) set(lint-extra $<$:-Wextra>) set(lint-w4 $<$:/W4>) +set(lint-no-unused-parameter-msvc $<$:/wd4100>) +set(lint-no-conditional-constant-msvc $<$:/wd4127>) +set(lint-no-nonstandard-msvc $<$:/wd4201>) +set(lint-no-nonstandard-empty-tu-msvc $<$:/wd4206>) +set(lint-no-nonstandard-file-scope-msvc $<$:/wd4210>) +set(lint-no-nonstandard-nonstatic-dlimport-msvc $<$:/wd4232>) +set(lint-no-hides-local-msvc $<$:/wd4456>) +set(lint-no-hides-param-msvc $<$:/wd4457>) +set(lint-no-hides-global-msvc $<$:/wd4459>) +set(lint-no-conditional-assignment-msvc $<$:/wd4706>) +set(lint-no-unsafe-msvc $<$:/wd4996>) # Unfortunately, this one is complicated because MSVC and clang-cl support -Wall # but using it is like calling -Weverything string(CONCAT lint-default $< @@ -50,6 +79,17 @@ string(CONCAT lint-default $< list(APPEND uv_cflags ${lint-strict-prototypes} ${lint-extra} ${lint-default} ${lint-w4}) list(APPEND uv_cflags ${lint-no-unused-parameter}) +list(APPEND uv_cflags ${lint-no-unused-parameter-msvc}) +list(APPEND uv_cflags ${lint-no-conditional-constant-msvc}) +list(APPEND uv_cflags ${lint-no-nonstandard-msvc}) +list(APPEND uv_cflags ${lint-no-nonstandard-empty-tu-msvc}) +list(APPEND uv_cflags ${lint-no-nonstandard-file-scope-msvc}) +list(APPEND uv_cflags ${lint-no-nonstandard-nonstatic-dlimport-msvc}) +list(APPEND uv_cflags ${lint-no-hides-local-msvc}) +list(APPEND uv_cflags ${lint-no-hides-param-msvc}) +list(APPEND uv_cflags ${lint-no-hides-global-msvc}) +list(APPEND uv_cflags ${lint-no-conditional-assignment-msvc}) +list(APPEND uv_cflags ${lint-no-unsafe-msvc}) set(uv_sources src/fs-poll.c @@ -64,22 +104,9 @@ set(uv_sources src/version.c) if(WIN32) - if (CMAKE_SYSTEM_VERSION VERSION_GREATER 10) # Windows 10 - set(windows-version 0x0A00) - elseif (CMAKE_SYSTEM_VERSION VERSION_GREATER 6.3) # Windows 8.1 - set(windows-version 0x0603) - elseif (CMAKE_SYSTEM_VERSION VERSION_GREATER 6.2) # Windows 8 - set(windows-version 0x0602) - elseif (CMAKE_SYSTEM_VERSION VERSION_GREATER 6.1) # Windows 7 - set(windows-version 0x0601) - elseif (CMAKE_SYSTEM_VERSION VERSION_GREATER 6.0) # Windows Vista - set(windows-version 0x0600) - else() - message(FATAL_ERROR "Windows Vista is the minimum version supported") - endif() - list(APPEND uv_defines WIN32_LEAN_AND_MEAN _WIN32_WINNT=${windows-version}) + list(APPEND uv_defines WIN32_LEAN_AND_MEAN _WIN32_WINNT=0x0600) list(APPEND uv_libraries - $<$:psapi> + psapi iphlpapi userenv ws2_32) @@ -155,7 +182,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "AIX") endif() if(CMAKE_SYSTEM_NAME STREQUAL "Android") - list(APPEND uv_libs dl) + list(APPEND uv_libraries dl) list(APPEND uv_sources src/unix/android-ifaddrs.c src/unix/linux-core.c @@ -489,7 +516,7 @@ if(LIBUV_BUILD_TESTS) test/test-walk-handles.c test/test-watcher-cross-stop.c) - add_executable(uv_run_tests ${uv_test_sources}) + add_executable(uv_run_tests ${uv_test_sources} uv_win_longpath.manifest) target_compile_definitions(uv_run_tests PRIVATE ${uv_defines} USING_UV_SHARED=1) target_compile_options(uv_run_tests PRIVATE ${uv_cflags}) @@ -501,10 +528,14 @@ if(LIBUV_BUILD_TESTS) set_tests_properties(uv_test PROPERTIES ENVIRONMENT "LIBPATH=${CMAKE_BINARY_DIR}:$ENV{LIBPATH}") endif() - add_executable(uv_run_tests_a ${uv_test_sources}) + add_executable(uv_run_tests_a ${uv_test_sources} uv_win_longpath.manifest) target_compile_definitions(uv_run_tests_a PRIVATE ${uv_defines}) target_compile_options(uv_run_tests_a PRIVATE ${uv_cflags}) - target_link_libraries(uv_run_tests_a uv_a ${uv_test_libraries}) + if(QEMU) + target_link_libraries(uv_run_tests_a uv_a ${uv_test_libraries} -static) + else() + target_link_libraries(uv_run_tests_a uv_a ${uv_test_libraries}) + endif() add_test(NAME uv_test_a COMMAND uv_run_tests_a WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) @@ -544,3 +575,11 @@ if(WIN32) RUNTIME DESTINATION lib/$ ARCHIVE DESTINATION lib/$) endif() + +message(STATUS "summary of build options: + Install prefix: ${CMAKE_INSTALL_PREFIX} + Target system: ${CMAKE_SYSTEM_NAME} + Compiler: + C compiler: ${CMAKE_C_COMPILER} + CFLAGS: ${CMAKE_C_FLAGS_${_build_type}} ${CMAKE_C_FLAGS} +") diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog index 3544c6c01b5a31..9b215a5ba0f6b9 100644 --- a/deps/uv/ChangeLog +++ b/deps/uv/ChangeLog @@ -1,3 +1,76 @@ +2020.05.18, Version 1.38.0 (Stable), 1ab9ea3790378f9f25c4e78e9e2b511c75f9c9ed + +Changes since version 1.37.0: + +* test: skip poll_duplex and poll_unidirectional on PASE (Xu Meng) + +* linux: make cpu_times consistently be milliseconds (James Ross) + +* win: DRY uv_poll_start() and uv_poll_stop() (Ben Noordhuis) + +* win: DRY uv_poll_close() (Ben Noordhuis) + +* unix,win: add uv_library_shutdown() (Ben Noordhuis) + +* unix: yield cpu when spinlocking on async handle (Ben Noordhuis) + +* win: remove dep on GetQueuedCompletionStatusEx (Colin Finck) + +* doc: correct source lines (Shohei YOSHIDA) + +* build,android: fix typo (twosee) + +* doc: uv_cancel() handles uv_random_t requests (Philip Chimento) + +* doc: fix unescaped character (Philip Chimento) + +* build,cmake: fix compilation on old MinGW (erw7) + +* build: remove unnessesary MSVC warnings (Bartosz Sosnowski) + +* win: make uv_udp_init_ex() accept UV_UDP_RECVMMSG (Ben Noordhuis) + +* unix: simplify uv__udp_init_ex() (Ben Noordhuis) + +* win: remove MAX_PATH limitations (Bartosz Sosnowski) + +* build, win: add long path aware manifest (Bartosz Sosnowski) + +* doc: check/idle/prepare functions always succeed (Ben Noordhuis) + +* darwin: fix build with non-apple compilers (Ben Noordhuis) + +* win: support environment variables > 32767 chars (Ben Noordhuis) + +* unix: fully initialize struct msghdr (Ben Noordhuis) + +* doc: add uv_replace_allocator thread safety warning (twosee) + +* unix: fix int overflow when copying large files (Michal Artazov) + +* fs: report original error (Bartosz Sosnowski) + +* win, fs: add IO_REPARSE_TAG_APPEXECLINK support (Bartosz Sosnowski) + +* doc: fix formatting (Ben Noordhuis) + +* unix: fix memory leak when uv_loop_init() fails (Anna Henningsen) + +* unix: shrink uv_udp_set_source_membership() stack (Ben Noordhuis) + +* unix,win: fix wrong sizeof argument to memcpy() (Ben Noordhuis) + +* build: check for libraries not provided by libc (Jeroen Roovers) + +* doc: fix the order of arguments to calloc() (MasterDuke17) + +* unix: don't abort when getrlimit() fails (Ben Noordhuis) + +* test: support common user profile on IBMi (Xu Meng) + +* build: test on more platforms via QEMU in CI (gengjiawen) + + 2020.04.20, Version 1.37.0 (Stable), 02a9e1be252b623ee032a3137c0b0c94afbe6809 Changes since version 1.36.0: diff --git a/deps/uv/Makefile.am b/deps/uv/Makefile.am index 23fa19dc4fc8e7..d9d2f3d02f52b4 100644 --- a/deps/uv/Makefile.am +++ b/deps/uv/Makefile.am @@ -409,8 +409,9 @@ uvinclude_HEADERS += include/uv/darwin.h libuv_la_CFLAGS += -D_DARWIN_USE_64_BIT_INODE=1 libuv_la_CFLAGS += -D_DARWIN_UNLIMITED_SELECT=1 libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \ - src/unix/darwin.c \ src/unix/darwin-proctitle.c \ + src/unix/darwin-stub.h \ + src/unix/darwin.c \ src/unix/fsevents.c \ src/unix/kqueue.c \ src/unix/proctitle.c \ diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac index cd7bab08570c8f..6616972ab1b98d 100644 --- a/deps/uv/configure.ac +++ b/deps/uv/configure.ac @@ -13,7 +13,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. AC_PREREQ(2.57) -AC_INIT([libuv], [1.37.0], [https://github.com/libuv/libuv/issues]) +AC_INIT([libuv], [1.38.0], [https://github.com/libuv/libuv/issues]) AC_CONFIG_MACRO_DIR([m4]) m4_include([m4/libuv-extra-automake-flags.m4]) m4_include([m4/as_case.m4]) @@ -38,15 +38,17 @@ m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) AC_PROG_LIBTOOL m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) LT_INIT -# TODO(bnoordhuis) Check for -pthread vs. -pthreads +AX_PTHREAD([ + LIBS="$LIBS $PTHREAD_LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" +]) AC_CHECK_LIB([dl], [dlopen]) -AC_CHECK_LIB([kstat], [kstat_lookup]) -AC_CHECK_LIB([nsl], [gethostbyname]) -AC_CHECK_LIB([perfstat], [perfstat_cpu]) -AC_CHECK_LIB([pthread], [pthread_mutex_init]) -AC_CHECK_LIB([rt], [clock_gettime]) -AC_CHECK_LIB([sendfile], [sendfile]) -AC_CHECK_LIB([socket], [socket]) +AC_SEARCH_LIBS([kstat_lookup], [kstat]) +AC_SEARCH_LIBS([gethostbyname], [nsl]) +AC_SEARCH_LIBS([perfstat_cpu], [perfstat]) +AC_SEARCH_LIBS([clock_gettime], [rt]) +AC_SEARCH_LIBS([sendfile], [sendfile]) +AC_SEARCH_LIBS([socket], [socket]) AC_SYS_LARGEFILE AM_CONDITIONAL([AIX], [AS_CASE([$host_os],[aix*], [true], [false])]) AM_CONDITIONAL([ANDROID], [AS_CASE([$host_os],[linux-android*],[true], [false])]) diff --git a/deps/uv/docs/src/check.rst b/deps/uv/docs/src/check.rst index 36c93cf03d99c0..33aab5516c2649 100644 --- a/deps/uv/docs/src/check.rst +++ b/deps/uv/docs/src/check.rst @@ -33,14 +33,22 @@ API .. c:function:: int uv_check_init(uv_loop_t* loop, uv_check_t* check) - Initialize the handle. + Initialize the handle. This function always succeeds. + + :returns: 0 .. c:function:: int uv_check_start(uv_check_t* check, uv_check_cb cb) - Start the handle with the given callback. + Start the handle with the given callback. This function always succeeds, + except when `cb` is `NULL`. + + :returns: 0 on success, or `UV_EINVAL` when `cb == NULL`. .. c:function:: int uv_check_stop(uv_check_t* check) Stop the handle, the callback will no longer be called. + This function always succeeds. + + :returns: 0 .. seealso:: The :c:type:`uv_handle_t` API functions also apply. diff --git a/deps/uv/docs/src/fs.rst b/deps/uv/docs/src/fs.rst index a475a460307898..73666f3cd87c29 100644 --- a/deps/uv/docs/src/fs.rst +++ b/deps/uv/docs/src/fs.rst @@ -492,6 +492,13 @@ API .. versionadded:: 1.19.0 +.. c:function:: int uv_fs_get_system_error(const uv_fs_t* req) + + Returns the platform specific error code - `GetLastError()` value on Windows + and `-(req->result)` on other platforms. + + .. versionadded:: 1.38.0 + .. c:function:: void* uv_fs_get_ptr(const uv_fs_t* req) Returns `req->ptr`. diff --git a/deps/uv/docs/src/idle.rst b/deps/uv/docs/src/idle.rst index 1f51c4a19e4a0b..b7a0507b0de2ac 100644 --- a/deps/uv/docs/src/idle.rst +++ b/deps/uv/docs/src/idle.rst @@ -41,14 +41,22 @@ API .. c:function:: int uv_idle_init(uv_loop_t* loop, uv_idle_t* idle) - Initialize the handle. + Initialize the handle. This function always succeeds. + + :returns: 0 .. c:function:: int uv_idle_start(uv_idle_t* idle, uv_idle_cb cb) - Start the handle with the given callback. + Start the handle with the given callback. This function always succeeds, + except when `cb` is `NULL`. + + :returns: 0 on success, or `UV_EINVAL` when `cb == NULL`. .. c:function:: int uv_idle_stop(uv_idle_t* idle) Stop the handle, the callback will no longer be called. + This function always succeeds. + + :returns: 0 .. seealso:: The :c:type:`uv_handle_t` API functions also apply. diff --git a/deps/uv/docs/src/misc.rst b/deps/uv/docs/src/misc.rst index 8515cdbc1b040a..906ca8ff75d345 100644 --- a/deps/uv/docs/src/misc.rst +++ b/deps/uv/docs/src/misc.rst @@ -131,11 +131,11 @@ Data types char* model; int speed; struct uv_cpu_times_s { - uint64_t user; - uint64_t nice; - uint64_t sys; - uint64_t idle; - uint64_t irq; + uint64_t user; /* milliseconds */ + uint64_t nice; /* milliseconds */ + uint64_t sys; /* milliseconds */ + uint64_t idle; /* milliseconds */ + uint64_t irq; /* milliseconds */ } cpu_times; } uv_cpu_info_t; @@ -233,6 +233,24 @@ API sure the allocator is changed while no memory was allocated with the previous allocator, or that they are compatible. + .. warning:: Allocator must be thread-safe. + +.. c:function:: void uv_library_shutdown(void); + + .. versionadded:: 1.38.0 + + Release any global state that libuv is holding onto. Libuv will normally + do so automatically when it is unloaded but it can be instructed to perform + cleanup manually. + + .. warning:: Only call :c:func:`uv_library_shutdown()` once. + + .. warning:: Don't call :c:func:`uv_library_shutdown()` when there are + still event loops or I/O requests active. + + .. warning:: Don't call libuv functions after calling + :c:func:`uv_library_shutdown()`. + .. c:function:: uv_buf_t uv_buf_init(char* base, unsigned int len) Constructor for :c:type:`uv_buf_t`. @@ -657,7 +675,7 @@ API .. note:: On IBM i PASE, you are not allowed to change your priority unless you - have the *JOBCTL special authority (even to lower it). + have the \*JOBCTL special authority (even to lower it). .. versionadded:: 1.23.0 diff --git a/deps/uv/docs/src/prepare.rst b/deps/uv/docs/src/prepare.rst index aca58155809cd9..5e0d247660ee14 100644 --- a/deps/uv/docs/src/prepare.rst +++ b/deps/uv/docs/src/prepare.rst @@ -33,14 +33,22 @@ API .. c:function:: int uv_prepare_init(uv_loop_t* loop, uv_prepare_t* prepare) - Initialize the handle. + Initialize the handle. This function always succeeds. + + :returns: 0 .. c:function:: int uv_prepare_start(uv_prepare_t* prepare, uv_prepare_cb cb) - Start the handle with the given callback. + Start the handle with the given callback. This function always succeeds, + except when `cb` is `NULL`. + + :returns: 0 on success, or `UV_EINVAL` when `cb == NULL`. .. c:function:: int uv_prepare_stop(uv_prepare_t* prepare) Stop the handle, the callback will no longer be called. + This function always succeeds. + + :returns: 0 .. seealso:: The :c:type:`uv_handle_t` API functions also apply. diff --git a/deps/uv/docs/src/request.rst b/deps/uv/docs/src/request.rst index 56038287b2ae11..5807ccba4a748e 100644 --- a/deps/uv/docs/src/request.rst +++ b/deps/uv/docs/src/request.rst @@ -69,8 +69,8 @@ API Returns 0 on success, or an error code < 0 on failure. Only cancellation of :c:type:`uv_fs_t`, :c:type:`uv_getaddrinfo_t`, - :c:type:`uv_getnameinfo_t` and :c:type:`uv_work_t` requests is - currently supported. + :c:type:`uv_getnameinfo_t`, :c:type:`uv_random_t` and :c:type:`uv_work_t` + requests is currently supported. Cancelled requests have their callbacks invoked some time in the future. It's **not** safe to free the memory associated with the request until the @@ -80,8 +80,9 @@ API * A :c:type:`uv_fs_t` request has its req->result field set to `UV_ECANCELED`. - * A :c:type:`uv_work_t`, :c:type:`uv_getaddrinfo_t` or c:type:`uv_getnameinfo_t` - request has its callback invoked with status == `UV_ECANCELED`. + * A :c:type:`uv_work_t`, :c:type:`uv_getaddrinfo_t`, + :c:type:`uv_getnameinfo_t` or :c:type:`uv_random_t` request has its + callback invoked with status == `UV_ECANCELED`. .. c:function:: size_t uv_req_size(uv_req_type type) diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h index a3a770db88b90e..fec663136a4ff1 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/include/uv.h @@ -265,6 +265,8 @@ typedef void* (*uv_realloc_func)(void* ptr, size_t size); typedef void* (*uv_calloc_func)(size_t count, size_t size); typedef void (*uv_free_func)(void* ptr); +UV_EXTERN void uv_library_shutdown(void); + UV_EXTERN int uv_replace_allocator(uv_malloc_func malloc_func, uv_realloc_func realloc_func, uv_calloc_func calloc_func, @@ -1069,11 +1071,11 @@ UV_EXTERN int uv_cancel(uv_req_t* req); struct uv_cpu_times_s { - uint64_t user; - uint64_t nice; - uint64_t sys; - uint64_t idle; - uint64_t irq; + uint64_t user; /* milliseconds */ + uint64_t nice; /* milliseconds */ + uint64_t sys; /* milliseconds */ + uint64_t idle; /* milliseconds */ + uint64_t irq; /* milliseconds */ }; struct uv_cpu_info_s { @@ -1305,6 +1307,7 @@ struct uv_fs_s { UV_EXTERN uv_fs_type uv_fs_get_type(const uv_fs_t*); UV_EXTERN ssize_t uv_fs_get_result(const uv_fs_t*); +UV_EXTERN int uv_fs_get_system_error(const uv_fs_t*); UV_EXTERN void* uv_fs_get_ptr(const uv_fs_t*); UV_EXTERN const char* uv_fs_get_path(const uv_fs_t*); UV_EXTERN uv_stat_t* uv_fs_get_statbuf(uv_fs_t*); diff --git a/deps/uv/include/uv/version.h b/deps/uv/include/uv/version.h index be97adf6fff794..486658c3933982 100644 --- a/deps/uv/include/uv/version.h +++ b/deps/uv/include/uv/version.h @@ -31,7 +31,7 @@ */ #define UV_VERSION_MAJOR 1 -#define UV_VERSION_MINOR 37 +#define UV_VERSION_MINOR 38 #define UV_VERSION_PATCH 0 #define UV_VERSION_IS_RELEASE 1 #define UV_VERSION_SUFFIX "" diff --git a/deps/uv/src/threadpool.c b/deps/uv/src/threadpool.c index a8f433f0510800..0998938f3e0d16 100644 --- a/deps/uv/src/threadpool.c +++ b/deps/uv/src/threadpool.c @@ -160,8 +160,8 @@ static void post(QUEUE* q, enum uv__work_kind kind) { } +void uv__threadpool_cleanup(void) { #ifndef _WIN32 -UV_DESTRUCTOR(static void cleanup(void)) { unsigned int i; if (nthreads == 0) @@ -181,8 +181,8 @@ UV_DESTRUCTOR(static void cleanup(void)) { threads = NULL; nthreads = 0; -} #endif +} static void init_threads(void) { diff --git a/deps/uv/src/unix/aix.c b/deps/uv/src/unix/aix.c index 417ee5512fa252..6b4594b43e9777 100644 --- a/deps/uv/src/unix/aix.c +++ b/deps/uv/src/unix/aix.c @@ -926,7 +926,7 @@ int uv_get_process_title(char* buffer, size_t size) { } -UV_DESTRUCTOR(static void free_args_mem(void)) { +void uv__process_title_cleanup(void) { uv__free(args_mem); /* Keep valgrind happy. */ args_mem = NULL; } diff --git a/deps/uv/src/unix/async.c b/deps/uv/src/unix/async.c index 26d337e0a44c0e..5f58fb88d628ec 100644 --- a/deps/uv/src/unix/async.c +++ b/deps/uv/src/unix/async.c @@ -32,6 +32,7 @@ #include #include #include +#include /* sched_yield() */ #ifdef __linux__ #include @@ -81,20 +82,32 @@ int uv_async_send(uv_async_t* handle) { /* Only call this from the event loop thread. */ static int uv__async_spin(uv_async_t* handle) { + int i; int rc; for (;;) { - /* rc=0 -- handle is not pending. - * rc=1 -- handle is pending, other thread is still working with it. - * rc=2 -- handle is pending, other thread is done. + /* 997 is not completely chosen at random. It's a prime number, acyclical + * by nature, and should therefore hopefully dampen sympathetic resonance. */ - rc = cmpxchgi(&handle->pending, 2, 0); - - if (rc != 1) - return rc; - - /* Other thread is busy with this handle, spin until it's done. */ - cpu_relax(); + for (i = 0; i < 997; i++) { + /* rc=0 -- handle is not pending. + * rc=1 -- handle is pending, other thread is still working with it. + * rc=2 -- handle is pending, other thread is done. + */ + rc = cmpxchgi(&handle->pending, 2, 0); + + if (rc != 1) + return rc; + + /* Other thread is busy with this handle, spin until it's done. */ + cpu_relax(); + } + + /* Yield the CPU. We may have preempted the other thread while it's + * inside the critical section and if it's running on the same CPU + * as us, we'll just burn CPU cycles until the end of our time slice. + */ + sched_yield(); } } diff --git a/deps/uv/src/unix/bsd-proctitle.c b/deps/uv/src/unix/bsd-proctitle.c index 0ce47c8f64e25d..723b81c01c201f 100644 --- a/deps/uv/src/unix/bsd-proctitle.c +++ b/deps/uv/src/unix/bsd-proctitle.c @@ -37,6 +37,13 @@ static void init_process_title_mutex_once(void) { } +void uv__process_title_cleanup(void) { + /* TODO(bnoordhuis) uv_mutex_destroy(&process_title_mutex) + * and reset process_title_mutex_once? + */ +} + + char** uv_setup_args(int argc, char** argv) { process_title = argc > 0 ? uv__strdup(argv[0]) : NULL; return argv; diff --git a/deps/uv/src/unix/darwin-proctitle.c b/deps/uv/src/unix/darwin-proctitle.c index 2daf3e3474acff..5288083ef04fd7 100644 --- a/deps/uv/src/unix/darwin-proctitle.c +++ b/deps/uv/src/unix/darwin-proctitle.c @@ -30,8 +30,7 @@ #include #if !TARGET_OS_IPHONE -# include -# include +#include "darwin-stub.h" #endif diff --git a/deps/uv/src/unix/darwin-stub.h b/deps/uv/src/unix/darwin-stub.h new file mode 100644 index 00000000000000..b93cf67c596285 --- /dev/null +++ b/deps/uv/src/unix/darwin-stub.h @@ -0,0 +1,97 @@ +/* Copyright libuv project contributors. All rights reserved. + * + * 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. + */ + +#ifndef UV_DARWIN_STUB_H_ +#define UV_DARWIN_STUB_H_ + +#include + +struct CFArrayCallBacks; +struct CFRunLoopSourceContext; +struct FSEventStreamContext; + +typedef double CFAbsoluteTime; +typedef double CFTimeInterval; +typedef int FSEventStreamEventFlags; +typedef int OSStatus; +typedef long CFIndex; +typedef struct CFArrayCallBacks CFArrayCallBacks; +typedef struct CFRunLoopSourceContext CFRunLoopSourceContext; +typedef struct FSEventStreamContext FSEventStreamContext; +typedef uint32_t FSEventStreamCreateFlags; +typedef uint64_t FSEventStreamEventId; +typedef unsigned CFStringEncoding; +typedef void* CFAllocatorRef; +typedef void* CFArrayRef; +typedef void* CFBundleRef; +typedef void* CFDictionaryRef; +typedef void* CFRunLoopRef; +typedef void* CFRunLoopSourceRef; +typedef void* CFStringRef; +typedef void* CFTypeRef; +typedef void* FSEventStreamRef; + +typedef void (*FSEventStreamCallback)(const FSEventStreamRef, + void*, + size_t, + void*, + const FSEventStreamEventFlags*, + const FSEventStreamEventId*); + +struct CFRunLoopSourceContext { + CFIndex version; + void* info; + void* pad[7]; + void (*perform)(void*); +}; + +struct FSEventStreamContext { + CFIndex version; + void* info; + void* pad[3]; +}; + +static const CFStringEncoding kCFStringEncodingUTF8 = 0x8000100; +static const OSStatus noErr = 0; + +static const FSEventStreamEventId kFSEventStreamEventIdSinceNow = -1; + +static const int kFSEventStreamCreateFlagNoDefer = 2; +static const int kFSEventStreamCreateFlagFileEvents = 16; + +static const int kFSEventStreamEventFlagEventIdsWrapped = 8; +static const int kFSEventStreamEventFlagHistoryDone = 16; +static const int kFSEventStreamEventFlagItemChangeOwner = 0x4000; +static const int kFSEventStreamEventFlagItemCreated = 0x100; +static const int kFSEventStreamEventFlagItemFinderInfoMod = 0x2000; +static const int kFSEventStreamEventFlagItemInodeMetaMod = 0x400; +static const int kFSEventStreamEventFlagItemIsDir = 0x20000; +static const int kFSEventStreamEventFlagItemModified = 0x1000; +static const int kFSEventStreamEventFlagItemRemoved = 0x200; +static const int kFSEventStreamEventFlagItemRenamed = 0x800; +static const int kFSEventStreamEventFlagItemXattrMod = 0x8000; +static const int kFSEventStreamEventFlagKernelDropped = 4; +static const int kFSEventStreamEventFlagMount = 64; +static const int kFSEventStreamEventFlagRootChanged = 32; +static const int kFSEventStreamEventFlagUnmount = 128; +static const int kFSEventStreamEventFlagUserDropped = 2; + +#endif /* UV_DARWIN_STUB_H_ */ diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c index 1b8d2ad199662b..f5b2b94207c19c 100644 --- a/deps/uv/src/unix/fs.c +++ b/deps/uv/src/unix/fs.c @@ -1110,9 +1110,10 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) { int dst_flags; int result; int err; - size_t bytes_to_send; - int64_t in_offset; - ssize_t bytes_written; + off_t bytes_to_send; + off_t in_offset; + off_t bytes_written; + size_t bytes_chunk; dstfd = -1; err = 0; @@ -1211,7 +1212,10 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) { bytes_to_send = src_statsbuf.st_size; in_offset = 0; while (bytes_to_send != 0) { - uv_fs_sendfile(NULL, &fs_req, dstfd, srcfd, in_offset, bytes_to_send, NULL); + bytes_chunk = SSIZE_MAX; + if (bytes_to_send < (off_t) bytes_chunk) + bytes_chunk = bytes_to_send; + uv_fs_sendfile(NULL, &fs_req, dstfd, srcfd, in_offset, bytes_chunk, NULL); bytes_written = fs_req.result; uv_fs_req_cleanup(&fs_req); @@ -2082,3 +2086,7 @@ int uv_fs_statfs(uv_loop_t* loop, PATH; POST; } + +int uv_fs_get_system_error(const uv_fs_t* req) { + return -req->result; +} diff --git a/deps/uv/src/unix/fsevents.c b/deps/uv/src/unix/fsevents.c index 448921f813d789..a51f29b3f6db55 100644 --- a/deps/uv/src/unix/fsevents.c +++ b/deps/uv/src/unix/fsevents.c @@ -41,34 +41,33 @@ void uv__fsevents_loop_delete(uv_loop_t* loop) { #else /* TARGET_OS_IPHONE */ +#include "darwin-stub.h" + #include #include #include #include -#include -#include - -/* These are macros to avoid "initializer element is not constant" errors - * with old versions of gcc. - */ -#define kFSEventsModified (kFSEventStreamEventFlagItemFinderInfoMod | \ - kFSEventStreamEventFlagItemModified | \ - kFSEventStreamEventFlagItemInodeMetaMod | \ - kFSEventStreamEventFlagItemChangeOwner | \ - kFSEventStreamEventFlagItemXattrMod) - -#define kFSEventsRenamed (kFSEventStreamEventFlagItemCreated | \ - kFSEventStreamEventFlagItemRemoved | \ - kFSEventStreamEventFlagItemRenamed) - -#define kFSEventsSystem (kFSEventStreamEventFlagUserDropped | \ - kFSEventStreamEventFlagKernelDropped | \ - kFSEventStreamEventFlagEventIdsWrapped | \ - kFSEventStreamEventFlagHistoryDone | \ - kFSEventStreamEventFlagMount | \ - kFSEventStreamEventFlagUnmount | \ - kFSEventStreamEventFlagRootChanged) +static const int kFSEventsModified = + kFSEventStreamEventFlagItemChangeOwner | + kFSEventStreamEventFlagItemFinderInfoMod | + kFSEventStreamEventFlagItemInodeMetaMod | + kFSEventStreamEventFlagItemModified | + kFSEventStreamEventFlagItemXattrMod; + +static const int kFSEventsRenamed = + kFSEventStreamEventFlagItemCreated | + kFSEventStreamEventFlagItemRemoved | + kFSEventStreamEventFlagItemRenamed; + +static const int kFSEventsSystem = + kFSEventStreamEventFlagUserDropped | + kFSEventStreamEventFlagKernelDropped | + kFSEventStreamEventFlagEventIdsWrapped | + kFSEventStreamEventFlagHistoryDone | + kFSEventStreamEventFlagMount | + kFSEventStreamEventFlagUnmount | + kFSEventStreamEventFlagRootChanged; typedef struct uv__fsevents_event_s uv__fsevents_event_t; typedef struct uv__cf_loop_signal_s uv__cf_loop_signal_t; @@ -148,7 +147,7 @@ static void (*pFSEventStreamRelease)(FSEventStreamRef); static void (*pFSEventStreamScheduleWithRunLoop)(FSEventStreamRef, CFRunLoopRef, CFStringRef); -static Boolean (*pFSEventStreamStart)(FSEventStreamRef); +static int (*pFSEventStreamStart)(FSEventStreamRef); static void (*pFSEventStreamStop)(FSEventStreamRef); #define UV__FSEVENTS_PROCESS(handle, block) \ @@ -215,7 +214,7 @@ static void uv__fsevents_push_event(uv_fs_event_t* handle, /* Runs in CF thread, when there're events in FSEventStream */ -static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef, +static void uv__fsevents_event_cb(const FSEventStreamRef streamRef, void* info, size_t numEvents, void* eventPaths, @@ -340,11 +339,8 @@ static int uv__fsevents_create_stream(uv_loop_t* loop, CFArrayRef paths) { FSEventStreamCreateFlags flags; /* Initialize context */ - ctx.version = 0; + memset(&ctx, 0, sizeof(ctx)); ctx.info = loop; - ctx.retain = NULL; - ctx.release = NULL; - ctx.copyDescription = NULL; latency = 0.05; diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h index 598554b607ec42..402ee877d076b6 100644 --- a/deps/uv/src/unix/internal.h +++ b/deps/uv/src/unix/internal.h @@ -106,10 +106,8 @@ int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset); #if defined(__clang__) || \ defined(__GNUC__) || \ defined(__INTEL_COMPILER) -# define UV_DESTRUCTOR(declaration) __attribute__((destructor)) declaration # define UV_UNUSED(declaration) __attribute__((unused)) declaration #else -# define UV_DESTRUCTOR(declaration) declaration # define UV_UNUSED(declaration) declaration #endif diff --git a/deps/uv/src/unix/linux-core.c b/deps/uv/src/unix/linux-core.c index f8d9ff5868ab58..99cbb1c8fd7ea4 100644 --- a/deps/uv/src/unix/linux-core.c +++ b/deps/uv/src/unix/linux-core.c @@ -768,7 +768,8 @@ static int read_times(FILE* statfile_fp, unsigned int numcpus, uv_cpu_info_t* ci) { struct uv_cpu_times_s ts; - uint64_t clock_ticks; + unsigned int ticks; + unsigned int multiplier; uint64_t user; uint64_t nice; uint64_t sys; @@ -779,9 +780,10 @@ static int read_times(FILE* statfile_fp, uint64_t len; char buf[1024]; - clock_ticks = sysconf(_SC_CLK_TCK); - assert(clock_ticks != (uint64_t) -1); - assert(clock_ticks != 0); + ticks = (unsigned int)sysconf(_SC_CLK_TCK); + multiplier = ((uint64_t)1000L / ticks); + assert(ticks != (unsigned int) -1); + assert(ticks != 0); rewind(statfile_fp); @@ -823,11 +825,11 @@ static int read_times(FILE* statfile_fp, &irq)) abort(); - ts.user = clock_ticks * user; - ts.nice = clock_ticks * nice; - ts.sys = clock_ticks * sys; - ts.idle = clock_ticks * idle; - ts.irq = clock_ticks * irq; + ts.user = user * multiplier; + ts.nice = nice * multiplier; + ts.sys = sys * multiplier; + ts.idle = idle * multiplier; + ts.irq = irq * multiplier; ci[num++].cpu_times = ts; } assert(num == numcpus); diff --git a/deps/uv/src/unix/loop.c b/deps/uv/src/unix/loop.c index c2a03d770f3764..e5b2889560a516 100644 --- a/deps/uv/src/unix/loop.c +++ b/deps/uv/src/unix/loop.c @@ -106,6 +106,8 @@ int uv_loop_init(uv_loop_t* loop) { fail_signal_init: uv__platform_loop_delete(loop); + uv__free(loop->watchers); + loop->nwatchers = 0; return err; } diff --git a/deps/uv/src/unix/no-proctitle.c b/deps/uv/src/unix/no-proctitle.c index 165740ca3ff9d5..32aa0af1f92f07 100644 --- a/deps/uv/src/unix/no-proctitle.c +++ b/deps/uv/src/unix/no-proctitle.c @@ -29,6 +29,9 @@ char** uv_setup_args(int argc, char** argv) { return argv; } +void uv__process_title_cleanup(void) { +} + int uv_set_process_title(const char* title) { return 0; } diff --git a/deps/uv/src/unix/proctitle.c b/deps/uv/src/unix/proctitle.c index d124d3c7fcfee0..4ee991fcc32466 100644 --- a/deps/uv/src/unix/proctitle.c +++ b/deps/uv/src/unix/proctitle.c @@ -145,7 +145,7 @@ int uv_get_process_title(char* buffer, size_t size) { } -UV_DESTRUCTOR(static void free_args_mem(void)) { +void uv__process_title_cleanup(void) { uv__free(args_mem); /* Keep valgrind happy. */ args_mem = NULL; } diff --git a/deps/uv/src/unix/signal.c b/deps/uv/src/unix/signal.c index 1e7e8ac574dfa4..1c83e095bcdead 100644 --- a/deps/uv/src/unix/signal.c +++ b/deps/uv/src/unix/signal.c @@ -77,7 +77,7 @@ static void uv__signal_global_init(void) { } -UV_DESTRUCTOR(static void uv__signal_global_fini(void)) { +void uv__signal_cleanup(void) { /* We can only use signal-safe functions here. * That includes read/write and close, fortunately. * We do all of this directly here instead of resetting @@ -98,7 +98,7 @@ UV_DESTRUCTOR(static void uv__signal_global_fini(void)) { static void uv__signal_global_reinit(void) { - uv__signal_global_fini(); + uv__signal_cleanup(); if (uv__make_pipe(uv__signal_lock_pipefd, 0)) abort(); diff --git a/deps/uv/src/unix/thread.c b/deps/uv/src/unix/thread.c index f10c351ebba27a..c9a18d1e8d440a 100644 --- a/deps/uv/src/unix/thread.c +++ b/deps/uv/src/unix/thread.c @@ -172,10 +172,11 @@ static size_t thread_stack_size(void) { #if defined(__APPLE__) || defined(__linux__) struct rlimit lim; - if (getrlimit(RLIMIT_STACK, &lim)) - abort(); - - if (lim.rlim_cur != RLIM_INFINITY) { + /* getrlimit() can fail on some aarch64 systems due to a glibc bug where + * the system call wrapper invokes the wrong system call. Don't treat + * that as fatal, just use the default stack size instead. + */ + if (0 == getrlimit(RLIMIT_STACK, &lim) && lim.rlim_cur != RLIM_INFINITY) { /* pthread_attr_setstacksize() expects page-aligned values. */ lim.rlim_cur -= lim.rlim_cur % (rlim_t) getpagesize(); diff --git a/deps/uv/src/unix/udp.c b/deps/uv/src/unix/udp.c index 3aa11c5beeb4ad..7cf80ef3b9f648 100644 --- a/deps/uv/src/unix/udp.c +++ b/deps/uv/src/unix/udp.c @@ -42,6 +42,11 @@ # define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP #endif +union uv__sockaddr { + struct sockaddr_in6 in6; + struct sockaddr_in in; + struct sockaddr addr; +}; static void uv__udp_run_completed(uv_udp_t* handle); static void uv__udp_io(uv_loop_t* loop, uv__io_t* w, unsigned int revents); @@ -202,6 +207,9 @@ static int uv__udp_recvmmsg(uv_udp_t* handle, uv_buf_t* buf) { msgs[k].msg_hdr.msg_iovlen = 1; msgs[k].msg_hdr.msg_name = peers + k; msgs[k].msg_hdr.msg_namelen = sizeof(peers[0]); + msgs[k].msg_hdr.msg_control = NULL; + msgs[k].msg_hdr.msg_controllen = 0; + msgs[k].msg_hdr.msg_flags = 0; } do @@ -564,11 +572,7 @@ int uv__udp_bind(uv_udp_t* handle, static int uv__udp_maybe_deferred_bind(uv_udp_t* handle, int domain, unsigned int flags) { - union { - struct sockaddr_in6 in6; - struct sockaddr_in in; - struct sockaddr addr; - } taddr; + union uv__sockaddr taddr; socklen_t addrlen; if (handle->io_watcher.fd != -1) @@ -921,8 +925,10 @@ static int uv__udp_set_source_membership6(uv_udp_t* handle, mreq.gsr_interface = 0; } - memcpy(&mreq.gsr_group, multicast_addr, sizeof(mreq.gsr_group)); - memcpy(&mreq.gsr_source, source_addr, sizeof(mreq.gsr_source)); + STATIC_ASSERT(sizeof(mreq.gsr_group) >= sizeof(*multicast_addr)); + STATIC_ASSERT(sizeof(mreq.gsr_source) >= sizeof(*source_addr)); + memcpy(&mreq.gsr_group, multicast_addr, sizeof(*multicast_addr)); + memcpy(&mreq.gsr_source, source_addr, sizeof(*source_addr)); if (membership == UV_JOIN_GROUP) optname = MCAST_JOIN_SOURCE_GROUP; @@ -944,29 +950,17 @@ static int uv__udp_set_source_membership6(uv_udp_t* handle, #endif -int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) { - int domain; - int err; - int extra_flags; +int uv__udp_init_ex(uv_loop_t* loop, + uv_udp_t* handle, + unsigned flags, + int domain) { int fd; - /* Use the lower 8 bits for the domain */ - domain = flags & 0xFF; - if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC) - return UV_EINVAL; - - /* Use the higher bits for extra flags */ - extra_flags = flags & ~0xFF; - if (extra_flags & ~UV_UDP_RECVMMSG) - return UV_EINVAL; - + fd = -1; if (domain != AF_UNSPEC) { - err = uv__socket(domain, SOCK_DGRAM, 0); - if (err < 0) - return err; - fd = err; - } else { - fd = -1; + fd = uv__socket(domain, SOCK_DGRAM, 0); + if (fd < 0) + return fd; } uv__handle_init(loop, (uv_handle_t*)handle, UV_UDP); @@ -978,18 +972,10 @@ int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) { QUEUE_INIT(&handle->write_queue); QUEUE_INIT(&handle->write_completed_queue); - if (extra_flags & UV_UDP_RECVMMSG) - handle->flags |= UV_HANDLE_UDP_RECVMMSG; - return 0; } -int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle) { - return uv_udp_init_ex(loop, handle, AF_UNSPEC); -} - - int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) { int err; @@ -1047,40 +1033,31 @@ int uv_udp_set_source_membership(uv_udp_t* handle, uv_membership membership) { #if !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__ANDROID__) int err; - struct sockaddr_storage mcast_addr; - struct sockaddr_in* mcast_addr4; - struct sockaddr_in6* mcast_addr6; - struct sockaddr_storage src_addr; - struct sockaddr_in* src_addr4; - struct sockaddr_in6* src_addr6; - - mcast_addr4 = (struct sockaddr_in*)&mcast_addr; - mcast_addr6 = (struct sockaddr_in6*)&mcast_addr; - src_addr4 = (struct sockaddr_in*)&src_addr; - src_addr6 = (struct sockaddr_in6*)&src_addr; - - err = uv_ip4_addr(multicast_addr, 0, mcast_addr4); + union uv__sockaddr mcast_addr; + union uv__sockaddr src_addr; + + err = uv_ip4_addr(multicast_addr, 0, &mcast_addr.in); if (err) { - err = uv_ip6_addr(multicast_addr, 0, mcast_addr6); + err = uv_ip6_addr(multicast_addr, 0, &mcast_addr.in6); if (err) return err; - err = uv_ip6_addr(source_addr, 0, src_addr6); + err = uv_ip6_addr(source_addr, 0, &src_addr.in6); if (err) return err; return uv__udp_set_source_membership6(handle, - mcast_addr6, + &mcast_addr.in6, interface_addr, - src_addr6, + &src_addr.in6, membership); } - err = uv_ip4_addr(source_addr, 0, src_addr4); + err = uv_ip4_addr(source_addr, 0, &src_addr.in); if (err) return err; return uv__udp_set_source_membership4(handle, - mcast_addr4, + &mcast_addr.in, interface_addr, - src_addr4, + &src_addr.in, membership); #else return UV_ENOSYS; diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c index 5cb1a8c898f7ae..a25d6aaef7217f 100644 --- a/deps/uv/src/uv-common.c +++ b/deps/uv/src/uv-common.c @@ -293,6 +293,36 @@ int uv_tcp_bind(uv_tcp_t* handle, } +int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned flags) { + unsigned extra_flags; + int domain; + int rc; + + /* Use the lower 8 bits for the domain. */ + domain = flags & 0xFF; + if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC) + return UV_EINVAL; + + /* Use the higher bits for extra flags. */ + extra_flags = flags & ~0xFF; + if (extra_flags & ~UV_UDP_RECVMMSG) + return UV_EINVAL; + + rc = uv__udp_init_ex(loop, handle, flags, domain); + + if (rc == 0) + if (extra_flags & UV_UDP_RECVMMSG) + handle->flags |= UV_HANDLE_UDP_RECVMMSG; + + return rc; +} + + +int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle) { + return uv_udp_init_ex(loop, handle, AF_UNSPEC); +} + + int uv_udp_bind(uv_udp_t* handle, const struct sockaddr* addr, unsigned int flags) { @@ -821,3 +851,19 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { uv__free(cpu_infos); } + + +#ifdef __GNUC__ /* Also covers __clang__ and __INTEL_COMPILER. */ +__attribute__((destructor)) +#endif +void uv_library_shutdown(void) { + static int was_shutdown; + + if (was_shutdown) + return; + + uv__process_title_cleanup(); + uv__signal_cleanup(); + uv__threadpool_cleanup(); + was_shutdown = 1; +} diff --git a/deps/uv/src/uv-common.h b/deps/uv/src/uv-common.h index f08fb8ae091e72..0b0f5f86a01a12 100644 --- a/deps/uv/src/uv-common.h +++ b/deps/uv/src/uv-common.h @@ -139,6 +139,11 @@ int uv__tcp_connect(uv_connect_t* req, unsigned int addrlen, uv_connect_cb cb); +int uv__udp_init_ex(uv_loop_t* loop, + uv_udp_t* handle, + unsigned flags, + int domain); + int uv__udp_bind(uv_udp_t* handle, const struct sockaddr* addr, unsigned int addrlen, @@ -201,6 +206,10 @@ int uv__next_timeout(const uv_loop_t* loop); void uv__run_timers(uv_loop_t* loop); void uv__timer_close(uv_timer_t* handle); +void uv__process_title_cleanup(void); +void uv__signal_cleanup(void); +void uv__threadpool_cleanup(void); + #define uv__has_active_reqs(loop) \ ((loop)->active_reqs.count > 0) diff --git a/deps/uv/src/win/core.c b/deps/uv/src/win/core.c index 6ded90cdcc7f86..9974a115534320 100644 --- a/deps/uv/src/win/core.c +++ b/deps/uv/src/win/core.c @@ -449,12 +449,12 @@ static void uv__poll(uv_loop_t* loop, DWORD timeout) { timeout_time = loop->time + timeout; for (repeat = 0; ; repeat++) { - success = GetQueuedCompletionStatusEx(loop->iocp, - overlappeds, - ARRAY_SIZE(overlappeds), - &count, - timeout, - FALSE); + success = pGetQueuedCompletionStatusEx(loop->iocp, + overlappeds, + ARRAY_SIZE(overlappeds), + &count, + timeout, + FALSE); if (success) { for (i = 0; i < count; i++) { diff --git a/deps/uv/src/win/error.c b/deps/uv/src/win/error.c index 32ac5e596fea82..3ec984c83eb077 100644 --- a/deps/uv/src/win/error.c +++ b/deps/uv/src/win/error.c @@ -72,6 +72,7 @@ int uv_translate_sys_error(int sys_errno) { case ERROR_NOACCESS: return UV_EACCES; case WSAEACCES: return UV_EACCES; case ERROR_ELEVATION_REQUIRED: return UV_EACCES; + case ERROR_CANT_ACCESS_FILE: return UV_EACCES; case ERROR_ADDRESS_ALREADY_ASSOCIATED: return UV_EADDRINUSE; case WSAEADDRINUSE: return UV_EADDRINUSE; case WSAEADDRNOTAVAIL: return UV_EADDRNOTAVAIL; diff --git a/deps/uv/src/win/fs-event.c b/deps/uv/src/win/fs-event.c index acf8e1107e9786..0126c5ededf376 100644 --- a/deps/uv/src/win/fs-event.c +++ b/deps/uv/src/win/fs-event.c @@ -83,6 +83,7 @@ static void uv_relative_path(const WCHAR* filename, static int uv_split_path(const WCHAR* filename, WCHAR** dir, WCHAR** file) { size_t len, i; + DWORD dir_len; if (filename == NULL) { if (dir != NULL) @@ -97,12 +98,16 @@ static int uv_split_path(const WCHAR* filename, WCHAR** dir, if (i == 0) { if (dir) { - *dir = (WCHAR*)uv__malloc((MAX_PATH + 1) * sizeof(WCHAR)); + dir_len = GetCurrentDirectoryW(0, NULL); + if (dir_len == 0) { + return -1; + } + *dir = (WCHAR*)uv__malloc(dir_len * sizeof(WCHAR)); if (!*dir) { uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); } - if (!GetCurrentDirectoryW(MAX_PATH, *dir)) { + if (!GetCurrentDirectoryW(dir_len, *dir)) { uv__free(*dir); *dir = NULL; return -1; @@ -155,9 +160,11 @@ int uv_fs_event_start(uv_fs_event_t* handle, int name_size, is_path_dir, size; DWORD attr, last_error; WCHAR* dir = NULL, *dir_to_watch, *pathw = NULL; - WCHAR short_path_buffer[MAX_PATH]; + DWORD short_path_buffer_len; + WCHAR *short_path_buffer; WCHAR* short_path, *long_path; + short_path = NULL; if (uv__is_active(handle)) return UV_EINVAL; @@ -230,13 +237,23 @@ int uv_fs_event_start(uv_fs_event_t* handle, */ /* Convert to short path. */ + short_path_buffer = NULL; + short_path_buffer_len = GetShortPathNameW(pathw, NULL, 0); + if (short_path_buffer_len == 0) { + goto short_path_done; + } + short_path_buffer = uv__malloc(short_path_buffer_len * sizeof(WCHAR)); + if (short_path_buffer == NULL) { + goto short_path_done; + } if (GetShortPathNameW(pathw, short_path_buffer, - ARRAY_SIZE(short_path_buffer))) { - short_path = short_path_buffer; - } else { - short_path = NULL; + short_path_buffer_len) == 0) { + uv__free(short_path_buffer); + short_path_buffer = NULL; } +short_path_done: + short_path = short_path_buffer; if (uv_split_path(pathw, &dir, &handle->filew) != 0) { last_error = GetLastError(); @@ -346,6 +363,8 @@ int uv_fs_event_start(uv_fs_event_t* handle, if (uv__is_active(handle)) uv__handle_stop(handle); + uv__free(short_path); + return uv_translate_sys_error(last_error); } diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c index 834c44a26d44cb..9577bc02d3cf24 100644 --- a/deps/uv/src/win/fs.c +++ b/deps/uv/src/win/fs.c @@ -257,6 +257,7 @@ INLINE static void uv_fs_req_init(uv_loop_t* loop, uv_fs_t* req, req->loop = loop; req->flags = 0; req->fs_type = fs_type; + req->sys_errno_ = 0; req->result = 0; req->ptr = NULL; req->path = NULL; @@ -321,6 +322,8 @@ INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr, WCHAR* w_target; DWORD w_target_len; DWORD bytes; + size_t i; + size_t len; if (!DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, @@ -405,6 +408,38 @@ INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr, w_target += 4; w_target_len -= 4; + } else if (reparse_data->ReparseTag == IO_REPARSE_TAG_APPEXECLINK) { + /* String #3 in the list has the target filename. */ + if (reparse_data->AppExecLinkReparseBuffer.StringCount < 3) { + SetLastError(ERROR_SYMLINK_NOT_SUPPORTED); + return -1; + } + w_target = reparse_data->AppExecLinkReparseBuffer.StringList; + /* The StringList buffer contains a list of strings separated by "\0", */ + /* with "\0\0" terminating the list. Move to the 3rd string in the list: */ + for (i = 0; i < 2; ++i) { + len = wcslen(w_target); + if (len == 0) { + SetLastError(ERROR_SYMLINK_NOT_SUPPORTED); + return -1; + } + w_target += len + 1; + } + w_target_len = wcslen(w_target); + if (w_target_len == 0) { + SetLastError(ERROR_SYMLINK_NOT_SUPPORTED); + return -1; + } + /* Make sure it is an absolute path. */ + if (!(w_target_len >= 3 && + ((w_target[0] >= L'a' && w_target[0] <= L'z') || + (w_target[0] >= L'A' && w_target[0] <= L'Z')) && + w_target[1] == L':' && + w_target[2] == L'\\')) { + SetLastError(ERROR_SYMLINK_NOT_SUPPORTED); + return -1; + } + } else { /* Reparse tag does not indicate a symlink. */ SetLastError(ERROR_SYMLINK_NOT_SUPPORTED); @@ -2840,7 +2875,8 @@ int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, INIT(UV_FS_OPEN); err = fs__capture_path(req, path, NULL, cb != NULL); if (err) { - return uv_translate_sys_error(err); + SET_REQ_WIN32_ERROR(req, err); + return req->result; } req->fs.info.file_flags = flags; @@ -2865,8 +2901,10 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_cb cb) { INIT(UV_FS_READ); - if (bufs == NULL || nbufs == 0) + if (bufs == NULL || nbufs == 0) { + SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER); return UV_EINVAL; + } req->file.fd = fd; @@ -2875,8 +2913,10 @@ int uv_fs_read(uv_loop_t* loop, if (nbufs > ARRAY_SIZE(req->fs.info.bufsml)) req->fs.info.bufs = uv__malloc(nbufs * sizeof(*bufs)); - if (req->fs.info.bufs == NULL) + if (req->fs.info.bufs == NULL) { + SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY); return UV_ENOMEM; + } memcpy(req->fs.info.bufs, bufs, nbufs * sizeof(*bufs)); @@ -2894,8 +2934,10 @@ int uv_fs_write(uv_loop_t* loop, uv_fs_cb cb) { INIT(UV_FS_WRITE); - if (bufs == NULL || nbufs == 0) + if (bufs == NULL || nbufs == 0) { + SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER); return UV_EINVAL; + } req->file.fd = fd; @@ -2904,8 +2946,10 @@ int uv_fs_write(uv_loop_t* loop, if (nbufs > ARRAY_SIZE(req->fs.info.bufsml)) req->fs.info.bufs = uv__malloc(nbufs * sizeof(*bufs)); - if (req->fs.info.bufs == NULL) + if (req->fs.info.bufs == NULL) { + SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY); return UV_ENOMEM; + } memcpy(req->fs.info.bufs, bufs, nbufs * sizeof(*bufs)); @@ -2921,7 +2965,8 @@ int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, INIT(UV_FS_UNLINK); err = fs__capture_path(req, path, NULL, cb != NULL); if (err) { - return uv_translate_sys_error(err); + SET_REQ_WIN32_ERROR(req, err); + return req->result; } POST; @@ -2935,7 +2980,8 @@ int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, INIT(UV_FS_MKDIR); err = fs__capture_path(req, path, NULL, cb != NULL); if (err) { - return uv_translate_sys_error(err); + SET_REQ_WIN32_ERROR(req, err); + return req->result; } req->fs.info.mode = mode; @@ -2951,8 +2997,10 @@ int uv_fs_mkdtemp(uv_loop_t* loop, INIT(UV_FS_MKDTEMP); err = fs__capture_path(req, tpl, NULL, TRUE); - if (err) - return uv_translate_sys_error(err); + if (err) { + SET_REQ_WIN32_ERROR(req, err); + return req->result; + } POST; } @@ -2966,8 +3014,10 @@ int uv_fs_mkstemp(uv_loop_t* loop, INIT(UV_FS_MKSTEMP); err = fs__capture_path(req, tpl, NULL, TRUE); - if (err) - return uv_translate_sys_error(err); + if (err) { + SET_REQ_WIN32_ERROR(req, err); + return req->result; + } POST; } @@ -2979,7 +3029,8 @@ int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { INIT(UV_FS_RMDIR); err = fs__capture_path(req, path, NULL, cb != NULL); if (err) { - return uv_translate_sys_error(err); + SET_REQ_WIN32_ERROR(req, err); + return req->result; } POST; @@ -2993,7 +3044,8 @@ int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, INIT(UV_FS_SCANDIR); err = fs__capture_path(req, path, NULL, cb != NULL); if (err) { - return uv_translate_sys_error(err); + SET_REQ_WIN32_ERROR(req, err); + return req->result; } req->fs.info.file_flags = flags; @@ -3008,8 +3060,10 @@ int uv_fs_opendir(uv_loop_t* loop, INIT(UV_FS_OPENDIR); err = fs__capture_path(req, path, NULL, cb != NULL); - if (err) - return uv_translate_sys_error(err); + if (err) { + SET_REQ_WIN32_ERROR(req, err); + return req->result; + } POST; } @@ -3022,6 +3076,7 @@ int uv_fs_readdir(uv_loop_t* loop, if (dir == NULL || dir->dirents == NULL || dir->dir_handle == INVALID_HANDLE_VALUE) { + SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER); return UV_EINVAL; } @@ -3034,8 +3089,10 @@ int uv_fs_closedir(uv_loop_t* loop, uv_dir_t* dir, uv_fs_cb cb) { INIT(UV_FS_CLOSEDIR); - if (dir == NULL) + if (dir == NULL) { + SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER); return UV_EINVAL; + } req->ptr = dir; POST; } @@ -3047,7 +3104,8 @@ int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path, INIT(UV_FS_LINK); err = fs__capture_path(req, path, new_path, cb != NULL); if (err) { - return uv_translate_sys_error(err); + SET_REQ_WIN32_ERROR(req, err); + return req->result; } POST; @@ -3061,7 +3119,8 @@ int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path, INIT(UV_FS_SYMLINK); err = fs__capture_path(req, path, new_path, cb != NULL); if (err) { - return uv_translate_sys_error(err); + SET_REQ_WIN32_ERROR(req, err); + return req->result; } req->fs.info.file_flags = flags; @@ -3076,7 +3135,8 @@ int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path, INIT(UV_FS_READLINK); err = fs__capture_path(req, path, NULL, cb != NULL); if (err) { - return uv_translate_sys_error(err); + SET_REQ_WIN32_ERROR(req, err); + return req->result; } POST; @@ -3090,12 +3150,14 @@ int uv_fs_realpath(uv_loop_t* loop, uv_fs_t* req, const char* path, INIT(UV_FS_REALPATH); if (!path) { + SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER); return UV_EINVAL; } err = fs__capture_path(req, path, NULL, cb != NULL); if (err) { - return uv_translate_sys_error(err); + SET_REQ_WIN32_ERROR(req, err); + return req->result; } POST; @@ -3109,7 +3171,8 @@ int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, INIT(UV_FS_CHOWN); err = fs__capture_path(req, path, NULL, cb != NULL); if (err) { - return uv_translate_sys_error(err); + SET_REQ_WIN32_ERROR(req, err); + return req->result; } POST; @@ -3130,8 +3193,10 @@ int uv_fs_lchown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, INIT(UV_FS_LCHOWN); err = fs__capture_path(req, path, NULL, cb != NULL); if (err) { - return uv_translate_sys_error(err); + SET_REQ_WIN32_ERROR(req, err); + return req->result; } + POST; } @@ -3142,7 +3207,8 @@ int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { INIT(UV_FS_STAT); err = fs__capture_path(req, path, NULL, cb != NULL); if (err) { - return uv_translate_sys_error(err); + SET_REQ_WIN32_ERROR(req, err); + return req->result; } POST; @@ -3155,7 +3221,8 @@ int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { INIT(UV_FS_LSTAT); err = fs__capture_path(req, path, NULL, cb != NULL); if (err) { - return uv_translate_sys_error(err); + SET_REQ_WIN32_ERROR(req, err); + return req->result; } POST; @@ -3176,7 +3243,8 @@ int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path, INIT(UV_FS_RENAME); err = fs__capture_path(req, path, new_path, cb != NULL); if (err) { - return uv_translate_sys_error(err); + SET_REQ_WIN32_ERROR(req, err); + return req->result; } POST; @@ -3219,13 +3287,15 @@ int uv_fs_copyfile(uv_loop_t* loop, if (flags & ~(UV_FS_COPYFILE_EXCL | UV_FS_COPYFILE_FICLONE | UV_FS_COPYFILE_FICLONE_FORCE)) { + SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER); return UV_EINVAL; } err = fs__capture_path(req, path, new_path, cb != NULL); - - if (err) - return uv_translate_sys_error(err); + if (err) { + SET_REQ_WIN32_ERROR(req, err); + return req->result; + } req->fs.info.file_flags = flags; POST; @@ -3252,8 +3322,10 @@ int uv_fs_access(uv_loop_t* loop, INIT(UV_FS_ACCESS); err = fs__capture_path(req, path, NULL, cb != NULL); - if (err) - return uv_translate_sys_error(err); + if (err) { + SET_REQ_WIN32_ERROR(req, err); + return req->result; + } req->fs.info.mode = flags; POST; @@ -3267,7 +3339,8 @@ int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, INIT(UV_FS_CHMOD); err = fs__capture_path(req, path, NULL, cb != NULL); if (err) { - return uv_translate_sys_error(err); + SET_REQ_WIN32_ERROR(req, err); + return req->result; } req->fs.info.mode = mode; @@ -3291,7 +3364,8 @@ int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, INIT(UV_FS_UTIME); err = fs__capture_path(req, path, NULL, cb != NULL); if (err) { - return uv_translate_sys_error(err); + SET_REQ_WIN32_ERROR(req, err); + return req->result; } req->fs.time.atime = atime; @@ -3316,7 +3390,8 @@ int uv_fs_lutime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, INIT(UV_FS_LUTIME); err = fs__capture_path(req, path, NULL, cb != NULL); if (err) { - return uv_translate_sys_error(err); + SET_REQ_WIN32_ERROR(req, err); + return req->result; } req->fs.time.atime = atime; @@ -3333,8 +3408,14 @@ int uv_fs_statfs(uv_loop_t* loop, INIT(UV_FS_STATFS); err = fs__capture_path(req, path, NULL, cb != NULL); - if (err) - return uv_translate_sys_error(err); + if (err) { + SET_REQ_WIN32_ERROR(req, err); + return req->result; + } POST; } + +int uv_fs_get_system_error(const uv_fs_t* req) { + return req->sys_errno_; +} diff --git a/deps/uv/src/win/poll.c b/deps/uv/src/win/poll.c index 3c6678600e40cc..87858590c8525a 100644 --- a/deps/uv/src/win/poll.c +++ b/deps/uv/src/win/poll.c @@ -134,32 +134,6 @@ static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) { } -static int uv__fast_poll_cancel_poll_req(uv_loop_t* loop, uv_poll_t* handle) { - AFD_POLL_INFO afd_poll_info; - int result; - - afd_poll_info.Exclusive = TRUE; - afd_poll_info.NumberOfHandles = 1; - afd_poll_info.Timeout.QuadPart = INT64_MAX; - afd_poll_info.Handles[0].Handle = (HANDLE) handle->socket; - afd_poll_info.Handles[0].Status = 0; - afd_poll_info.Handles[0].Events = AFD_POLL_ALL; - - result = uv_msafd_poll(handle->socket, - &afd_poll_info, - uv__get_afd_poll_info_dummy(), - uv__get_overlapped_dummy()); - - if (result == SOCKET_ERROR) { - DWORD error = WSAGetLastError(); - if (error != WSA_IO_PENDING) - return error; - } - - return 0; -} - - static void uv__fast_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, uv_req_t* req) { unsigned char mask_events; @@ -226,44 +200,6 @@ static void uv__fast_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, } -static int uv__fast_poll_set(uv_loop_t* loop, uv_poll_t* handle, int events) { - assert(handle->type == UV_POLL); - assert(!(handle->flags & UV_HANDLE_CLOSING)); - assert((events & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT)) == 0); - - handle->events = events; - - if (handle->events != 0) { - uv__handle_start(handle); - } else { - uv__handle_stop(handle); - } - - if ((handle->events & ~(handle->submitted_events_1 | - handle->submitted_events_2)) != 0) { - uv__fast_poll_submit_poll_req(handle->loop, handle); - } - - return 0; -} - - -static int uv__fast_poll_close(uv_loop_t* loop, uv_poll_t* handle) { - handle->events = 0; - uv__handle_closing(handle); - - if (handle->submitted_events_1 == 0 && - handle->submitted_events_2 == 0) { - uv_want_endgame(loop, (uv_handle_t*) handle); - return 0; - } else { - /* Cancel outstanding poll requests by executing another, unique poll - * request that forces the outstanding ones to return. */ - return uv__fast_poll_cancel_poll_req(loop, handle); - } -} - - static SOCKET uv__fast_poll_create_peer_socket(HANDLE iocp, WSAPROTOCOL_INFOW* protocol_info) { SOCKET sock = 0; @@ -469,41 +405,6 @@ static void uv__slow_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, } -static int uv__slow_poll_set(uv_loop_t* loop, uv_poll_t* handle, int events) { - assert(handle->type == UV_POLL); - assert(!(handle->flags & UV_HANDLE_CLOSING)); - assert((events & ~(UV_READABLE | UV_WRITABLE)) == 0); - - handle->events = events; - - if (handle->events != 0) { - uv__handle_start(handle); - } else { - uv__handle_stop(handle); - } - - if ((handle->events & - ~(handle->submitted_events_1 | handle->submitted_events_2)) != 0) { - uv__slow_poll_submit_poll_req(handle->loop, handle); - } - - return 0; -} - - -static int uv__slow_poll_close(uv_loop_t* loop, uv_poll_t* handle) { - handle->events = 0; - uv__handle_closing(handle); - - if (handle->submitted_events_1 == 0 && - handle->submitted_events_2 == 0) { - uv_want_endgame(loop, (uv_handle_t*) handle); - } - - return 0; -} - - int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) { return uv_poll_init_socket(loop, handle, (SOCKET) uv__get_osfhandle(fd)); } @@ -582,35 +483,43 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle, } -int uv_poll_start(uv_poll_t* handle, int events, uv_poll_cb cb) { - int err; +static int uv__poll_set(uv_poll_t* handle, int events, uv_poll_cb cb) { + int submitted_events; - if (!(handle->flags & UV_HANDLE_POLL_SLOW)) { - err = uv__fast_poll_set(handle->loop, handle, events); - } else { - err = uv__slow_poll_set(handle->loop, handle, events); - } + assert(handle->type == UV_POLL); + assert(!(handle->flags & UV_HANDLE_CLOSING)); + assert((events & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT)) == 0); + + handle->events = events; + handle->poll_cb = cb; - if (err) { - return uv_translate_sys_error(err); + if (handle->events == 0) { + uv__handle_stop(handle); + return 0; } - handle->poll_cb = cb; + uv__handle_start(handle); + submitted_events = handle->submitted_events_1 | handle->submitted_events_2; + + if (handle->events & ~submitted_events) { + if (handle->flags & UV_HANDLE_POLL_SLOW) { + uv__slow_poll_submit_poll_req(handle->loop, handle); + } else { + uv__fast_poll_submit_poll_req(handle->loop, handle); + } + } return 0; } -int uv_poll_stop(uv_poll_t* handle) { - int err; +int uv_poll_start(uv_poll_t* handle, int events, uv_poll_cb cb) { + return uv__poll_set(handle, events, cb); +} - if (!(handle->flags & UV_HANDLE_POLL_SLOW)) { - err = uv__fast_poll_set(handle->loop, handle, 0); - } else { - err = uv__slow_poll_set(handle->loop, handle, 0); - } - return uv_translate_sys_error(err); +int uv_poll_stop(uv_poll_t* handle) { + return uv__poll_set(handle, 0, handle->poll_cb); } @@ -624,11 +533,43 @@ void uv_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, uv_req_t* req) { int uv_poll_close(uv_loop_t* loop, uv_poll_t* handle) { - if (!(handle->flags & UV_HANDLE_POLL_SLOW)) { - return uv__fast_poll_close(loop, handle); - } else { - return uv__slow_poll_close(loop, handle); + AFD_POLL_INFO afd_poll_info; + DWORD error; + int result; + + handle->events = 0; + uv__handle_closing(handle); + + if (handle->submitted_events_1 == 0 && + handle->submitted_events_2 == 0) { + uv_want_endgame(loop, (uv_handle_t*) handle); + return 0; + } + + if (handle->flags & UV_HANDLE_POLL_SLOW) + return 0; + + /* Cancel outstanding poll requests by executing another, unique poll + * request that forces the outstanding ones to return. */ + afd_poll_info.Exclusive = TRUE; + afd_poll_info.NumberOfHandles = 1; + afd_poll_info.Timeout.QuadPart = INT64_MAX; + afd_poll_info.Handles[0].Handle = (HANDLE) handle->socket; + afd_poll_info.Handles[0].Status = 0; + afd_poll_info.Handles[0].Events = AFD_POLL_ALL; + + result = uv_msafd_poll(handle->socket, + &afd_poll_info, + uv__get_afd_poll_info_dummy(), + uv__get_overlapped_dummy()); + + if (result == SOCKET_ERROR) { + error = WSAGetLastError(); + if (error != WSA_IO_PENDING) + return uv_translate_sys_error(error); } + + return 0; } diff --git a/deps/uv/src/win/signal.c b/deps/uv/src/win/signal.c index 276dc609733320..3d9f92cfb17017 100644 --- a/deps/uv/src/win/signal.c +++ b/deps/uv/src/win/signal.c @@ -46,6 +46,11 @@ void uv_signals_init(void) { } +void uv__signal_cleanup(void) { + /* TODO(bnoordhuis) Undo effects of uv_signal_init()? */ +} + + static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) { /* Compare signums first so all watchers with the same signnum end up * adjacent. */ diff --git a/deps/uv/src/win/udp.c b/deps/uv/src/win/udp.c index 3daa55f62db063..1c4977af968a46 100644 --- a/deps/uv/src/win/udp.c +++ b/deps/uv/src/win/udp.c @@ -125,17 +125,10 @@ static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket, } -int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) { - int domain; - - /* Use the lower 8 bits for the domain */ - domain = flags & 0xFF; - if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC) - return UV_EINVAL; - - if (flags & ~0xFF) - return UV_EINVAL; - +int uv__udp_init_ex(uv_loop_t* loop, + uv_udp_t* handle, + unsigned flags, + int domain) { uv__handle_init(loop, (uv_handle_t*) handle, UV_UDP); handle->socket = INVALID_SOCKET; handle->reqs_pending = 0; @@ -174,11 +167,6 @@ int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) { } -int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle) { - return uv_udp_init_ex(loop, handle, AF_UNSPEC); -} - - void uv_udp_close(uv_loop_t* loop, uv_udp_t* handle) { uv_udp_recv_stop(handle); closesocket(handle->socket); @@ -786,8 +774,10 @@ int uv__udp_set_source_membership6(uv_udp_t* handle, mreq.gsr_interface = 0; } - memcpy(&mreq.gsr_group, multicast_addr, sizeof(mreq.gsr_group)); - memcpy(&mreq.gsr_source, source_addr, sizeof(mreq.gsr_source)); + STATIC_ASSERT(sizeof(mreq.gsr_group) >= sizeof(*multicast_addr)); + STATIC_ASSERT(sizeof(mreq.gsr_source) >= sizeof(*source_addr)); + memcpy(&mreq.gsr_group, multicast_addr, sizeof(*multicast_addr)); + memcpy(&mreq.gsr_source, source_addr, sizeof(*source_addr)); if (membership == UV_JOIN_GROUP) optname = MCAST_JOIN_SOURCE_GROUP; diff --git a/deps/uv/src/win/util.c b/deps/uv/src/win/util.c index aaa7ba0325b0e5..9e1e7f73e3168b 100644 --- a/deps/uv/src/win/util.c +++ b/deps/uv/src/win/util.c @@ -60,9 +60,6 @@ #endif -/* Maximum environment variable size, including the terminating null */ -#define MAX_ENV_VAR_LENGTH 32767 - /* A RtlGenRandom() by any other name... */ extern BOOLEAN NTAPI SystemFunction036(PVOID Buffer, ULONG BufferLength); @@ -154,20 +151,26 @@ int uv_exepath(char* buffer, size_t* size_ptr) { int uv_cwd(char* buffer, size_t* size) { DWORD utf16_len; - WCHAR utf16_buffer[MAX_PATH]; + WCHAR *utf16_buffer; int r; if (buffer == NULL || size == NULL) { return UV_EINVAL; } - utf16_len = GetCurrentDirectoryW(MAX_PATH, utf16_buffer); + utf16_len = GetCurrentDirectoryW(0, NULL); if (utf16_len == 0) { return uv_translate_sys_error(GetLastError()); - } else if (utf16_len > MAX_PATH) { - /* This should be impossible; however the CRT has a code path to deal with - * this scenario, so I added a check anyway. */ - return UV_EIO; + } + utf16_buffer = uv__malloc(utf16_len * sizeof(WCHAR)); + if (utf16_buffer == NULL) { + return UV_ENOMEM; + } + + utf16_len = GetCurrentDirectoryW(utf16_len, utf16_buffer); + if (utf16_len == 0) { + uv__free(utf16_buffer); + return uv_translate_sys_error(GetLastError()); } /* utf16_len contains the length, *not* including the terminating null. */ @@ -191,8 +194,10 @@ int uv_cwd(char* buffer, size_t* size) { NULL, NULL); if (r == 0) { + uv__free(utf16_buffer); return uv_translate_sys_error(GetLastError()); } else if (r > (int) *size) { + uv__free(utf16_buffer); *size = r; return UV_ENOBUFS; } @@ -206,6 +211,8 @@ int uv_cwd(char* buffer, size_t* size) { *size > INT_MAX ? INT_MAX : (int) *size, NULL, NULL); + uv__free(utf16_buffer); + if (r == 0) { return uv_translate_sys_error(GetLastError()); } @@ -216,43 +223,61 @@ int uv_cwd(char* buffer, size_t* size) { int uv_chdir(const char* dir) { - WCHAR utf16_buffer[MAX_PATH]; - size_t utf16_len; + WCHAR *utf16_buffer; + size_t utf16_len, new_utf16_len; WCHAR drive_letter, env_var[4]; if (dir == NULL) { return UV_EINVAL; } + utf16_len = MultiByteToWideChar(CP_UTF8, + 0, + dir, + -1, + NULL, + 0); + if (utf16_len == 0) { + return uv_translate_sys_error(GetLastError()); + } + utf16_buffer = uv__malloc(utf16_len * sizeof(WCHAR)); + if (utf16_buffer == NULL) { + return UV_ENOMEM; + } + if (MultiByteToWideChar(CP_UTF8, 0, dir, -1, utf16_buffer, - MAX_PATH) == 0) { - DWORD error = GetLastError(); - /* The maximum length of the current working directory is 260 chars, - * including terminating null. If it doesn't fit, the path name must be too - * long. */ - if (error == ERROR_INSUFFICIENT_BUFFER) { - return UV_ENAMETOOLONG; - } else { - return uv_translate_sys_error(error); - } + utf16_len) == 0) { + uv__free(utf16_buffer); + return uv_translate_sys_error(GetLastError()); } if (!SetCurrentDirectoryW(utf16_buffer)) { + uv__free(utf16_buffer); return uv_translate_sys_error(GetLastError()); } /* Windows stores the drive-local path in an "hidden" environment variable, * which has the form "=C:=C:\Windows". SetCurrentDirectory does not update * this, so we'll have to do it. */ - utf16_len = GetCurrentDirectoryW(MAX_PATH, utf16_buffer); + new_utf16_len = GetCurrentDirectoryW(utf16_len, utf16_buffer); + if (new_utf16_len > utf16_len ) { + uv__free(utf16_buffer); + utf16_buffer = uv__malloc(new_utf16_len * sizeof(WCHAR)); + if (utf16_buffer == NULL) { + /* When updating the environment variable fails, return UV_OK anyway. + * We did successfully change current working directory, only updating + * hidden env variable failed. */ + return 0; + } + new_utf16_len = GetCurrentDirectoryW(new_utf16_len, utf16_buffer); + } if (utf16_len == 0) { - return uv_translate_sys_error(GetLastError()); - } else if (utf16_len > MAX_PATH) { - return UV_EIO; + uv__free(utf16_buffer); + return 0; } /* The returned directory should not have a trailing slash, unless it points @@ -284,11 +309,10 @@ int uv_chdir(const char* dir) { env_var[2] = L':'; env_var[3] = L'\0'; - if (!SetEnvironmentVariableW(env_var, utf16_buffer)) { - return uv_translate_sys_error(GetLastError()); - } + SetEnvironmentVariableW(env_var, utf16_buffer); } + uv__free(utf16_buffer); return 0; } @@ -361,6 +385,10 @@ char** uv_setup_args(int argc, char** argv) { } +void uv__process_title_cleanup(void) { +} + + int uv_set_process_title(const char* title) { int err; int length; @@ -1163,20 +1191,29 @@ int uv_os_homedir(char* buffer, size_t* size) { int uv_os_tmpdir(char* buffer, size_t* size) { - wchar_t path[MAX_PATH + 2]; + wchar_t *path; DWORD bufsize; size_t len; if (buffer == NULL || size == NULL || *size == 0) return UV_EINVAL; - len = GetTempPathW(ARRAY_SIZE(path), path); + len = 0; + len = GetTempPathW(0, NULL); + if (len == 0) { + return uv_translate_sys_error(GetLastError()); + } + /* Include space for terminating null char. */ + len += 1; + path = uv__malloc(len * sizeof(wchar_t)); + if (path == NULL) { + return UV_ENOMEM; + } + len = GetTempPathW(len, path); if (len == 0) { + uv__free(path); return uv_translate_sys_error(GetLastError()); - } else if (len > ARRAY_SIZE(path)) { - /* This should not be possible */ - return UV_EIO; } /* The returned directory should not have a trailing slash, unless it points @@ -1191,8 +1228,10 @@ int uv_os_tmpdir(char* buffer, size_t* size) { bufsize = WideCharToMultiByte(CP_UTF8, 0, path, -1, NULL, 0, NULL, NULL); if (bufsize == 0) { + uv__free(path); return uv_translate_sys_error(GetLastError()); } else if (bufsize > *size) { + uv__free(path); *size = bufsize; return UV_ENOBUFS; } @@ -1206,6 +1245,7 @@ int uv_os_tmpdir(char* buffer, size_t* size) { *size, NULL, NULL); + uv__free(path); if (bufsize == 0) return uv_translate_sys_error(GetLastError()); @@ -1325,7 +1365,7 @@ int uv__convert_utf8_to_utf16(const char* utf8, int utf8len, WCHAR** utf16) { int uv__getpwuid_r(uv_passwd_t* pwd) { HANDLE token; wchar_t username[UNLEN + 1]; - wchar_t path[MAX_PATH]; + wchar_t *path; DWORD bufsize; int r; @@ -1336,15 +1376,24 @@ int uv__getpwuid_r(uv_passwd_t* pwd) { if (OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token) == 0) return uv_translate_sys_error(GetLastError()); - bufsize = ARRAY_SIZE(path); - if (!GetUserProfileDirectoryW(token, path, &bufsize)) { + bufsize = 0; + GetUserProfileDirectoryW(token, NULL, &bufsize); + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { r = GetLastError(); CloseHandle(token); + return uv_translate_sys_error(r); + } - /* This should not be possible */ - if (r == ERROR_INSUFFICIENT_BUFFER) - return UV_ENOMEM; + path = uv__malloc(bufsize * sizeof(wchar_t)); + if (path == NULL) { + CloseHandle(token); + return UV_ENOMEM; + } + if (!GetUserProfileDirectoryW(token, path, &bufsize)) { + r = GetLastError(); + CloseHandle(token); + uv__free(path); return uv_translate_sys_error(r); } @@ -1354,6 +1403,7 @@ int uv__getpwuid_r(uv_passwd_t* pwd) { bufsize = ARRAY_SIZE(username); if (!GetUserNameW(username, &bufsize)) { r = GetLastError(); + uv__free(path); /* This should not be possible */ if (r == ERROR_INSUFFICIENT_BUFFER) @@ -1364,6 +1414,7 @@ int uv__getpwuid_r(uv_passwd_t* pwd) { pwd->homedir = NULL; r = uv__convert_utf16_to_utf8(path, -1, &pwd->homedir); + uv__free(path); if (r != 0) return r; @@ -1461,7 +1512,9 @@ int uv_os_environ(uv_env_item_t** envitems, int* count) { int uv_os_getenv(const char* name, char* buffer, size_t* size) { - wchar_t var[MAX_ENV_VAR_LENGTH]; + wchar_t fastvar[512]; + wchar_t* var; + DWORD varlen; wchar_t* name_w; DWORD bufsize; size_t len; @@ -1475,25 +1528,52 @@ int uv_os_getenv(const char* name, char* buffer, size_t* size) { if (r != 0) return r; - SetLastError(ERROR_SUCCESS); - len = GetEnvironmentVariableW(name_w, var, MAX_ENV_VAR_LENGTH); + var = fastvar; + varlen = ARRAY_SIZE(fastvar); + + for (;;) { + SetLastError(ERROR_SUCCESS); + len = GetEnvironmentVariableW(name_w, var, varlen); + + if (len < varlen) + break; + + /* Try repeatedly because we might have been preempted by another thread + * modifying the environment variable just as we're trying to read it. + */ + if (var != fastvar) + uv__free(var); + + varlen = 1 + len; + var = uv__malloc(varlen * sizeof(*var)); + + if (var == NULL) { + r = UV_ENOMEM; + goto fail; + } + } + uv__free(name_w); - assert(len < MAX_ENV_VAR_LENGTH); /* len does not include the null */ + name_w = NULL; if (len == 0) { r = GetLastError(); - if (r != ERROR_SUCCESS) - return uv_translate_sys_error(r); + if (r != ERROR_SUCCESS) { + r = uv_translate_sys_error(r); + goto fail; + } } /* Check how much space we need */ bufsize = WideCharToMultiByte(CP_UTF8, 0, var, -1, NULL, 0, NULL, NULL); if (bufsize == 0) { - return uv_translate_sys_error(GetLastError()); + r = uv_translate_sys_error(GetLastError()); + goto fail; } else if (bufsize > *size) { *size = bufsize; - return UV_ENOBUFS; + r = UV_ENOBUFS; + goto fail; } /* Convert to UTF-8 */ @@ -1506,11 +1586,23 @@ int uv_os_getenv(const char* name, char* buffer, size_t* size) { NULL, NULL); - if (bufsize == 0) - return uv_translate_sys_error(GetLastError()); + if (bufsize == 0) { + r = uv_translate_sys_error(GetLastError()); + goto fail; + } *size = bufsize - 1; - return 0; + r = 0; + +fail: + + if (name_w != NULL) + uv__free(name_w); + + if (var != fastvar) + uv__free(var); + + return r; } diff --git a/deps/uv/src/win/winapi.h b/deps/uv/src/win/winapi.h index 322a212dd73c19..cbe1437a42e6bd 100644 --- a/deps/uv/src/win/winapi.h +++ b/deps/uv/src/win/winapi.h @@ -4152,6 +4152,10 @@ typedef const UNICODE_STRING *PCUNICODE_STRING; struct { UCHAR DataBuffer[1]; } GenericReparseBuffer; + struct { + ULONG StringCount; + WCHAR StringList[1]; + } AppExecLinkReparseBuffer; }; } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; #endif @@ -4517,6 +4521,9 @@ typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION { #ifndef IO_REPARSE_TAG_SYMLINK # define IO_REPARSE_TAG_SYMLINK (0xA000000CL) #endif +#ifndef IO_REPARSE_TAG_APPEXECLINK +# define IO_REPARSE_TAG_APPEXECLINK (0x8000001BL) +#endif typedef VOID (NTAPI *PIO_APC_ROUTINE) (PVOID ApcContext, diff --git a/deps/uv/test/task.h b/deps/uv/test/task.h index 27b731032e10b3..e95e3bde5a7e3e 100644 --- a/deps/uv/test/task.h +++ b/deps/uv/test/task.h @@ -230,6 +230,7 @@ typedef enum { do { \ close_loop(uv_default_loop()); \ ASSERT(0 == uv_loop_close(uv_default_loop())); \ + uv_library_shutdown(); \ } while (0) /* Just sugar for wrapping the main() for a task or helper. */ diff --git a/deps/uv/test/test-connection-fail.c b/deps/uv/test/test-connection-fail.c index 8338cacdec3c5f..5904810252995f 100644 --- a/deps/uv/test/test-connection-fail.c +++ b/deps/uv/test/test-connection-fail.c @@ -120,6 +120,11 @@ static void connection_fail(uv_connect_cb connect_cb) { * expect an error. */ TEST_IMPL(connection_fail) { +/* TODO(gengjiawen): Fix test on QEMU. */ +#if defined(__QEMU__) + RETURN_SKIP("Test does not currently work in QEMU"); +#endif + connection_fail(on_connect_with_close); ASSERT(timer_close_cb_calls == 0); @@ -136,6 +141,11 @@ TEST_IMPL(connection_fail) { * attempt. */ TEST_IMPL(connection_fail_doesnt_auto_close) { +/* TODO(gengjiawen): Fix test on QEMU. */ +#if defined(__QEMU__) + RETURN_SKIP("Test does not currently work in QEMU"); +#endif + int r; r = uv_timer_init(uv_default_loop(), &timer); diff --git a/deps/uv/test/test-env-vars.c b/deps/uv/test/test-env-vars.c index f61c1c6c115cae..ecaba337ca1088 100644 --- a/deps/uv/test/test-env-vars.c +++ b/deps/uv/test/test-env-vars.c @@ -142,5 +142,29 @@ TEST_IMPL(env_vars) { r = uv_os_unsetenv(name2); ASSERT(r == 0); + for (i = 1; i <= 4; i++) { + size_t n; + char* p; + + n = i * 32768; + size = n + 1; + + p = malloc(size); + ASSERT_NOT_NULL(p); + + memset(p, 'x', n); + p[n] = '\0'; + + ASSERT_EQ(0, uv_os_setenv(name, p)); + ASSERT_EQ(0, uv_os_getenv(name, p, &size)); + ASSERT_EQ(n, size); + + for (n = 0; n < size; n++) + ASSERT_EQ('x', p[n]); + + ASSERT_EQ(0, uv_os_unsetenv(name)); + free(p); + } + return 0; } diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c index 2966a53b79d349..ae9923a9a16ec3 100644 --- a/deps/uv/test/test-fs.c +++ b/deps/uv/test/test-fs.c @@ -315,7 +315,7 @@ static void chown_root_cb(uv_fs_t* req) { * User may grant qsecofr's privileges, including changing * the file's ownership to uid 0. */ - ASSERT(req->result == 0); + ASSERT(req->result == 0 || req->result == UV_EPERM); # else ASSERT(req->result == UV_EPERM); # endif @@ -2453,6 +2453,57 @@ TEST_IMPL(fs_non_symlink_reparse_point) { MAKE_VALGRIND_HAPPY(); return 0; } + +TEST_IMPL(fs_lstat_windows_store_apps) { + uv_loop_t* loop; + char localappdata[MAX_PATH]; + char windowsapps_path[MAX_PATH]; + char file_path[MAX_PATH]; + size_t len; + int r; + uv_fs_t req; + uv_fs_t stat_req; + uv_dirent_t dirent; + + loop = uv_default_loop(); + ASSERT_NOT_NULL(loop); + len = sizeof(localappdata); + r = uv_os_getenv("LOCALAPPDATA", localappdata, &len); + if (r == UV_ENOENT) { + MAKE_VALGRIND_HAPPY(); + return TEST_SKIP; + } + ASSERT_EQ(r, 0); + r = snprintf(windowsapps_path, + sizeof(localappdata), + "%s\\Microsoft\\WindowsApps", + localappdata); + ASSERT_GT(r, 0); + if (uv_fs_opendir(loop, &req, windowsapps_path, NULL) != 0) { + /* If we cannot read the directory, skip the test. */ + MAKE_VALGRIND_HAPPY(); + return TEST_SKIP; + } + if (uv_fs_scandir(loop, &req, windowsapps_path, 0, NULL) <= 0) { + MAKE_VALGRIND_HAPPY(); + return TEST_SKIP; + } + while (uv_fs_scandir_next(&req, &dirent) != UV_EOF) { + if (dirent.type != UV_DIRENT_LINK) { + continue; + } + if (snprintf(file_path, + sizeof(file_path), + "%s\\%s", + windowsapps_path, + dirent.name) < 0) { + continue; + } + ASSERT_EQ(uv_fs_lstat(loop, &stat_req, file_path, NULL), 0); + } + MAKE_VALGRIND_HAPPY(); + return 0; +} #endif @@ -4347,3 +4398,21 @@ TEST_IMPL(fs_statfs) { return 0; } + +TEST_IMPL(fs_get_system_error) { + uv_fs_t req; + int r; + int system_error; + + r = uv_fs_statfs(NULL, &req, "non_existing_file", NULL); + ASSERT(r != 0); + + system_error = uv_fs_get_system_error(&req); +#ifdef _WIN32 + ASSERT(system_error == ERROR_FILE_NOT_FOUND); +#else + ASSERT(system_error == ENOENT); +#endif + + return 0; +} diff --git a/deps/uv/test/test-get-currentexe.c b/deps/uv/test/test-get-currentexe.c index 8c730334c205b3..5e4a083f3060b7 100644 --- a/deps/uv/test/test-get-currentexe.c +++ b/deps/uv/test/test-get-currentexe.c @@ -31,6 +31,11 @@ extern char executable_path[]; TEST_IMPL(get_currentexe) { +/* TODO(gengjiawen): Fix test on QEMU. */ +#if defined(__QEMU__) + RETURN_SKIP("Test does not currently work in QEMU"); +#endif + char buffer[PATHMAX]; char path[PATHMAX]; size_t size; diff --git a/deps/uv/test/test-get-passwd.c b/deps/uv/test/test-get-passwd.c index 9b5273b315db6f..abe8be36a332b5 100644 --- a/deps/uv/test/test-get-passwd.c +++ b/deps/uv/test/test-get-passwd.c @@ -24,6 +24,11 @@ #include TEST_IMPL(get_passwd) { +/* TODO(gengjiawen): Fix test on QEMU. */ +#if defined(__QEMU__) + RETURN_SKIP("Test does not currently work in QEMU"); +#endif + uv_passwd_t pwd; size_t len; int r; diff --git a/deps/uv/test/test-getaddrinfo.c b/deps/uv/test/test-getaddrinfo.c index 03dc126956162c..f2b4e03cd74cdb 100644 --- a/deps/uv/test/test-getaddrinfo.c +++ b/deps/uv/test/test-getaddrinfo.c @@ -106,6 +106,10 @@ TEST_IMPL(getaddrinfo_fail) { TEST_IMPL(getaddrinfo_fail_sync) { +/* TODO(gengjiawen): Fix test on QEMU. */ +#if defined(__QEMU__) + RETURN_SKIP("Test does not currently work in QEMU"); +#endif uv_getaddrinfo_t req; /* Use a FQDN by ending in a period */ @@ -144,6 +148,10 @@ TEST_IMPL(getaddrinfo_basic) { TEST_IMPL(getaddrinfo_basic_sync) { +/* TODO(gengjiawen): Fix test on QEMU. */ +#if defined(__QEMU__) + RETURN_SKIP("Test does not currently work in QEMU"); +#endif uv_getaddrinfo_t req; ASSERT(0 == uv_getaddrinfo(uv_default_loop(), diff --git a/deps/uv/test/test-getnameinfo.c b/deps/uv/test/test-getnameinfo.c index b1391616d13e54..3767ffd9aea5de 100644 --- a/deps/uv/test/test-getnameinfo.c +++ b/deps/uv/test/test-getnameinfo.c @@ -66,6 +66,11 @@ TEST_IMPL(getnameinfo_basic_ip4) { TEST_IMPL(getnameinfo_basic_ip4_sync) { +/* TODO(gengjiawen): Fix test on QEMU. */ +#if defined(__QEMU__) + RETURN_SKIP("Test does not currently work in QEMU"); +#endif + ASSERT(0 == uv_ip4_addr(address_ip4, port, &addr4)); ASSERT(0 == uv_getnameinfo(uv_default_loop(), diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index eb6665716f0718..24a8a657489a4e 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -346,6 +346,7 @@ TEST_DECLARE (fs_symlink_dir) #ifdef _WIN32 TEST_DECLARE (fs_symlink_junction) TEST_DECLARE (fs_non_symlink_reparse_point) +TEST_DECLARE (fs_lstat_windows_store_apps) TEST_DECLARE (fs_open_flags) #endif #if defined(_WIN32) && !defined(USING_UV_SHARED) @@ -409,6 +410,7 @@ TEST_DECLARE (fs_open_readonly_acl) TEST_DECLARE (fs_fchmod_archive_readonly) TEST_DECLARE (fs_invalid_mkdir_name) #endif +TEST_DECLARE (fs_get_system_error) TEST_DECLARE (strscpy) TEST_DECLARE (threadpool_queue_work_simple) TEST_DECLARE (threadpool_queue_work_einval) @@ -978,6 +980,7 @@ TASK_LIST_START #ifdef _WIN32 TEST_ENTRY (fs_symlink_junction) TEST_ENTRY (fs_non_symlink_reparse_point) + TEST_ENTRY (fs_lstat_windows_store_apps) TEST_ENTRY (fs_open_flags) #endif #if defined(_WIN32) && !defined(USING_UV_SHARED) @@ -1036,6 +1039,7 @@ TASK_LIST_START TEST_ENTRY (fs_fchmod_archive_readonly) TEST_ENTRY (fs_invalid_mkdir_name) #endif + TEST_ENTRY (fs_get_system_error) TEST_ENTRY (get_osfhandle_valid_handle) TEST_ENTRY (open_osfhandle_valid_handle) TEST_ENTRY (strscpy) diff --git a/deps/uv/test/test-platform-output.c b/deps/uv/test/test-platform-output.c index 65cfa1b3dcd4c4..f547ddfd7696ff 100644 --- a/deps/uv/test/test-platform-output.c +++ b/deps/uv/test/test-platform-output.c @@ -25,6 +25,11 @@ TEST_IMPL(platform_output) { +/* TODO(gengjiawen): Fix test on QEMU. */ +#if defined(__QEMU__) + RETURN_SKIP("Test does not currently work in QEMU"); +#endif + char buffer[512]; size_t rss; size_t size; diff --git a/deps/uv/test/test-poll.c b/deps/uv/test/test-poll.c index b3308446f1d81f..edd75d38266768 100644 --- a/deps/uv/test/test-poll.c +++ b/deps/uv/test/test-poll.c @@ -592,10 +592,19 @@ static void start_poll_test(void) { MAKE_VALGRIND_HAPPY(); } - + +/* Issuing a shutdown() on IBM i PASE with parameter SHUT_WR + * also sends a normal close sequence to the partner program. + * This leads to timing issues and ECONNRESET failures in the + * test 'poll_duplex' and 'poll_unidirectional'. + * + * https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_74/apis/shutdn.htm + */ TEST_IMPL(poll_duplex) { #if defined(NO_SELF_CONNECT) RETURN_SKIP(NO_SELF_CONNECT); +#elif defined(__PASE__) + RETURN_SKIP("API shutdown() may lead to timing issue on IBM i PASE"); #endif test_mode = DUPLEX; start_poll_test(); @@ -606,6 +615,8 @@ TEST_IMPL(poll_duplex) { TEST_IMPL(poll_unidirectional) { #if defined(NO_SELF_CONNECT) RETURN_SKIP(NO_SELF_CONNECT); +#elif defined(__PASE__) + RETURN_SKIP("API shutdown() may lead to timing issue on IBM i PASE"); #endif test_mode = UNIDIRECTIONAL; start_poll_test(); diff --git a/deps/uv/test/test-spawn.c b/deps/uv/test/test-spawn.c index 314a3562b02034..5e1c6d613003c0 100644 --- a/deps/uv/test/test-spawn.c +++ b/deps/uv/test/test-spawn.c @@ -1452,7 +1452,7 @@ TEST_IMPL(spawn_setuid_fails) { options.flags |= UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS; r = uv_spawn(uv_default_loop(), &process, &options); -#if defined(__CYGWIN__) || defined(__PASE__) +#if defined(__CYGWIN__) ASSERT(r == UV_EINVAL); #else ASSERT(r == UV_EPERM); @@ -1497,7 +1497,7 @@ TEST_IMPL(spawn_setgid_fails) { #endif r = uv_spawn(uv_default_loop(), &process, &options); -#if defined(__CYGWIN__) || defined(__MVS__) || defined(__PASE__) +#if defined(__CYGWIN__) || defined(__MVS__) ASSERT(r == UV_EINVAL); #else ASSERT(r == UV_EPERM); @@ -1689,7 +1689,7 @@ TEST_IMPL(spawn_reads_child_path) { */ #if defined(__APPLE__) static const char dyld_path_var[] = "DYLD_LIBRARY_PATH"; -#elif defined __MVS__ +#elif defined(__MVS__) || defined(__PASE__) static const char dyld_path_var[] = "LIBPATH"; #else static const char dyld_path_var[] = "LD_LIBRARY_PATH"; diff --git a/deps/uv/test/test-tcp-write-after-connect.c b/deps/uv/test/test-tcp-write-after-connect.c index 8198e7e184d5e4..8a698f44bd5db5 100644 --- a/deps/uv/test/test-tcp-write-after-connect.c +++ b/deps/uv/test/test-tcp-write-after-connect.c @@ -43,6 +43,11 @@ static void connect_cb(uv_connect_t *req, int status) { TEST_IMPL(tcp_write_after_connect) { +/* TODO(gengjiawen): Fix test on QEMU. */ +#if defined(__QEMU__) + RETURN_SKIP("Test does not currently work in QEMU"); +#endif + struct sockaddr_in sa; ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &sa)); ASSERT(0 == uv_loop_init(&loop)); diff --git a/deps/uv/test/test-thread.c b/deps/uv/test/test-thread.c index ffb392ceebc764..f53bce0601cea9 100644 --- a/deps/uv/test/test-thread.c +++ b/deps/uv/test/test-thread.c @@ -78,6 +78,10 @@ static void getaddrinfo_do(struct getaddrinfo_req* req) { static void getaddrinfo_cb(uv_getaddrinfo_t* handle, int status, struct addrinfo* res) { +/* TODO(gengjiawen): Fix test on QEMU. */ +#if defined(__QEMU__) + RETURN_SKIP("Test does not currently work in QEMU"); +#endif struct getaddrinfo_req* req; ASSERT(status == 0); diff --git a/deps/uv/test/test-udp-multicast-interface.c b/deps/uv/test/test-udp-multicast-interface.c index 0b3c0e62da559f..9d36098d0d0ac2 100644 --- a/deps/uv/test/test-udp-multicast-interface.c +++ b/deps/uv/test/test-udp-multicast-interface.c @@ -54,6 +54,11 @@ static void sv_send_cb(uv_udp_send_t* req, int status) { TEST_IMPL(udp_multicast_interface) { +/* TODO(gengjiawen): Fix test on QEMU. */ +#if defined(__QEMU__) + RETURN_SKIP("Test does not currently work in QEMU"); +#endif + int r; uv_udp_send_t req; uv_buf_t buf; diff --git a/deps/uv/test/test-udp-multicast-interface6.c b/deps/uv/test/test-udp-multicast-interface6.c index 40b05536dc7430..23a68a00f85625 100644 --- a/deps/uv/test/test-udp-multicast-interface6.c +++ b/deps/uv/test/test-udp-multicast-interface6.c @@ -54,6 +54,11 @@ static void sv_send_cb(uv_udp_send_t* req, int status) { TEST_IMPL(udp_multicast_interface6) { +/* TODO(gengjiawen): Fix test on QEMU. */ +#if defined(__QEMU__) + RETURN_SKIP("Test does not currently work in QEMU"); +#endif + int r; uv_udp_send_t req; uv_buf_t buf; diff --git a/deps/uv/test/test-udp-multicast-join6.c b/deps/uv/test/test-udp-multicast-join6.c index 5de27a7fb292db..40aa577d0a1b12 100644 --- a/deps/uv/test/test-udp-multicast-join6.c +++ b/deps/uv/test/test-udp-multicast-join6.c @@ -193,6 +193,10 @@ TEST_IMPL(udp_multicast_join6) { ASSERT(r == 0); +/* TODO(gengjiawen): Fix test on QEMU. */ +#if defined(__QEMU__) + RETURN_SKIP("Test does not currently work in QEMU"); +#endif r = uv_udp_recv_start(&server, alloc_cb, cl_recv_cb); ASSERT(r == 0); diff --git a/deps/uv/test/test-udp-options.c b/deps/uv/test/test-udp-options.c index d8c9d68d81b428..3ea51baf40b736 100644 --- a/deps/uv/test/test-udp-options.c +++ b/deps/uv/test/test-udp-options.c @@ -128,12 +128,16 @@ TEST_IMPL(udp_no_autobind) { ASSERT(UV_EBADF == uv_udp_set_ttl(&h, 1)); #endif ASSERT(UV_EBADF == uv_udp_set_multicast_loop(&h, 1)); +/* TODO(gengjiawen): Fix test on QEMU. */ +#if defined(__QEMU__) + RETURN_SKIP("Test does not currently work in QEMU"); +#endif ASSERT(UV_EBADF == uv_udp_set_multicast_interface(&h, "0.0.0.0")); uv_close((uv_handle_t*) &h, NULL); /* Test a non-lazily initialized socket. */ - ASSERT(0 == uv_udp_init_ex(loop, &h2, AF_INET)); + ASSERT(0 == uv_udp_init_ex(loop, &h2, AF_INET | UV_UDP_RECVMMSG)); ASSERT(0 == uv_udp_set_multicast_ttl(&h2, 32)); ASSERT(0 == uv_udp_set_broadcast(&h2, 1)); diff --git a/deps/uv/uv_win_longpath.manifest b/deps/uv/uv_win_longpath.manifest new file mode 100644 index 00000000000000..8976e6dfca7657 --- /dev/null +++ b/deps/uv/uv_win_longpath.manifest @@ -0,0 +1,8 @@ + + + + + true + + + diff --git a/deps/uvwasi/include/uvwasi.h b/deps/uvwasi/include/uvwasi.h index f2d2d1a9fd8945..0090313c8af2eb 100644 --- a/deps/uvwasi/include/uvwasi.h +++ b/deps/uvwasi/include/uvwasi.h @@ -5,13 +5,12 @@ extern "C" { #endif -#include "uv.h" +#include "wasi_serdes.h" #include "wasi_types.h" -#include "fd_table.h" #define UVWASI_VERSION_MAJOR 0 #define UVWASI_VERSION_MINOR 0 -#define UVWASI_VERSION_PATCH 8 +#define UVWASI_VERSION_PATCH 9 #define UVWASI_VERSION_HEX ((UVWASI_VERSION_MAJOR << 16) | \ (UVWASI_VERSION_MINOR << 8) | \ (UVWASI_VERSION_PATCH)) @@ -35,16 +34,18 @@ typedef struct uvwasi_mem_s { uvwasi_realloc realloc; } uvwasi_mem_t; +struct uvwasi_fd_table_t; + typedef struct uvwasi_s { - struct uvwasi_fd_table_t fds; - size_t argc; + struct uvwasi_fd_table_t* fds; + uvwasi_size_t argc; char** argv; char* argv_buf; - size_t argv_buf_size; - size_t envc; + uvwasi_size_t argv_buf_size; + uvwasi_size_t envc; char** env; char* env_buf; - size_t env_buf_size; + uvwasi_size_t env_buf_size; const uvwasi_mem_t* allocator; } uvwasi_t; @@ -54,12 +55,12 @@ typedef struct uvwasi_preopen_s { } uvwasi_preopen_t; typedef struct uvwasi_options_s { - size_t fd_table_size; - size_t preopenc; + uvwasi_size_t fd_table_size; + uvwasi_size_t preopenc; uvwasi_preopen_t* preopens; - size_t argc; - char** argv; - char** envp; + uvwasi_size_t argc; + const char** argv; + const char** envp; uvwasi_fd_t in; uvwasi_fd_t out; uvwasi_fd_t err; @@ -69,17 +70,18 @@ typedef struct uvwasi_options_s { /* Embedder API. */ uvwasi_errno_t uvwasi_init(uvwasi_t* uvwasi, uvwasi_options_t* options); void uvwasi_destroy(uvwasi_t* uvwasi); +/* Use int instead of uv_file to avoid needing uv.h */ uvwasi_errno_t uvwasi_embedder_remap_fd(uvwasi_t* uvwasi, const uvwasi_fd_t fd, - uv_file new_host_fd); + int new_host_fd); const char* uvwasi_embedder_err_code_to_string(uvwasi_errno_t code); /* WASI system call API. */ uvwasi_errno_t uvwasi_args_get(uvwasi_t* uvwasi, char** argv, char* argv_buf); uvwasi_errno_t uvwasi_args_sizes_get(uvwasi_t* uvwasi, - size_t* argc, - size_t* argv_buf_size); + uvwasi_size_t* argc, + uvwasi_size_t* argv_buf_size); uvwasi_errno_t uvwasi_clock_res_get(uvwasi_t* uvwasi, uvwasi_clockid_t clock_id, uvwasi_timestamp_t* resolution); @@ -91,8 +93,8 @@ uvwasi_errno_t uvwasi_environ_get(uvwasi_t* uvwasi, char** environment, char* environ_buf); uvwasi_errno_t uvwasi_environ_sizes_get(uvwasi_t* uvwasi, - size_t* environ_count, - size_t* environ_buf_size); + uvwasi_size_t* environ_count, + uvwasi_size_t* environ_buf_size); uvwasi_errno_t uvwasi_fd_advise(uvwasi_t* uvwasi, uvwasi_fd_t fd, uvwasi_filesize_t offset, @@ -129,33 +131,33 @@ uvwasi_errno_t uvwasi_fd_filestat_set_times(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_fd_pread(uvwasi_t* uvwasi, uvwasi_fd_t fd, const uvwasi_iovec_t* iovs, - size_t iovs_len, + uvwasi_size_t iovs_len, uvwasi_filesize_t offset, - size_t* nread); + uvwasi_size_t* nread); uvwasi_errno_t uvwasi_fd_prestat_get(uvwasi_t* uvwasi, uvwasi_fd_t fd, uvwasi_prestat_t* buf); uvwasi_errno_t uvwasi_fd_prestat_dir_name(uvwasi_t* uvwasi, uvwasi_fd_t fd, char* path, - size_t path_len); + uvwasi_size_t path_len); uvwasi_errno_t uvwasi_fd_pwrite(uvwasi_t* uvwasi, uvwasi_fd_t fd, const uvwasi_ciovec_t* iovs, - size_t iovs_len, + uvwasi_size_t iovs_len, uvwasi_filesize_t offset, - size_t* nwritten); + uvwasi_size_t* nwritten); uvwasi_errno_t uvwasi_fd_read(uvwasi_t* uvwasi, uvwasi_fd_t fd, const uvwasi_iovec_t* iovs, - size_t iovs_len, - size_t* nread); + uvwasi_size_t iovs_len, + uvwasi_size_t* nread); uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi, uvwasi_fd_t fd, void* buf, - size_t buf_len, + uvwasi_size_t buf_len, uvwasi_dircookie_t cookie, - size_t* bufused); + uvwasi_size_t* bufused); uvwasi_errno_t uvwasi_fd_renumber(uvwasi_t* uvwasi, uvwasi_fd_t from, uvwasi_fd_t to); @@ -171,23 +173,23 @@ uvwasi_errno_t uvwasi_fd_tell(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_fd_write(uvwasi_t* uvwasi, uvwasi_fd_t fd, const uvwasi_ciovec_t* iovs, - size_t iovs_len, - size_t* nwritten); + uvwasi_size_t iovs_len, + uvwasi_size_t* nwritten); uvwasi_errno_t uvwasi_path_create_directory(uvwasi_t* uvwasi, uvwasi_fd_t fd, const char* path, - size_t path_len); + uvwasi_size_t path_len); uvwasi_errno_t uvwasi_path_filestat_get(uvwasi_t* uvwasi, uvwasi_fd_t fd, uvwasi_lookupflags_t flags, const char* path, - size_t path_len, + uvwasi_size_t path_len, uvwasi_filestat_t* buf); uvwasi_errno_t uvwasi_path_filestat_set_times(uvwasi_t* uvwasi, uvwasi_fd_t fd, uvwasi_lookupflags_t flags, const char* path, - size_t path_len, + uvwasi_size_t path_len, uvwasi_timestamp_t st_atim, uvwasi_timestamp_t st_mtim, uvwasi_fstflags_t fst_flags); @@ -195,15 +197,15 @@ uvwasi_errno_t uvwasi_path_link(uvwasi_t* uvwasi, uvwasi_fd_t old_fd, uvwasi_lookupflags_t old_flags, const char* old_path, - size_t old_path_len, + uvwasi_size_t old_path_len, uvwasi_fd_t new_fd, const char* new_path, - size_t new_path_len); + uvwasi_size_t new_path_len); uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi, uvwasi_fd_t dirfd, uvwasi_lookupflags_t dirflags, const char* path, - size_t path_len, + uvwasi_size_t path_len, uvwasi_oflags_t o_flags, uvwasi_rights_t fs_rights_base, uvwasi_rights_t fs_rights_inheriting, @@ -212,53 +214,55 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_path_readlink(uvwasi_t* uvwasi, uvwasi_fd_t fd, const char* path, - size_t path_len, + uvwasi_size_t path_len, char* buf, - size_t buf_len, - size_t* bufused); + uvwasi_size_t buf_len, + uvwasi_size_t* bufused); uvwasi_errno_t uvwasi_path_remove_directory(uvwasi_t* uvwasi, uvwasi_fd_t fd, const char* path, - size_t path_len); + uvwasi_size_t path_len); uvwasi_errno_t uvwasi_path_rename(uvwasi_t* uvwasi, uvwasi_fd_t old_fd, const char* old_path, - size_t old_path_len, + uvwasi_size_t old_path_len, uvwasi_fd_t new_fd, const char* new_path, - size_t new_path_len); + uvwasi_size_t new_path_len); uvwasi_errno_t uvwasi_path_symlink(uvwasi_t* uvwasi, const char* old_path, - size_t old_path_len, + uvwasi_size_t old_path_len, uvwasi_fd_t fd, const char* new_path, - size_t new_path_len); + uvwasi_size_t new_path_len); uvwasi_errno_t uvwasi_path_unlink_file(uvwasi_t* uvwasi, uvwasi_fd_t fd, const char* path, - size_t path_len); + uvwasi_size_t path_len); uvwasi_errno_t uvwasi_poll_oneoff(uvwasi_t* uvwasi, const uvwasi_subscription_t* in, uvwasi_event_t* out, - size_t nsubscriptions, - size_t* nevents); + uvwasi_size_t nsubscriptions, + uvwasi_size_t* nevents); uvwasi_errno_t uvwasi_proc_exit(uvwasi_t* uvwasi, uvwasi_exitcode_t rval); uvwasi_errno_t uvwasi_proc_raise(uvwasi_t* uvwasi, uvwasi_signal_t sig); -uvwasi_errno_t uvwasi_random_get(uvwasi_t* uvwasi, void* buf, size_t buf_len); +uvwasi_errno_t uvwasi_random_get(uvwasi_t* uvwasi, + void* buf, + uvwasi_size_t buf_len); uvwasi_errno_t uvwasi_sched_yield(uvwasi_t* uvwasi); uvwasi_errno_t uvwasi_sock_recv(uvwasi_t* uvwasi, uvwasi_fd_t sock, const uvwasi_iovec_t* ri_data, - size_t ri_data_len, + uvwasi_size_t ri_data_len, uvwasi_riflags_t ri_flags, - size_t* ro_datalen, + uvwasi_size_t* ro_datalen, uvwasi_roflags_t* ro_flags); uvwasi_errno_t uvwasi_sock_send(uvwasi_t* uvwasi, uvwasi_fd_t sock, const uvwasi_ciovec_t* si_data, - size_t si_data_len, + uvwasi_size_t si_data_len, uvwasi_siflags_t si_flags, - size_t* so_datalen); + uvwasi_size_t* so_datalen); uvwasi_errno_t uvwasi_sock_shutdown(uvwasi_t* uvwasi, uvwasi_fd_t sock, uvwasi_sdflags_t how); diff --git a/deps/uvwasi/include/wasi_serdes.h b/deps/uvwasi/include/wasi_serdes.h new file mode 100644 index 00000000000000..f927b82bac9cbc --- /dev/null +++ b/deps/uvwasi/include/wasi_serdes.h @@ -0,0 +1,145 @@ +#ifndef __UVWASI_SERDES_H__ +#define __UVWASI_SERDES_H__ + +#include "wasi_types.h" + +/* Basic uint{8,16,32,64}_t read/write functions. */ + +#define BASIC_TYPE_(name, type) \ + void uvwasi_serdes_write_##name(void* ptr, size_t offset, type value); \ + type uvwasi_serdes_read_##name(const void* ptr, size_t offset); \ + +#define BASIC_TYPE(type) BASIC_TYPE_(type, type) +#define BASIC_TYPE_UVWASI(type) BASIC_TYPE_(type, uvwasi_##type) + +#define UVWASI_SERDES_SIZE_uint8_t sizeof(uint8_t) +BASIC_TYPE(uint8_t) +#define UVWASI_SERDES_SIZE_uint16_t sizeof(uint16_t) +BASIC_TYPE(uint16_t) +#define UVWASI_SERDES_SIZE_uint32_t sizeof(uint32_t) +BASIC_TYPE(uint32_t) +#define UVWASI_SERDES_SIZE_uint64_t sizeof(uint64_t) +BASIC_TYPE(uint64_t) + +#define UVWASI_SERDES_SIZE_advice_t sizeof(uvwasi_advice_t) +BASIC_TYPE_UVWASI(advice_t) +#define UVWASI_SERDES_SIZE_clockid_t sizeof(uvwasi_clockid_t) +BASIC_TYPE_UVWASI(clockid_t) +#define UVWASI_SERDES_SIZE_device_t sizeof(uvwasi_device_t) +BASIC_TYPE_UVWASI(device_t) +#define UVWASI_SERDES_SIZE_dircookie_t sizeof(uvwasi_dircookie_t) +BASIC_TYPE_UVWASI(dircookie_t) +#define UVWASI_SERDES_SIZE_eventrwflags_t sizeof(uvwasi_eventrwflags_t) +BASIC_TYPE_UVWASI(eventrwflags_t) +#define UVWASI_SERDES_SIZE_eventtype_t sizeof(uvwasi_eventtype_t) +BASIC_TYPE_UVWASI(eventtype_t) +#define UVWASI_SERDES_SIZE_exitcode_t sizeof(uvwasi_exitcode_t) +BASIC_TYPE_UVWASI(exitcode_t) +#define UVWASI_SERDES_SIZE_fd_t sizeof(uvwasi_fd_t) +BASIC_TYPE_UVWASI(fd_t) +#define UVWASI_SERDES_SIZE_fdflags_t sizeof(uvwasi_fdflags_t) +BASIC_TYPE_UVWASI(fdflags_t) +#define UVWASI_SERDES_SIZE_filesize_t sizeof(uvwasi_filesize_t) +BASIC_TYPE_UVWASI(filesize_t) +#define UVWASI_SERDES_SIZE_fstflags_t sizeof(uvwasi_fstflags_t) +BASIC_TYPE_UVWASI(fstflags_t) +#define UVWASI_SERDES_SIZE_inode_t sizeof(uvwasi_inode_t) +BASIC_TYPE_UVWASI(inode_t) +#define UVWASI_SERDES_SIZE_linkcount_t sizeof(uvwasi_linkcount_t) +BASIC_TYPE_UVWASI(linkcount_t) +#define UVWASI_SERDES_SIZE_lookupflags_t sizeof(uvwasi_lookupflags_t) +BASIC_TYPE_UVWASI(lookupflags_t) +#define UVWASI_SERDES_SIZE_oflags_t sizeof(uvwasi_oflags_t) +BASIC_TYPE_UVWASI(oflags_t) +#define UVWASI_SERDES_SIZE_preopentype_t sizeof(uvwasi_preopentype_t) +BASIC_TYPE_UVWASI(preopentype_t) +#define UVWASI_SERDES_SIZE_riflags_t sizeof(uvwasi_riflags_t) +BASIC_TYPE_UVWASI(riflags_t) +#define UVWASI_SERDES_SIZE_rights_t sizeof(uvwasi_rights_t) +BASIC_TYPE_UVWASI(rights_t) +#define UVWASI_SERDES_SIZE_roflags_t sizeof(uvwasi_roflags_t) +BASIC_TYPE_UVWASI(roflags_t) +#define UVWASI_SERDES_SIZE_sdflags_t sizeof(uvwasi_sdflags_t) +BASIC_TYPE_UVWASI(sdflags_t) +#define UVWASI_SERDES_SIZE_siflags_t sizeof(uvwasi_siflags_t) +BASIC_TYPE_UVWASI(siflags_t) +#define UVWASI_SERDES_SIZE_size_t sizeof(uvwasi_size_t) +BASIC_TYPE_UVWASI(size_t) +#define UVWASI_SERDES_SIZE_inode_t sizeof(uvwasi_inode_t) +BASIC_TYPE_UVWASI(inode_t) +#define UVWASI_SERDES_SIZE_signal_t sizeof(uvwasi_signal_t) +BASIC_TYPE_UVWASI(signal_t) +#define UVWASI_SERDES_SIZE_subclockflags_t sizeof(uvwasi_subclockflags_t) +BASIC_TYPE_UVWASI(subclockflags_t) +#define UVWASI_SERDES_SIZE_timestamp_t sizeof(uvwasi_timestamp_t) +BASIC_TYPE_UVWASI(timestamp_t) +#define UVWASI_SERDES_SIZE_userdata_t sizeof(uvwasi_userdata_t) +BASIC_TYPE_UVWASI(userdata_t) +#define UVWASI_SERDES_SIZE_whence_t sizeof(uvwasi_whence_t) +BASIC_TYPE_UVWASI(whence_t) + +#undef BASIC_TYPE_UVWASI +#undef BASIC_TYPE +#undef BASIC_TYPE_ + +/* WASI structure read/write functions. */ + +#define STRUCT(name) \ + void uvwasi_serdes_write_##name(void* ptr, \ + size_t offset, \ + const uvwasi_##name* value); \ + void uvwasi_serdes_read_##name(const void* ptr, \ + size_t offset, \ + uvwasi_##name* value); + +/* iovs currently only need to be read from WASM memory. */ +#define IOVS_STRUCT(name) \ + uvwasi_errno_t uvwasi_serdes_read_##name(const void* ptr, \ + size_t end, \ + size_t offset, \ + uvwasi_##name* value); + +#define UVWASI_SERDES_SIZE_ciovec_t 8 +IOVS_STRUCT(ciovec_t) + +#define UVWASI_SERDES_SIZE_iovec_t 8 +IOVS_STRUCT(iovec_t) + +#define UVWASI_SERDES_SIZE_fdstat_t 24 +STRUCT(fdstat_t) + +#define UVWASI_SERDES_SIZE_filestat_t 64 +STRUCT(filestat_t) + +#define UVWASI_SERDES_SIZE_prestat_t 8 +STRUCT(prestat_t) + +#define UVWASI_SERDES_SIZE_event_t 32 +STRUCT(event_t) + +#define UVWASI_SERDES_SIZE_subscription_t 48 +STRUCT(subscription_t) + +#undef STRUCT +#undef IOVS_STRUCT + +uvwasi_errno_t uvwasi_serdes_readv_ciovec_t(const void* ptr, + size_t end, + size_t offset, + uvwasi_ciovec_t* iovs, + uvwasi_size_t iovs_len); + +uvwasi_errno_t uvwasi_serdes_readv_iovec_t(const void* ptr, + size_t end, + size_t offset, + uvwasi_iovec_t* iovs, + uvwasi_size_t iovs_len); + +/* Helper functions for memory bounds checking. */ +int uvwasi_serdes_check_bounds(size_t offset, size_t end, size_t size); +int uvwasi_serdes_check_array_bounds(size_t offset, + size_t end, + size_t size, + size_t count); + +#endif /* __UVWASI_SERDES_H__ */ diff --git a/deps/uvwasi/include/wasi_types.h b/deps/uvwasi/include/wasi_types.h index 2f93b412624c06..57c2dd2f3ce589 100644 --- a/deps/uvwasi/include/wasi_types.h +++ b/deps/uvwasi/include/wasi_types.h @@ -6,6 +6,8 @@ /* API: https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/docs.md */ +typedef uint32_t uvwasi_size_t; + typedef uint8_t uvwasi_advice_t; #define UVWASI_ADVICE_NORMAL 0 #define UVWASI_ADVICE_SEQUENTIAL 1 @@ -16,7 +18,7 @@ typedef uint8_t uvwasi_advice_t; typedef struct uvwasi_ciovec_s { const void* buf; - size_t buf_len; + uvwasi_size_t buf_len; } uvwasi_ciovec_t; typedef uint32_t uvwasi_clockid_t; @@ -152,7 +154,7 @@ typedef uint64_t uvwasi_inode_t; typedef struct uvwasi_iovec_s { void* buf; - size_t buf_len; + uvwasi_size_t buf_len; } uvwasi_iovec_t; typedef uint64_t uvwasi_linkcount_t; @@ -173,7 +175,7 @@ typedef struct uvwasi_prestat_s { uvwasi_preopentype_t pr_type; union uvwasi_prestat_u { struct uvwasi_prestat_dir_t { - size_t pr_name_len; + uvwasi_size_t pr_name_len; } dir; } u; } uvwasi_prestat_t; diff --git a/deps/uvwasi/src/debug.h b/deps/uvwasi/src/debug.h new file mode 100644 index 00000000000000..16bc2732ec90cd --- /dev/null +++ b/deps/uvwasi/src/debug.h @@ -0,0 +1,13 @@ +#ifndef __UVWASI_DEBUG_H__ +#define __UVWASI_DEBUG_H__ + +#ifdef UVWASI_DEBUG_LOG +# define __STDC_FORMAT_MACROS +# include +# define DEBUG(fmt, ...) \ + do { fprintf(stderr, fmt, __VA_ARGS__); } while (0) +#else +# define DEBUG(fmt, ...) +#endif + +#endif /* __UVWASI_DEBUG_H__ */ diff --git a/deps/uvwasi/src/fd_table.c b/deps/uvwasi/src/fd_table.c index 3d134e3b7e5e2e..877faf4ca19cd0 100644 --- a/deps/uvwasi/src/fd_table.c +++ b/deps/uvwasi/src/fd_table.c @@ -181,26 +181,25 @@ uvwasi_errno_t uvwasi_fd_table_init(uvwasi_t* uvwasi, if (uvwasi == NULL || options == NULL || options->fd_table_size < 3) return UVWASI_EINVAL; - table = &uvwasi->fds; - table->fds = NULL; + table = uvwasi__malloc(uvwasi, sizeof(*table)); + if (table == NULL) + return UVWASI_ENOMEM; + table->used = 0; table->size = options->fd_table_size; table->fds = uvwasi__calloc(uvwasi, options->fd_table_size, sizeof(struct uvwasi_fd_wrap_t*)); - - if (table->fds == NULL) + if (table->fds == NULL) { + uvwasi__free(uvwasi, table); return UVWASI_ENOMEM; + } r = uv_rwlock_init(&table->rwlock); if (r != 0) { err = uvwasi__translate_uv_error(r); - /* Free table->fds and set it to NULL here. This is done explicitly instead - of jumping to error_exit because uvwasi_fd_table_free() relies on fds - being NULL to know whether or not to destroy the rwlock. - */ uvwasi__free(uvwasi, table->fds); - table->fds = NULL; + uvwasi__free(uvwasi, table); return err; } @@ -217,6 +216,7 @@ uvwasi_errno_t uvwasi_fd_table_init(uvwasi_t* uvwasi, if (err != UVWASI_ESUCCESS) goto error_exit; + uvwasi->fds = table; return UVWASI_ESUCCESS; error_exit: uvwasi_fd_table_free(uvwasi, table); @@ -228,12 +228,14 @@ void uvwasi_fd_table_free(uvwasi_t* uvwasi, struct uvwasi_fd_table_t* table) { struct uvwasi_fd_wrap_t* entry; uint32_t i; - if (table == NULL) + if (uvwasi == NULL || table == NULL) return; for (i = 0; i < table->size; i++) { entry = table->fds[i]; - if (entry == NULL) continue; + + if (entry == NULL) + continue; uv_mutex_destroy(&entry->mutex); uvwasi__free(uvwasi, entry); @@ -246,6 +248,8 @@ void uvwasi_fd_table_free(uvwasi_t* uvwasi, struct uvwasi_fd_table_t* table) { table->used = 0; uv_rwlock_destroy(&table->rwlock); } + + uvwasi__free(uvwasi, table); } diff --git a/deps/uvwasi/include/fd_table.h b/deps/uvwasi/src/fd_table.h similarity index 100% rename from deps/uvwasi/include/fd_table.h rename to deps/uvwasi/src/fd_table.h diff --git a/deps/uvwasi/src/path_resolver.c b/deps/uvwasi/src/path_resolver.c index ee0e60f7e8f4ea..af13c1553ca874 100644 --- a/deps/uvwasi/src/path_resolver.c +++ b/deps/uvwasi/src/path_resolver.c @@ -15,7 +15,7 @@ #endif /* _WIN32 */ -static int uvwasi__is_absolute_path(const char* path, size_t path_len) { +static int uvwasi__is_absolute_path(const char* path, uvwasi_size_t path_len) { /* It's expected that only Unix style paths will be generated by WASI. */ return path != NULL && path_len > 0 && path[0] == '/'; } @@ -33,9 +33,9 @@ static char* uvwasi__strchr_slash(const char* s) { uvwasi_errno_t uvwasi__normalize_path(const char* path, - size_t path_len, + uvwasi_size_t path_len, char* normalized_path, - size_t normalized_len) { + uvwasi_size_t normalized_len) { const char* cur; char* ptr; char* next; @@ -125,9 +125,9 @@ uvwasi_errno_t uvwasi__normalize_path(const char* path, static int uvwasi__is_path_sandboxed(const char* path, - size_t path_len, + uvwasi_size_t path_len, const char* fd_path, - size_t fd_path_len) { + uvwasi_size_t fd_path_len) { char* ptr; int remaining_len; @@ -173,9 +173,9 @@ static uvwasi_errno_t uvwasi__normalize_absolute_path( const uvwasi_t* uvwasi, const struct uvwasi_fd_wrap_t* fd, const char* path, - size_t path_len, + uvwasi_size_t path_len, char** normalized_path, - size_t* normalized_len + uvwasi_size_t* normalized_len ) { /* This function resolves an absolute path to the provided file descriptor. If the file descriptor's path is relative, then this operation will fail @@ -224,9 +224,9 @@ static uvwasi_errno_t uvwasi__normalize_relative_path( const uvwasi_t* uvwasi, const struct uvwasi_fd_wrap_t* fd, const char* path, - size_t path_len, + uvwasi_size_t path_len, char** normalized_path, - size_t* normalized_len + uvwasi_size_t* normalized_len ) { /* This function resolves a relative path to the provided file descriptor. The relative path is concatenated to the file descriptor's path, and then @@ -298,9 +298,9 @@ static uvwasi_errno_t uvwasi__resolve_path_to_host( const uvwasi_t* uvwasi, const struct uvwasi_fd_wrap_t* fd, const char* path, - size_t path_len, + uvwasi_size_t path_len, char** resolved_path, - size_t* resolved_len + uvwasi_size_t* resolved_len ) { /* Return the normalized path, but resolved to the host's real path. */ char* res_path; @@ -309,7 +309,7 @@ static uvwasi_errno_t uvwasi__resolve_path_to_host( int fake_path_len; int stripped_len; #ifdef _WIN32 - size_t i; + uvwasi_size_t i; #endif /* _WIN32 */ real_path_len = strlen(fd->real_path); @@ -351,6 +351,7 @@ static uvwasi_errno_t uvwasi__resolve_path_to_host( #ifdef _WIN32 /* Replace / with \ on Windows. */ + res_path = *resolved_path; for (i = real_path_len; i < *resolved_len; i++) { if (res_path[i] == '/') res_path[i] = '\\'; @@ -364,8 +365,8 @@ static uvwasi_errno_t uvwasi__resolve_path_to_host( uvwasi_errno_t uvwasi__resolve_path(const uvwasi_t* uvwasi, const struct uvwasi_fd_wrap_t* fd, const char* path, - size_t path_len, - char* resolved_path, + uvwasi_size_t path_len, + char** resolved_path, uvwasi_lookupflags_t flags) { uv_fs_t req; uvwasi_errno_t err; @@ -373,9 +374,9 @@ uvwasi_errno_t uvwasi__resolve_path(const uvwasi_t* uvwasi, char* host_path; char* normalized_path; char* link_target; - size_t input_len; - size_t host_path_len; - size_t normalized_len; + uvwasi_size_t input_len; + uvwasi_size_t host_path_len; + uvwasi_size_t normalized_len; int follow_count; int r; @@ -418,14 +419,6 @@ uvwasi_errno_t uvwasi__resolve_path(const uvwasi_t* uvwasi, if (err != UVWASI_ESUCCESS) goto exit; - /* TODO(cjihrig): Currently performing a bounds check here. The TODO is to - stop allocating resolved_path in every caller and instead return the - path allocated in this function. */ - if (host_path_len > PATH_MAX_BYTES) { - err = UVWASI_ENOBUFS; - goto exit; - } - if ((flags & UVWASI_LOOKUP_SYMLINK_FOLLOW) == UVWASI_LOOKUP_SYMLINK_FOLLOW) { r = uv_fs_readlink(NULL, &req, host_path, NULL); @@ -482,11 +475,14 @@ uvwasi_errno_t uvwasi__resolve_path(const uvwasi_t* uvwasi, } exit: - if (err == UVWASI_ESUCCESS) - memcpy(resolved_path, host_path, host_path_len + 1); + if (err == UVWASI_ESUCCESS) { + *resolved_path = host_path; + } else { + *resolved_path = NULL; + uvwasi__free(uvwasi, host_path); + } uvwasi__free(uvwasi, link_target); uvwasi__free(uvwasi, normalized_path); - uvwasi__free(uvwasi, host_path); return err; } diff --git a/deps/uvwasi/src/path_resolver.h b/deps/uvwasi/src/path_resolver.h index d5f95eafbfbf83..5040c69ac40cb7 100644 --- a/deps/uvwasi/src/path_resolver.h +++ b/deps/uvwasi/src/path_resolver.h @@ -1,28 +1,19 @@ #ifndef __UVWASI_PATH_RESOLVER_H__ #define __UVWASI_PATH_RESOLVER_H__ +#include "fd_table.h" #include "uvwasi.h" -/* TODO(cjihrig): PATH_MAX_BYTES shouldn't be stack allocated. On Windows, paths - can be 32k long, and this PATH_MAX_BYTES is an artificial limitation. */ -#ifdef _WIN32 -/* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */ -# define PATH_MAX_BYTES (MAX_PATH * 4) -#else -# include -# define PATH_MAX_BYTES (PATH_MAX) -#endif - uvwasi_errno_t uvwasi__normalize_path(const char* path, - size_t path_len, + uvwasi_size_t path_len, char* normalized_path, - size_t normalized_len); + uvwasi_size_t normalized_len); uvwasi_errno_t uvwasi__resolve_path(const uvwasi_t* uvwasi, const struct uvwasi_fd_wrap_t* fd, const char* path, - size_t path_len, - char* resolved_path, + uvwasi_size_t path_len, + char** resolved_path, uvwasi_lookupflags_t flags); #endif /* __UVWASI_PATH_RESOLVER_H__ */ diff --git a/deps/uvwasi/src/poll_oneoff.c b/deps/uvwasi/src/poll_oneoff.c new file mode 100644 index 00000000000000..a4b1c3c84282fa --- /dev/null +++ b/deps/uvwasi/src/poll_oneoff.c @@ -0,0 +1,269 @@ +#include "uv.h" +#include "poll_oneoff.h" +#include "uv_mapping.h" +#include "uvwasi_alloc.h" + + +static void poll_cb(uv_poll_t* handle, int status, int events) { + struct uvwasi_poll_oneoff_state_t* state; + struct uvwasi__poll_fdevent_t* event; + + uv_poll_stop(handle); + event = uv_handle_get_data((uv_handle_t*) handle); + event->revents = events; + + if (status != 0) + event->error = UVWASI_EIO; + + state = uv_loop_get_data(handle->loop); + state->result++; +} + + +static void timeout_cb(uv_timer_t* handle) { + struct uvwasi_poll_oneoff_state_t* state; + uvwasi_size_t i; + + state = uv_loop_get_data(handle->loop); + + for (i = 0; i < state->handle_cnt; i++) + uv_poll_stop(&state->poll_handles[i]); +} + + +uvwasi_errno_t uvwasi__poll_oneoff_state_init( + uvwasi_t* uvwasi, + struct uvwasi_poll_oneoff_state_t* state, + uvwasi_size_t max_fds + ) { + uvwasi_errno_t err; + int r; + + if (uvwasi == NULL || state == NULL) + return UVWASI_EINVAL; + + state->uvwasi = NULL; + state->timeout = 0; + state->has_timer = 0; + state->fdevents = NULL; + state->poll_handles = NULL; + state->max_fds = 0; + state->fdevent_cnt = 0; + state->handle_cnt = 0; + state->result = 0; + + r = uv_loop_init(&state->loop); + if (r != 0) + return uvwasi__translate_uv_error(r); + + if (max_fds > 0) { + state->fdevents = uvwasi__calloc(uvwasi, + max_fds, + sizeof(*state->fdevents)); + if (state->fdevents == NULL) { + err = UVWASI_ENOMEM; + goto error_exit; + } + + state->poll_handles = uvwasi__calloc(uvwasi, + max_fds, + sizeof(*state->poll_handles)); + if (state->poll_handles == NULL) { + err = UVWASI_ENOMEM; + goto error_exit; + } + } + + uv_loop_set_data(&state->loop, (void*) state); + state->uvwasi = uvwasi; + state->max_fds = max_fds; + + return UVWASI_ESUCCESS; + +error_exit: + uv_loop_close(&state->loop); + uvwasi__free(state->uvwasi, state->fdevents); + uvwasi__free(state->uvwasi, state->poll_handles); + return err; +} + + +uvwasi_errno_t uvwasi__poll_oneoff_state_cleanup( + struct uvwasi_poll_oneoff_state_t* state + ) { + struct uvwasi__poll_fdevent_t* event; + uvwasi_size_t i; + int r; + + if (state == NULL) + return UVWASI_EINVAL; + + if (state->has_timer != 0) { + state->timeout = 0; + state->has_timer = 0; + uv_close((uv_handle_t*) &state->timer, NULL); + } + + for (i = 0; i < state->fdevent_cnt; i++) { + event = &state->fdevents[i]; + + if (event->is_duplicate_fd == 0 && event->wrap != NULL) + uv_mutex_unlock(&event->wrap->mutex); + } + + for (i = 0; i < state->handle_cnt; i++) + uv_close((uv_handle_t*) &state->poll_handles[i], NULL); + + uv_run(&state->loop, UV_RUN_NOWAIT); + + state->max_fds = 0; + state->fdevent_cnt = 0; + state->handle_cnt = 0; + + uvwasi__free(state->uvwasi, state->fdevents); + uvwasi__free(state->uvwasi, state->poll_handles); + state->fdevents = NULL; + state->poll_handles = NULL; + state->uvwasi = NULL; + + r = uv_loop_close(&state->loop); + if (r != 0) + return uvwasi__translate_uv_error(r); + + return UVWASI_ESUCCESS; +} + + +uvwasi_errno_t uvwasi__poll_oneoff_state_set_timer( + struct uvwasi_poll_oneoff_state_t* state, + uvwasi_timestamp_t timeout + ) { + int r; + + if (state == NULL) + return UVWASI_EINVAL; + + r = uv_timer_init(&state->loop, &state->timer); + if (r != 0) + return uvwasi__translate_uv_error(r); + + /* Convert WASI timeout from nanoseconds to milliseconds for libuv. */ + state->timeout = timeout / 1000000; + state->has_timer = 1; + return UVWASI_ESUCCESS; +} + + +uvwasi_errno_t uvwasi__poll_oneoff_state_add_fdevent( + struct uvwasi_poll_oneoff_state_t* state, + uvwasi_subscription_t* subscription + ) { + struct uvwasi__poll_fdevent_t* event; + struct uvwasi__poll_fdevent_t* dup; + uv_poll_t* poll_handle; + uvwasi_eventtype_t type; + uvwasi_rights_t rights; + uvwasi_fd_t fd; + uvwasi_errno_t err; + uvwasi_size_t i; + int r; + + if (state == NULL) + return UVWASI_EINVAL; + + event = &state->fdevents[state->fdevent_cnt]; + fd = subscription->u.fd_readwrite.fd; + type = subscription->type; + + if (type == UVWASI_EVENTTYPE_FD_READ) { + event->events = UV_DISCONNECT | UV_READABLE; + rights = UVWASI_RIGHT_POLL_FD_READWRITE | UVWASI_RIGHT_FD_READ; + } else if (type == UVWASI_EVENTTYPE_FD_WRITE) { + event->events = UV_DISCONNECT | UV_WRITABLE; + rights = UVWASI_RIGHT_POLL_FD_READWRITE | UVWASI_RIGHT_FD_WRITE; + } else { + return UVWASI_EINVAL; + } + + /* Check if the same file descriptor is already being polled. If so, use the + wrap and poll handle from the first descriptor. The reasons are that libuv + does not support polling the same fd more than once at the same time, and + uvwasi has the fd's mutex locked. */ + event->is_duplicate_fd = 0; + for (i = 0; i < state->fdevent_cnt; i++) { + dup = &state->fdevents[i]; + if (dup->wrap->id == fd) { + event->is_duplicate_fd = 1; + event->wrap = dup->wrap; + event->poll_handle = dup->poll_handle; + err = event->error; + goto poll_config_done; + } + } + + /* Get the file descriptor. If UVWASI_EBADF is returned, continue on, but + don't do any polling with the handle. */ + err = uvwasi_fd_table_get(state->uvwasi->fds, fd, &event->wrap, rights, 0); + if (err == UVWASI_EBADF) + event->wrap = NULL; + else if (err != UVWASI_ESUCCESS) + return err; + + if (err == UVWASI_ESUCCESS) { + /* The fd is valid, so setup the poll handle. */ + poll_handle = &state->poll_handles[state->handle_cnt]; + r = uv_poll_init(&state->loop, poll_handle, event->wrap->fd); + + if (r != 0) { + /* If uv_poll_init() fails (for example on Windows because only sockets + are supported), set the error for this event to UVWASI_EBADF, but don't + do any polling with the handle. */ + uv_mutex_unlock(&event->wrap->mutex); + return uvwasi__translate_uv_error(r); + } else { + r = uv_poll_start(poll_handle, + event->events, + poll_cb); + if (r != 0) { + uv_mutex_unlock(&event->wrap->mutex); + uv_close((uv_handle_t*) poll_handle, NULL); + return uvwasi__translate_uv_error(r); + } + + uv_handle_set_data((uv_handle_t*) poll_handle, + (void*) &state->fdevents[state->fdevent_cnt]); + event->poll_handle = poll_handle; + state->handle_cnt++; + } + } + +poll_config_done: + event->type = type; + event->userdata = subscription->userdata; + event->error = err; + event->revents = 0; + state->fdevent_cnt++; + return UVWASI_ESUCCESS; +} + + +uvwasi_errno_t uvwasi__poll_oneoff_run( + struct uvwasi_poll_oneoff_state_t* state + ) { + int r; + + if (state->has_timer == 1) { + r = uv_timer_start(&state->timer, timeout_cb, state->timeout, 0); + if (r != 0) + return uvwasi__translate_uv_error(r); + + if (state->fdevent_cnt > 0) + uv_unref((uv_handle_t*) &state->timer); + } + + r = uv_run(&state->loop, UV_RUN_DEFAULT); + if (r != 0) + return uvwasi__translate_uv_error(r); + + return UVWASI_ESUCCESS; +} diff --git a/deps/uvwasi/src/poll_oneoff.h b/deps/uvwasi/src/poll_oneoff.h new file mode 100644 index 00000000000000..64a315af1b334b --- /dev/null +++ b/deps/uvwasi/src/poll_oneoff.h @@ -0,0 +1,60 @@ +#ifndef __UVWASI_POLL_ONEOFF_H__ +#define __UVWASI_POLL_ONEOFF_H__ + +#include "fd_table.h" +#include "wasi_types.h" + +struct uvwasi_s; + +struct uvwasi__poll_fdevent_t { + struct uvwasi_fd_wrap_t* wrap; + uvwasi_userdata_t userdata; + uvwasi_eventtype_t type; + uvwasi_errno_t error; + uv_poll_t* poll_handle; + int is_duplicate_fd; + int events; + int revents; +}; + +struct uvwasi_poll_oneoff_state_t { + struct uvwasi_s* uvwasi; + struct uvwasi__poll_fdevent_t* fdevents; + uv_poll_t* poll_handles; + uv_timer_t timer; + uint64_t timeout; + uv_loop_t loop; + uvwasi_size_t max_fds; + int has_timer; + uvwasi_size_t fdevent_cnt; + uvwasi_size_t handle_cnt; + int result; +}; + + +uvwasi_errno_t uvwasi__poll_oneoff_state_init( + struct uvwasi_s* uvwasi, + struct uvwasi_poll_oneoff_state_t* state, + uvwasi_size_t max_fds + ); + +uvwasi_errno_t uvwasi__poll_oneoff_state_cleanup( + struct uvwasi_poll_oneoff_state_t* state + ); + +uvwasi_errno_t uvwasi__poll_oneoff_state_set_timer( + struct uvwasi_poll_oneoff_state_t* state, + uvwasi_timestamp_t timeout + ); + +uvwasi_errno_t uvwasi__poll_oneoff_state_add_fdevent( + struct uvwasi_poll_oneoff_state_t* state, + uvwasi_subscription_t* subscription + ); + +uvwasi_errno_t uvwasi__poll_oneoff_run( + struct uvwasi_poll_oneoff_state_t* state + ); + + +#endif /* __UVWASI_POLL_ONEOFF_H__ */ diff --git a/deps/uvwasi/src/uvwasi.c b/deps/uvwasi/src/uvwasi.c index 0ee66be36a3951..fc8f0ee4844b9e 100644 --- a/deps/uvwasi/src/uvwasi.c +++ b/deps/uvwasi/src/uvwasi.c @@ -20,7 +20,9 @@ #include "fd_table.h" #include "clocks.h" #include "path_resolver.h" +#include "poll_oneoff.h" #include "wasi_rights.h" +#include "debug.h" /* IBMi PASE does not support posix_fadvise() */ #ifdef __PASE__ @@ -109,9 +111,9 @@ static uvwasi_errno_t uvwasi__lseek(uv_file fd, static uvwasi_errno_t uvwasi__setup_iovs(const uvwasi_t* uvwasi, uv_buf_t** buffers, const uvwasi_iovec_t* iovs, - size_t iovs_len) { + uvwasi_size_t iovs_len) { uv_buf_t* bufs; - size_t i; + uvwasi_size_t i; if ((iovs_len * sizeof(*bufs)) / (sizeof(*bufs)) != iovs_len) return UVWASI_ENOMEM; @@ -131,9 +133,9 @@ static uvwasi_errno_t uvwasi__setup_iovs(const uvwasi_t* uvwasi, static uvwasi_errno_t uvwasi__setup_ciovs(const uvwasi_t* uvwasi, uv_buf_t** buffers, const uvwasi_ciovec_t* iovs, - size_t iovs_len) { + uvwasi_size_t iovs_len) { uv_buf_t* bufs; - size_t i; + uvwasi_size_t i; if ((iovs_len * sizeof(*bufs)) / (sizeof(*bufs)) != iovs_len) return UVWASI_ENOMEM; @@ -154,12 +156,12 @@ uvwasi_errno_t uvwasi_init(uvwasi_t* uvwasi, uvwasi_options_t* options) { uv_fs_t realpath_req; uv_fs_t open_req; uvwasi_errno_t err; - size_t args_size; - size_t size; - size_t offset; - size_t env_count; - size_t env_buf_size; - size_t i; + uvwasi_size_t args_size; + uvwasi_size_t size; + uvwasi_size_t offset; + uvwasi_size_t env_count; + uvwasi_size_t env_buf_size; + uvwasi_size_t i; int r; if (uvwasi == NULL || options == NULL || options->fd_table_size == 0) @@ -173,7 +175,7 @@ uvwasi_errno_t uvwasi_init(uvwasi_t* uvwasi, uvwasi_options_t* options) { uvwasi->argv = NULL; uvwasi->env_buf = NULL; uvwasi->env = NULL; - uvwasi->fds.fds = NULL; + uvwasi->fds = NULL; args_size = 0; for (i = 0; i < options->argc; ++i) @@ -270,7 +272,7 @@ uvwasi_errno_t uvwasi_init(uvwasi_t* uvwasi, uvwasi_options_t* options) { } err = uvwasi_fd_table_insert_preopen(uvwasi, - &uvwasi->fds, + uvwasi->fds, open_req.result, options->preopens[i].mapped_path, realpath_req.ptr); @@ -293,11 +295,12 @@ void uvwasi_destroy(uvwasi_t* uvwasi) { if (uvwasi == NULL) return; - uvwasi_fd_table_free(uvwasi, &uvwasi->fds); + uvwasi_fd_table_free(uvwasi, uvwasi->fds); uvwasi__free(uvwasi, uvwasi->argv_buf); uvwasi__free(uvwasi, uvwasi->argv); uvwasi__free(uvwasi, uvwasi->env_buf); uvwasi__free(uvwasi, uvwasi->env); + uvwasi->fds = NULL; uvwasi->argv_buf = NULL; uvwasi->argv = NULL; uvwasi->env_buf = NULL; @@ -314,7 +317,7 @@ uvwasi_errno_t uvwasi_embedder_remap_fd(uvwasi_t* uvwasi, if (uvwasi == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, fd, &wrap, 0, 0); + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, 0, 0); if (err != UVWASI_ESUCCESS) return err; @@ -325,7 +328,12 @@ uvwasi_errno_t uvwasi_embedder_remap_fd(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_args_get(uvwasi_t* uvwasi, char** argv, char* argv_buf) { - size_t i; + uvwasi_size_t i; + + DEBUG("uvwasi_args_get(uvwasi=%p, argv=%p, argv_buf=%p)\n", + uvwasi, + argv, + argv_buf); if (uvwasi == NULL || argv == NULL || argv_buf == NULL) return UVWASI_EINVAL; @@ -340,8 +348,13 @@ uvwasi_errno_t uvwasi_args_get(uvwasi_t* uvwasi, char** argv, char* argv_buf) { uvwasi_errno_t uvwasi_args_sizes_get(uvwasi_t* uvwasi, - size_t* argc, - size_t* argv_buf_size) { + uvwasi_size_t* argc, + uvwasi_size_t* argv_buf_size) { + DEBUG("uvwasi_args_sizes_get(uvwasi=%p, argc=%p, argv_buf_size=%p)\n", + uvwasi, + argc, + argv_buf_size); + if (uvwasi == NULL || argc == NULL || argv_buf_size == NULL) return UVWASI_EINVAL; @@ -354,6 +367,11 @@ uvwasi_errno_t uvwasi_args_sizes_get(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_clock_res_get(uvwasi_t* uvwasi, uvwasi_clockid_t clock_id, uvwasi_timestamp_t* resolution) { + DEBUG("uvwasi_clock_res_get(uvwasi=%p, clock_id=%d, resolution=%p)\n", + uvwasi, + clock_id, + resolution); + if (uvwasi == NULL || resolution == NULL) return UVWASI_EINVAL; @@ -376,6 +394,13 @@ uvwasi_errno_t uvwasi_clock_time_get(uvwasi_t* uvwasi, uvwasi_clockid_t clock_id, uvwasi_timestamp_t precision, uvwasi_timestamp_t* time) { + DEBUG("uvwasi_clock_time_get(uvwasi=%p, clock_id=%d, " + "precision=%"PRIu64", time=%p)\n", + uvwasi, + clock_id, + precision, + time); + if (uvwasi == NULL || time == NULL) return UVWASI_EINVAL; @@ -398,7 +423,12 @@ uvwasi_errno_t uvwasi_clock_time_get(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_environ_get(uvwasi_t* uvwasi, char** environment, char* environ_buf) { - size_t i; + uvwasi_size_t i; + + DEBUG("uvwasi_environ_get(uvwasi=%p, environment=%p, environ_buf=%p)\n", + uvwasi, + environment, + environ_buf); if (uvwasi == NULL || environment == NULL || environ_buf == NULL) return UVWASI_EINVAL; @@ -413,8 +443,14 @@ uvwasi_errno_t uvwasi_environ_get(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_environ_sizes_get(uvwasi_t* uvwasi, - size_t* environ_count, - size_t* environ_buf_size) { + uvwasi_size_t* environ_count, + uvwasi_size_t* environ_buf_size) { + DEBUG("uvwasi_environ_sizes_get(uvwasi=%p, environ_count=%p, " + "environ_buf_size=%p)\n", + uvwasi, + environ_count, + environ_buf_size); + if (uvwasi == NULL || environ_count == NULL || environ_buf_size == NULL) return UVWASI_EINVAL; @@ -436,6 +472,14 @@ uvwasi_errno_t uvwasi_fd_advise(uvwasi_t* uvwasi, int r; #endif /* POSIX_FADV_NORMAL */ + DEBUG("uvwasi_fd_advise(uvwasi=%p, fd=%d, offset=%"PRIu64", len=%"PRIu64", " + "advice=%d)\n", + uvwasi, + fd, + offset, + len, + advice); + if (uvwasi == NULL) return UVWASI_EINVAL; @@ -474,7 +518,7 @@ uvwasi_errno_t uvwasi_fd_advise(uvwasi_t* uvwasi, return UVWASI_EINVAL; } - err = uvwasi_fd_table_get(&uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_ADVISE, 0); + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_ADVISE, 0); if (err != UVWASI_ESUCCESS) return err; @@ -502,10 +546,17 @@ uvwasi_errno_t uvwasi_fd_allocate(uvwasi_t* uvwasi, uvwasi_errno_t err; int r; + DEBUG("uvwasi_fd_allocate(uvwasi=%p, fd=%d, offset=%"PRIu64", " + "len=%"PRIu64")\n", + uvwasi, + fd, + offset, + len); + if (uvwasi == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_ALLOCATE, @@ -552,12 +603,14 @@ uvwasi_errno_t uvwasi_fd_close(uvwasi_t* uvwasi, uvwasi_fd_t fd) { uv_fs_t req; int r; + DEBUG("uvwasi_fd_close(uvwasi=%p, fd=%d)\n", uvwasi, fd); + if (uvwasi == NULL) return UVWASI_EINVAL; - uvwasi_fd_table_lock(&uvwasi->fds); + uvwasi_fd_table_lock(uvwasi->fds); - err = uvwasi_fd_table_get_nolock(&uvwasi->fds, fd, &wrap, 0, 0); + err = uvwasi_fd_table_get_nolock(uvwasi->fds, fd, &wrap, 0, 0); if (err != UVWASI_ESUCCESS) goto exit; @@ -570,10 +623,10 @@ uvwasi_errno_t uvwasi_fd_close(uvwasi_t* uvwasi, uvwasi_fd_t fd) { goto exit; } - err = uvwasi_fd_table_remove_nolock(uvwasi, &uvwasi->fds, fd); + err = uvwasi_fd_table_remove_nolock(uvwasi, uvwasi->fds, fd); exit: - uvwasi_fd_table_unlock(&uvwasi->fds); + uvwasi_fd_table_unlock(uvwasi->fds); return err; } @@ -584,10 +637,12 @@ uvwasi_errno_t uvwasi_fd_datasync(uvwasi_t* uvwasi, uvwasi_fd_t fd) { uv_fs_t req; int r; + DEBUG("uvwasi_fd_datasync(uvwasi=%p, fd=%d)\n", uvwasi, fd); + if (uvwasi == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_DATASYNC, @@ -615,10 +670,12 @@ uvwasi_errno_t uvwasi_fd_fdstat_get(uvwasi_t* uvwasi, int r; #endif + DEBUG("uvwasi_fd_fdstat_get(uvwasi=%p, fd=%d, buf=%p)\n", uvwasi, fd, buf); + if (uvwasi == NULL || buf == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, fd, &wrap, 0, 0); + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, 0, 0); if (err != UVWASI_ESUCCESS) return err; @@ -646,7 +703,12 @@ uvwasi_errno_t uvwasi_fd_fdstat_set_flags(uvwasi_t* uvwasi, uvwasi_fd_t fd, uvwasi_fdflags_t flags) { #ifdef _WIN32 - /* TODO(cjihrig): Missing Windows support. */ + DEBUG("uvwasi_fd_fdstat_set_flags(uvwasi=%p, fd=%d, flags=%d)\n", + uvwasi, + fd, + flags); + + /* TODO(cjihrig): Windows is not supported. */ return UVWASI_ENOSYS; #else struct uvwasi_fd_wrap_t* wrap; @@ -654,10 +716,15 @@ uvwasi_errno_t uvwasi_fd_fdstat_set_flags(uvwasi_t* uvwasi, int mapped_flags; int r; + DEBUG("uvwasi_fd_fdstat_set_flags(uvwasi=%p, fd=%d, flags=%d)\n", + uvwasi, + fd, + flags); + if (uvwasi == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_FDSTAT_SET_FLAGS, @@ -710,10 +777,17 @@ uvwasi_errno_t uvwasi_fd_fdstat_set_rights(uvwasi_t* uvwasi, struct uvwasi_fd_wrap_t* wrap; uvwasi_errno_t err; + DEBUG("uvwasi_fd_fdstat_set_rights(uvwasi=%p, fd=%d, " + "fs_rights_base=%"PRIu64", fs_rights_inheriting=%"PRIu64")\n", + uvwasi, + fd, + fs_rights_base, + fs_rights_inheriting); + if (uvwasi == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, fd, &wrap, 0, 0); + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, 0, 0); if (err != UVWASI_ESUCCESS) return err; @@ -746,10 +820,12 @@ uvwasi_errno_t uvwasi_fd_filestat_get(uvwasi_t* uvwasi, uvwasi_errno_t err; int r; + DEBUG("uvwasi_fd_filestat_get(uvwasi=%p, fd=%d, buf=%p)\n", uvwasi, fd, buf); + if (uvwasi == NULL || buf == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_FILESTAT_GET, @@ -781,10 +857,15 @@ uvwasi_errno_t uvwasi_fd_filestat_set_size(uvwasi_t* uvwasi, uvwasi_errno_t err; int r; + DEBUG("uvwasi_fd_filestat_set_size(uvwasi=%p, fd=%d, st_size=%"PRIu64")\n", + uvwasi, + fd, + st_size); + if (uvwasi == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_FILESTAT_SET_SIZE, @@ -814,6 +895,14 @@ uvwasi_errno_t uvwasi_fd_filestat_set_times(uvwasi_t* uvwasi, uvwasi_errno_t err; int r; + DEBUG("uvwasi_fd_filestat_set_times(uvwasi=%p, fd=%d, st_atim=%"PRIu64", " + "st_mtim=%"PRIu64", fst_flags=%d)\n", + uvwasi, + fd, + st_atim, + st_mtim, + fst_flags); + if (uvwasi == NULL) return UVWASI_EINVAL; @@ -822,7 +911,7 @@ uvwasi_errno_t uvwasi_fd_filestat_set_times(uvwasi_t* uvwasi, return UVWASI_EINVAL; } - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_FILESTAT_SET_TIMES, @@ -845,9 +934,9 @@ uvwasi_errno_t uvwasi_fd_filestat_set_times(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_fd_pread(uvwasi_t* uvwasi, uvwasi_fd_t fd, const uvwasi_iovec_t* iovs, - size_t iovs_len, + uvwasi_size_t iovs_len, uvwasi_filesize_t offset, - size_t* nread) { + uvwasi_size_t* nread) { struct uvwasi_fd_wrap_t* wrap; uv_buf_t* bufs; uv_fs_t req; @@ -855,10 +944,19 @@ uvwasi_errno_t uvwasi_fd_pread(uvwasi_t* uvwasi, size_t uvread; int r; + DEBUG("uvwasi_fd_pread(uvwasi=%p, fd=%d, iovs=%p, iovs_len=%zu, " + "offset=%"PRIu64", nread=%p)\n", + uvwasi, + fd, + iovs, + iovs_len, + offset, + nread); + if (uvwasi == NULL || iovs == NULL || nread == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_READ | UVWASI_RIGHT_FD_SEEK, @@ -881,7 +979,7 @@ uvwasi_errno_t uvwasi_fd_pread(uvwasi_t* uvwasi, if (r < 0) return uvwasi__translate_uv_error(r); - *nread = uvread; + *nread = (uvwasi_size_t) uvread; return UVWASI_ESUCCESS; } @@ -892,10 +990,15 @@ uvwasi_errno_t uvwasi_fd_prestat_get(uvwasi_t* uvwasi, struct uvwasi_fd_wrap_t* wrap; uvwasi_errno_t err; + DEBUG("uvwasi_fd_prestat_get(uvwasi=%p, fd=%d, buf=%p)\n", + uvwasi, + fd, + buf); + if (uvwasi == NULL || buf == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, fd, &wrap, 0, 0); + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, 0, 0); if (err != UVWASI_ESUCCESS) return err; if (wrap->preopen != 1) { @@ -915,15 +1018,21 @@ uvwasi_errno_t uvwasi_fd_prestat_get(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_fd_prestat_dir_name(uvwasi_t* uvwasi, uvwasi_fd_t fd, char* path, - size_t path_len) { + uvwasi_size_t path_len) { struct uvwasi_fd_wrap_t* wrap; uvwasi_errno_t err; size_t size; + DEBUG("uvwasi_fd_prestat_dir_name(uvwasi=%p, fd=%d, path=%p, path_len=%zu)\n", + uvwasi, + fd, + path, + path_len); + if (uvwasi == NULL || path == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, fd, &wrap, 0, 0); + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, 0, 0); if (err != UVWASI_ESUCCESS) return err; if (wrap->preopen != 1) { @@ -932,7 +1041,7 @@ uvwasi_errno_t uvwasi_fd_prestat_dir_name(uvwasi_t* uvwasi, } size = strlen(wrap->path) + 1; - if (size > path_len) { + if (size > (size_t) path_len) { err = UVWASI_ENOBUFS; goto exit; } @@ -948,9 +1057,9 @@ uvwasi_errno_t uvwasi_fd_prestat_dir_name(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_fd_pwrite(uvwasi_t* uvwasi, uvwasi_fd_t fd, const uvwasi_ciovec_t* iovs, - size_t iovs_len, + uvwasi_size_t iovs_len, uvwasi_filesize_t offset, - size_t* nwritten) { + uvwasi_size_t* nwritten) { struct uvwasi_fd_wrap_t* wrap; uv_buf_t* bufs; uv_fs_t req; @@ -958,10 +1067,19 @@ uvwasi_errno_t uvwasi_fd_pwrite(uvwasi_t* uvwasi, size_t uvwritten; int r; + DEBUG("uvwasi_fd_pwrite(uvwasi=%p, fd=%d, iovs=%p, iovs_len=%zu, " + "offset=%"PRIu64", nwritten=%p)\n", + uvwasi, + fd, + iovs, + iovs_len, + offset, + nwritten); + if (uvwasi == NULL || iovs == NULL || nwritten == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_WRITE | UVWASI_RIGHT_FD_SEEK, @@ -984,7 +1102,7 @@ uvwasi_errno_t uvwasi_fd_pwrite(uvwasi_t* uvwasi, if (r < 0) return uvwasi__translate_uv_error(r); - *nwritten = uvwritten; + *nwritten = (uvwasi_size_t) uvwritten; return UVWASI_ESUCCESS; } @@ -992,8 +1110,8 @@ uvwasi_errno_t uvwasi_fd_pwrite(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_fd_read(uvwasi_t* uvwasi, uvwasi_fd_t fd, const uvwasi_iovec_t* iovs, - size_t iovs_len, - size_t* nread) { + uvwasi_size_t iovs_len, + uvwasi_size_t* nread) { struct uvwasi_fd_wrap_t* wrap; uv_buf_t* bufs; uv_fs_t req; @@ -1001,10 +1119,17 @@ uvwasi_errno_t uvwasi_fd_read(uvwasi_t* uvwasi, size_t uvread; int r; + DEBUG("uvwasi_fd_read(uvwasi=%p, fd=%d, iovs=%p, iovs_len=%zu, nread=%p)\n", + uvwasi, + fd, + iovs, + iovs_len, + nread); + if (uvwasi == NULL || iovs == NULL || nread == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_READ, 0); + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_READ, 0); if (err != UVWASI_ESUCCESS) return err; @@ -1023,7 +1148,7 @@ uvwasi_errno_t uvwasi_fd_read(uvwasi_t* uvwasi, if (r < 0) return uvwasi__translate_uv_error(r); - *nread = uvread; + *nread = (uvwasi_size_t) uvread; return UVWASI_ESUCCESS; } @@ -1031,9 +1156,9 @@ uvwasi_errno_t uvwasi_fd_read(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi, uvwasi_fd_t fd, void* buf, - size_t buf_len, + uvwasi_size_t buf_len, uvwasi_dircookie_t cookie, - size_t* bufused) { + uvwasi_size_t* bufused) { /* TODO(cjihrig): Support Windows where seekdir() and telldir() are used. */ /* TODO(cjihrig): Avoid opening and closing the directory on each call. */ struct uvwasi_fd_wrap_t* wrap; @@ -1049,10 +1174,19 @@ uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi, int i; int r; + DEBUG("uvwasi_fd_readdir(uvwasi=%p, fd=%d, buf=%p, buf_len=%zu, " + "cookie=%"PRIu64", bufused=%p)\n", + uvwasi, + fd, + buf, + buf_len, + cookie, + bufused); + if (uvwasi == NULL || buf == NULL || bufused == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_READDIR, @@ -1171,10 +1305,12 @@ uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_fd_renumber(uvwasi_t* uvwasi, uvwasi_fd_t from, uvwasi_fd_t to) { + DEBUG("uvwasi_fd_renumber(uvwasi=%p, from=%d, to=%d)\n", uvwasi, from, to); + if (uvwasi == NULL) return UVWASI_EINVAL; - return uvwasi_fd_table_renumber(uvwasi, &uvwasi->fds, to, from); + return uvwasi_fd_table_renumber(uvwasi, uvwasi->fds, to, from); } @@ -1186,10 +1322,18 @@ uvwasi_errno_t uvwasi_fd_seek(uvwasi_t* uvwasi, struct uvwasi_fd_wrap_t* wrap; uvwasi_errno_t err; + DEBUG("uvwasi_fd_seek(uvwasi=%p, fd=%d, offset=%"PRId64", " + "whence=%d, newoffset=%p)\n", + uvwasi, + fd, + offset, + whence, + newoffset); + if (uvwasi == NULL || newoffset == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_SEEK, 0); + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_SEEK, 0); if (err != UVWASI_ESUCCESS) return err; @@ -1205,10 +1349,12 @@ uvwasi_errno_t uvwasi_fd_sync(uvwasi_t* uvwasi, uvwasi_fd_t fd) { uvwasi_errno_t err; int r; + DEBUG("uvwasi_fd_sync(uvwasi=%p, fd=%d)\n", uvwasi, fd); + if (uvwasi == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_SYNC, @@ -1233,10 +1379,12 @@ uvwasi_errno_t uvwasi_fd_tell(uvwasi_t* uvwasi, struct uvwasi_fd_wrap_t* wrap; uvwasi_errno_t err; + DEBUG("uvwasi_fd_tell(uvwasi=%p, fd=%d, offset=%p)\n", uvwasi, fd, offset); + if (uvwasi == NULL || offset == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_TELL, 0); + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_TELL, 0); if (err != UVWASI_ESUCCESS) return err; @@ -1249,8 +1397,8 @@ uvwasi_errno_t uvwasi_fd_tell(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_fd_write(uvwasi_t* uvwasi, uvwasi_fd_t fd, const uvwasi_ciovec_t* iovs, - size_t iovs_len, - size_t* nwritten) { + uvwasi_size_t iovs_len, + uvwasi_size_t* nwritten) { struct uvwasi_fd_wrap_t* wrap; uv_buf_t* bufs; uv_fs_t req; @@ -1258,10 +1406,18 @@ uvwasi_errno_t uvwasi_fd_write(uvwasi_t* uvwasi, size_t uvwritten; int r; + DEBUG("uvwasi_fd_write(uvwasi=%p, fd=%d, iovs=%p, iovs_len=%zu, " + "nwritten=%p)\n", + uvwasi, + fd, + iovs, + iovs_len, + nwritten); + if (uvwasi == NULL || iovs == NULL || nwritten == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_WRITE, 0); + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_WRITE, 0); if (err != UVWASI_ESUCCESS) return err; @@ -1280,7 +1436,7 @@ uvwasi_errno_t uvwasi_fd_write(uvwasi_t* uvwasi, if (r < 0) return uvwasi__translate_uv_error(r); - *nwritten = uvwritten; + *nwritten = (uvwasi_size_t) uvwritten; return UVWASI_ESUCCESS; } @@ -1288,17 +1444,24 @@ uvwasi_errno_t uvwasi_fd_write(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_path_create_directory(uvwasi_t* uvwasi, uvwasi_fd_t fd, const char* path, - size_t path_len) { - char resolved_path[PATH_MAX_BYTES]; + uvwasi_size_t path_len) { + char* resolved_path; struct uvwasi_fd_wrap_t* wrap; uv_fs_t req; uvwasi_errno_t err; int r; + DEBUG("uvwasi_path_create_directory(uvwasi=%p, fd=%d, path='%s', " + "path_len=%zu)\n", + uvwasi, + fd, + path, + path_len); + if (uvwasi == NULL || path == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_PATH_CREATE_DIRECTORY, @@ -1306,12 +1469,13 @@ uvwasi_errno_t uvwasi_path_create_directory(uvwasi_t* uvwasi, if (err != UVWASI_ESUCCESS) return err; - err = uvwasi__resolve_path(uvwasi, wrap, path, path_len, resolved_path, 0); + err = uvwasi__resolve_path(uvwasi, wrap, path, path_len, &resolved_path, 0); if (err != UVWASI_ESUCCESS) goto exit; r = uv_fs_mkdir(NULL, &req, resolved_path, 0777, NULL); uv_fs_req_cleanup(&req); + uvwasi__free(uvwasi, resolved_path); if (r != 0) { err = uvwasi__translate_uv_error(r); @@ -1329,18 +1493,27 @@ uvwasi_errno_t uvwasi_path_filestat_get(uvwasi_t* uvwasi, uvwasi_fd_t fd, uvwasi_lookupflags_t flags, const char* path, - size_t path_len, + uvwasi_size_t path_len, uvwasi_filestat_t* buf) { - char resolved_path[PATH_MAX_BYTES]; + char* resolved_path; struct uvwasi_fd_wrap_t* wrap; uv_fs_t req; uvwasi_errno_t err; int r; + DEBUG("uvwasi_path_filestat_get(uvwasi=%p, fd=%d, flags=%d, path='%s', " + "path_len=%zu, buf=%p)\n", + uvwasi, + fd, + flags, + path, + path_len, + buf); + if (uvwasi == NULL || path == NULL || buf == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_PATH_FILESTAT_GET, @@ -1352,12 +1525,13 @@ uvwasi_errno_t uvwasi_path_filestat_get(uvwasi_t* uvwasi, wrap, path, path_len, - resolved_path, + &resolved_path, flags); if (err != UVWASI_ESUCCESS) goto exit; r = uv_fs_stat(NULL, &req, resolved_path, NULL); + uvwasi__free(uvwasi, resolved_path); if (r != 0) { uv_fs_req_cleanup(&req); err = uvwasi__translate_uv_error(r); @@ -1377,17 +1551,28 @@ uvwasi_errno_t uvwasi_path_filestat_set_times(uvwasi_t* uvwasi, uvwasi_fd_t fd, uvwasi_lookupflags_t flags, const char* path, - size_t path_len, + uvwasi_size_t path_len, uvwasi_timestamp_t st_atim, uvwasi_timestamp_t st_mtim, uvwasi_fstflags_t fst_flags) { /* TODO(cjihrig): libuv does not currently support nanosecond precision. */ - char resolved_path[PATH_MAX_BYTES]; + char* resolved_path; struct uvwasi_fd_wrap_t* wrap; uv_fs_t req; uvwasi_errno_t err; int r; + DEBUG("uvwasi_path_filestat_set_times(uvwasi=%p, fd=%d, flags=%d, path='%s', " + "path_len=%zu, st_atim=%"PRIu64", st_mtim=%"PRIu64", fst_flags=%d)\n", + uvwasi, + fd, + flags, + path, + path_len, + st_atim, + st_mtim, + fst_flags); + if (uvwasi == NULL || path == NULL) return UVWASI_EINVAL; @@ -1396,7 +1581,7 @@ uvwasi_errno_t uvwasi_path_filestat_set_times(uvwasi_t* uvwasi, return UVWASI_EINVAL; } - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_PATH_FILESTAT_SET_TIMES, @@ -1408,13 +1593,14 @@ uvwasi_errno_t uvwasi_path_filestat_set_times(uvwasi_t* uvwasi, wrap, path, path_len, - resolved_path, + &resolved_path, flags); if (err != UVWASI_ESUCCESS) goto exit; /* TODO(cjihrig): st_atim and st_mtim should not be unconditionally passed. */ r = uv_fs_utime(NULL, &req, resolved_path, st_atim, st_mtim, NULL); + uvwasi__free(uvwasi, resolved_path); uv_fs_req_cleanup(&req); if (r != 0) { @@ -1433,25 +1619,36 @@ uvwasi_errno_t uvwasi_path_link(uvwasi_t* uvwasi, uvwasi_fd_t old_fd, uvwasi_lookupflags_t old_flags, const char* old_path, - size_t old_path_len, + uvwasi_size_t old_path_len, uvwasi_fd_t new_fd, const char* new_path, - size_t new_path_len) { - char resolved_old_path[PATH_MAX_BYTES]; - char resolved_new_path[PATH_MAX_BYTES]; + uvwasi_size_t new_path_len) { + char* resolved_old_path; + char* resolved_new_path; struct uvwasi_fd_wrap_t* old_wrap; struct uvwasi_fd_wrap_t* new_wrap; uvwasi_errno_t err; uv_fs_t req; int r; + DEBUG("uvwasi_path_link(uvwasi=%p, old_fd=%d, old_flags=%d, old_path='%s', " + "old_path_len=%zu, new_fd=%d, new_path='%s', new_path_len=%zu)\n", + uvwasi, + old_fd, + old_flags, + old_path, + old_path_len, + new_fd, + new_path, + new_path_len); + if (uvwasi == NULL || old_path == NULL || new_path == NULL) return UVWASI_EINVAL; - uvwasi_fd_table_lock(&uvwasi->fds); + uvwasi_fd_table_lock(uvwasi->fds); if (old_fd == new_fd) { - err = uvwasi_fd_table_get_nolock(&uvwasi->fds, + err = uvwasi_fd_table_get_nolock(uvwasi->fds, old_fd, &old_wrap, UVWASI_RIGHT_PATH_LINK_SOURCE | @@ -1459,17 +1656,17 @@ uvwasi_errno_t uvwasi_path_link(uvwasi_t* uvwasi, 0); new_wrap = old_wrap; } else { - err = uvwasi_fd_table_get_nolock(&uvwasi->fds, + err = uvwasi_fd_table_get_nolock(uvwasi->fds, old_fd, &old_wrap, UVWASI_RIGHT_PATH_LINK_SOURCE, 0); if (err != UVWASI_ESUCCESS) { - uvwasi_fd_table_unlock(&uvwasi->fds); + uvwasi_fd_table_unlock(uvwasi->fds); return err; } - err = uvwasi_fd_table_get_nolock(&uvwasi->fds, + err = uvwasi_fd_table_get_nolock(uvwasi->fds, new_fd, &new_wrap, UVWASI_RIGHT_PATH_LINK_TARGET, @@ -1478,16 +1675,19 @@ uvwasi_errno_t uvwasi_path_link(uvwasi_t* uvwasi, uv_mutex_unlock(&old_wrap->mutex); } - uvwasi_fd_table_unlock(&uvwasi->fds); + uvwasi_fd_table_unlock(uvwasi->fds); if (err != UVWASI_ESUCCESS) return err; + resolved_old_path = NULL; + resolved_new_path = NULL; + err = uvwasi__resolve_path(uvwasi, old_wrap, old_path, old_path_len, - resolved_old_path, + &resolved_old_path, old_flags); if (err != UVWASI_ESUCCESS) goto exit; @@ -1496,7 +1696,7 @@ uvwasi_errno_t uvwasi_path_link(uvwasi_t* uvwasi, new_wrap, new_path, new_path_len, - resolved_new_path, + &resolved_new_path, 0); if (err != UVWASI_ESUCCESS) goto exit; @@ -1513,6 +1713,9 @@ uvwasi_errno_t uvwasi_path_link(uvwasi_t* uvwasi, uv_mutex_unlock(&new_wrap->mutex); if (old_fd != new_fd) uv_mutex_unlock(&old_wrap->mutex); + + uvwasi__free(uvwasi, resolved_old_path); + uvwasi__free(uvwasi, resolved_new_path); return err; } @@ -1521,13 +1724,13 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi, uvwasi_fd_t dirfd, uvwasi_lookupflags_t dirflags, const char* path, - size_t path_len, + uvwasi_size_t path_len, uvwasi_oflags_t o_flags, uvwasi_rights_t fs_rights_base, uvwasi_rights_t fs_rights_inheriting, uvwasi_fdflags_t fs_flags, uvwasi_fd_t* fd) { - char resolved_path[PATH_MAX_BYTES]; + char* resolved_path; uvwasi_rights_t needed_inheriting; uvwasi_rights_t needed_base; uvwasi_rights_t max_base; @@ -1542,6 +1745,20 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi, int write; int r; + DEBUG("uvwasi_path_open(uvwasi=%p, dirfd=%d, dirflags=%d, path='%s', " + "path_len=%zu, o_flags=%d, fs_rights_base=%"PRIu64", " + "fs_rights_inheriting=%"PRIu64", fs_flags=%d, fd=%p)\n", + uvwasi, + dirfd, + dirflags, + path, + path_len, + o_flags, + fs_rights_base, + fs_rights_inheriting, + fs_flags, + fd); + if (uvwasi == NULL || path == NULL || fd == NULL) return UVWASI_EINVAL; @@ -1591,7 +1808,7 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi, if (write && (flags & (UV_FS_O_APPEND | UV_FS_O_TRUNC)) == 0) needed_inheriting |= UVWASI_RIGHT_FD_SEEK; - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, dirfd, &dirfd_wrap, needed_base, @@ -1603,7 +1820,7 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi, dirfd_wrap, path, path_len, - resolved_path, + &resolved_path, dirflags); if (err != UVWASI_ESUCCESS) { uv_mutex_unlock(&dirfd_wrap->mutex); @@ -1614,8 +1831,10 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi, uv_mutex_unlock(&dirfd_wrap->mutex); uv_fs_req_cleanup(&req); - if (r < 0) + if (r < 0) { + uvwasi__free(uvwasi, resolved_path); return uvwasi__translate_uv_error(r); + } /* Not all platforms support UV_FS_O_DIRECTORY, so get the file type and check it here. */ @@ -1634,7 +1853,7 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi, goto close_file_and_error_exit; err = uvwasi_fd_table_insert(uvwasi, - &uvwasi->fds, + uvwasi->fds, r, resolved_path, resolved_path, @@ -1648,11 +1867,13 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi, *fd = wrap->id; uv_mutex_unlock(&wrap->mutex); + uvwasi__free(uvwasi, resolved_path); return UVWASI_ESUCCESS; close_file_and_error_exit: uv_fs_close(NULL, &req, r, NULL); uv_fs_req_cleanup(&req); + uvwasi__free(uvwasi, resolved_path); return err; } @@ -1660,21 +1881,31 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_path_readlink(uvwasi_t* uvwasi, uvwasi_fd_t fd, const char* path, - size_t path_len, + uvwasi_size_t path_len, char* buf, - size_t buf_len, - size_t* bufused) { - char resolved_path[PATH_MAX_BYTES]; + uvwasi_size_t buf_len, + uvwasi_size_t* bufused) { + char* resolved_path; struct uvwasi_fd_wrap_t* wrap; uvwasi_errno_t err; uv_fs_t req; size_t len; int r; + DEBUG("uvwasi_path_readlink(uvwasi=%p, fd=%d, path='%s', path_len=%zu, " + "buf=%p, buf_len=%zu, bufused=%p)\n", + uvwasi, + fd, + path, + path_len, + buf, + buf_len, + bufused); + if (uvwasi == NULL || path == NULL || buf == NULL || bufused == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_PATH_READLINK, @@ -1682,7 +1913,7 @@ uvwasi_errno_t uvwasi_path_readlink(uvwasi_t* uvwasi, if (err != UVWASI_ESUCCESS) return err; - err = uvwasi__resolve_path(uvwasi, wrap, path, path_len, resolved_path, 0); + err = uvwasi__resolve_path(uvwasi, wrap, path, path_len, &resolved_path, 0); if (err != UVWASI_ESUCCESS) { uv_mutex_unlock(&wrap->mutex); return err; @@ -1690,6 +1921,7 @@ uvwasi_errno_t uvwasi_path_readlink(uvwasi_t* uvwasi, r = uv_fs_readlink(NULL, &req, resolved_path, NULL); uv_mutex_unlock(&wrap->mutex); + uvwasi__free(uvwasi, resolved_path); if (r != 0) { uv_fs_req_cleanup(&req); return uvwasi__translate_uv_error(r); @@ -1712,17 +1944,24 @@ uvwasi_errno_t uvwasi_path_readlink(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_path_remove_directory(uvwasi_t* uvwasi, uvwasi_fd_t fd, const char* path, - size_t path_len) { - char resolved_path[PATH_MAX_BYTES]; + uvwasi_size_t path_len) { + char* resolved_path; struct uvwasi_fd_wrap_t* wrap; uv_fs_t req; uvwasi_errno_t err; int r; + DEBUG("uvwasi_path_remove_directory(uvwasi=%p, fd=%d, path='%s', " + "path_len=%zu)\n", + uvwasi, + fd, + path, + path_len); + if (uvwasi == NULL || path == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_PATH_REMOVE_DIRECTORY, @@ -1730,7 +1969,7 @@ uvwasi_errno_t uvwasi_path_remove_directory(uvwasi_t* uvwasi, if (err != UVWASI_ESUCCESS) return err; - err = uvwasi__resolve_path(uvwasi, wrap, path, path_len, resolved_path, 0); + err = uvwasi__resolve_path(uvwasi, wrap, path, path_len, &resolved_path, 0); if (err != UVWASI_ESUCCESS) { uv_mutex_unlock(&wrap->mutex); return err; @@ -1738,6 +1977,7 @@ uvwasi_errno_t uvwasi_path_remove_directory(uvwasi_t* uvwasi, r = uv_fs_rmdir(NULL, &req, resolved_path, NULL); uv_mutex_unlock(&wrap->mutex); + uvwasi__free(uvwasi, resolved_path); uv_fs_req_cleanup(&req); if (r != 0) @@ -1750,25 +1990,35 @@ uvwasi_errno_t uvwasi_path_remove_directory(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_path_rename(uvwasi_t* uvwasi, uvwasi_fd_t old_fd, const char* old_path, - size_t old_path_len, + uvwasi_size_t old_path_len, uvwasi_fd_t new_fd, const char* new_path, - size_t new_path_len) { - char resolved_old_path[PATH_MAX_BYTES]; - char resolved_new_path[PATH_MAX_BYTES]; + uvwasi_size_t new_path_len) { + char* resolved_old_path; + char* resolved_new_path; struct uvwasi_fd_wrap_t* old_wrap; struct uvwasi_fd_wrap_t* new_wrap; uvwasi_errno_t err; uv_fs_t req; int r; + DEBUG("uvwasi_path_rename(uvwasi=%p, old_fd=%d, old_path='%s', " + "old_path_len=%zu, new_fd=%d, new_path='%s', new_path_len=%zu)\n", + uvwasi, + old_fd, + old_path, + old_path_len, + new_fd, + new_path, + new_path_len); + if (uvwasi == NULL || old_path == NULL || new_path == NULL) return UVWASI_EINVAL; - uvwasi_fd_table_lock(&uvwasi->fds); + uvwasi_fd_table_lock(uvwasi->fds); if (old_fd == new_fd) { - err = uvwasi_fd_table_get_nolock(&uvwasi->fds, + err = uvwasi_fd_table_get_nolock(uvwasi->fds, old_fd, &old_wrap, UVWASI_RIGHT_PATH_RENAME_SOURCE | @@ -1776,17 +2026,17 @@ uvwasi_errno_t uvwasi_path_rename(uvwasi_t* uvwasi, 0); new_wrap = old_wrap; } else { - err = uvwasi_fd_table_get_nolock(&uvwasi->fds, + err = uvwasi_fd_table_get_nolock(uvwasi->fds, old_fd, &old_wrap, UVWASI_RIGHT_PATH_RENAME_SOURCE, 0); if (err != UVWASI_ESUCCESS) { - uvwasi_fd_table_unlock(&uvwasi->fds); + uvwasi_fd_table_unlock(uvwasi->fds); return err; } - err = uvwasi_fd_table_get_nolock(&uvwasi->fds, + err = uvwasi_fd_table_get_nolock(uvwasi->fds, new_fd, &new_wrap, UVWASI_RIGHT_PATH_RENAME_TARGET, @@ -1795,16 +2045,19 @@ uvwasi_errno_t uvwasi_path_rename(uvwasi_t* uvwasi, uv_mutex_unlock(&old_wrap->mutex); } - uvwasi_fd_table_unlock(&uvwasi->fds); + uvwasi_fd_table_unlock(uvwasi->fds); if (err != UVWASI_ESUCCESS) return err; + resolved_old_path = NULL; + resolved_new_path = NULL; + err = uvwasi__resolve_path(uvwasi, old_wrap, old_path, old_path_len, - resolved_old_path, + &resolved_old_path, 0); if (err != UVWASI_ESUCCESS) goto exit; @@ -1813,7 +2066,7 @@ uvwasi_errno_t uvwasi_path_rename(uvwasi_t* uvwasi, new_wrap, new_path, new_path_len, - resolved_new_path, + &resolved_new_path, 0); if (err != UVWASI_ESUCCESS) goto exit; @@ -1831,26 +2084,37 @@ uvwasi_errno_t uvwasi_path_rename(uvwasi_t* uvwasi, if (old_fd != new_fd) uv_mutex_unlock(&old_wrap->mutex); + uvwasi__free(uvwasi, resolved_old_path); + uvwasi__free(uvwasi, resolved_new_path); return err; } uvwasi_errno_t uvwasi_path_symlink(uvwasi_t* uvwasi, const char* old_path, - size_t old_path_len, + uvwasi_size_t old_path_len, uvwasi_fd_t fd, const char* new_path, - size_t new_path_len) { - char resolved_new_path[PATH_MAX_BYTES]; + uvwasi_size_t new_path_len) { + char* resolved_new_path; struct uvwasi_fd_wrap_t* wrap; uvwasi_errno_t err; uv_fs_t req; int r; + DEBUG("uvwasi_path_symlink(uvwasi=%p, old_path='%s', old_path_len=%zu, " + "fd=%d, new_path='%s', new_path_len=%zu)\n", + uvwasi, + old_path, + old_path_len, + fd, + new_path, + new_path_len); + if (uvwasi == NULL || old_path == NULL || new_path == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_PATH_SYMLINK, @@ -1862,7 +2126,7 @@ uvwasi_errno_t uvwasi_path_symlink(uvwasi_t* uvwasi, wrap, new_path, new_path_len, - resolved_new_path, + &resolved_new_path, 0); if (err != UVWASI_ESUCCESS) { uv_mutex_unlock(&wrap->mutex); @@ -1872,6 +2136,7 @@ uvwasi_errno_t uvwasi_path_symlink(uvwasi_t* uvwasi, /* Windows support may require setting the flags option. */ r = uv_fs_symlink(NULL, &req, old_path, resolved_new_path, 0, NULL); uv_mutex_unlock(&wrap->mutex); + uvwasi__free(uvwasi, resolved_new_path); uv_fs_req_cleanup(&req); if (r != 0) return uvwasi__translate_uv_error(r); @@ -1883,17 +2148,23 @@ uvwasi_errno_t uvwasi_path_symlink(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_path_unlink_file(uvwasi_t* uvwasi, uvwasi_fd_t fd, const char* path, - size_t path_len) { - char resolved_path[PATH_MAX_BYTES]; + uvwasi_size_t path_len) { + char* resolved_path; struct uvwasi_fd_wrap_t* wrap; uv_fs_t req; uvwasi_errno_t err; int r; + DEBUG("uvwasi_path_unlink_file(uvwasi=%p, fd=%d, path='%s', path_len=%zu)\n", + uvwasi, + fd, + path, + path_len); + if (uvwasi == NULL || path == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_PATH_UNLINK_FILE, @@ -1901,7 +2172,7 @@ uvwasi_errno_t uvwasi_path_unlink_file(uvwasi_t* uvwasi, if (err != UVWASI_ESUCCESS) return err; - err = uvwasi__resolve_path(uvwasi, wrap, path, path_len, resolved_path, 0); + err = uvwasi__resolve_path(uvwasi, wrap, path, path_len, &resolved_path, 0); if (err != UVWASI_ESUCCESS) { uv_mutex_unlock(&wrap->mutex); return err; @@ -1909,6 +2180,7 @@ uvwasi_errno_t uvwasi_path_unlink_file(uvwasi_t* uvwasi, r = uv_fs_unlink(NULL, &req, resolved_path, NULL); uv_mutex_unlock(&wrap->mutex); + uvwasi__free(uvwasi, resolved_path); uv_fs_req_cleanup(&req); if (r != 0) @@ -1921,14 +2193,127 @@ uvwasi_errno_t uvwasi_path_unlink_file(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_poll_oneoff(uvwasi_t* uvwasi, const uvwasi_subscription_t* in, uvwasi_event_t* out, - size_t nsubscriptions, - size_t* nevents) { - /* TODO(cjihrig): Implement this. */ - return UVWASI_ENOTSUP; + uvwasi_size_t nsubscriptions, + uvwasi_size_t* nevents) { + struct uvwasi_poll_oneoff_state_t state; + struct uvwasi__poll_fdevent_t* fdevent; + uvwasi_userdata_t timer_userdata; + uvwasi_timestamp_t min_timeout; + uvwasi_timestamp_t cur_timeout; + uvwasi_timestamp_t now; + uvwasi_subscription_t sub; + uvwasi_event_t* event; + uvwasi_errno_t err; + int has_timeout; + uvwasi_size_t i; + + DEBUG("uvwasi_poll_oneoff(uvwasi=%p, in=%p, out=%p, nsubscriptions=%zu, " + "nevents=%p)\n", + uvwasi, + in, + out, + nsubscriptions, + nevents); + + if (uvwasi == NULL || in == NULL || out == NULL || + nsubscriptions == 0 || nevents == NULL) { + return UVWASI_EINVAL; + } + + *nevents = 0; + err = uvwasi__poll_oneoff_state_init(uvwasi, &state, nsubscriptions); + if (err != UVWASI_ESUCCESS) + return err; + + has_timeout = 0; + min_timeout = 0; + + for (i = 0; i < nsubscriptions; i++) { + sub = in[i]; + + switch (sub.type) { + case UVWASI_EVENTTYPE_CLOCK: + if (sub.u.clock.flags == UVWASI_SUBSCRIPTION_CLOCK_ABSTIME) { + /* Convert absolute time to relative delay. */ + err = uvwasi__clock_gettime_realtime(&now); + if (err != UVWASI_ESUCCESS) + goto exit; + + cur_timeout = sub.u.clock.timeout - now; + } else { + cur_timeout = sub.u.clock.timeout; + } + + if (has_timeout == 0 || cur_timeout < min_timeout) { + min_timeout = cur_timeout; + timer_userdata = sub.userdata; + has_timeout = 1; + } + + break; + case UVWASI_EVENTTYPE_FD_READ: + case UVWASI_EVENTTYPE_FD_WRITE: + err = uvwasi__poll_oneoff_state_add_fdevent(&state, &sub); + if (err != UVWASI_ESUCCESS) + goto exit; + + break; + default: + err = UVWASI_EINVAL; + goto exit; + } + } + + if (has_timeout == 1) { + err = uvwasi__poll_oneoff_state_set_timer(&state, min_timeout); + if (err != UVWASI_ESUCCESS) + goto exit; + } + + /* Handle poll() errors, then timeouts, then happy path. */ + err = uvwasi__poll_oneoff_run(&state); + if (err != UVWASI_ESUCCESS) { + goto exit; + } else if (state.result == 0) { + event = &out[0]; + event->userdata = timer_userdata; + event->error = UVWASI_ESUCCESS; + event->type = UVWASI_EVENTTYPE_CLOCK; + *nevents = 1; + } else { + for (i = 0; i < state.fdevent_cnt; i++) { + fdevent = &state.fdevents[i]; + event = &out[*nevents]; + + event->userdata = fdevent->userdata; + event->error = fdevent->error; + event->type = fdevent->type; + event->u.fd_readwrite.nbytes = 0; + event->u.fd_readwrite.flags = 0; + + if (fdevent->error != UVWASI_ESUCCESS) + ; + else if ((fdevent->revents & UV_DISCONNECT) != 0) + event->u.fd_readwrite.flags = UVWASI_EVENT_FD_READWRITE_HANGUP; + else if ((fdevent->revents & (UV_READABLE | UV_WRITABLE)) != 0) + ; /* TODO(cjihrig): Set nbytes if type is UVWASI_EVENTTYPE_FD_READ. */ + else + continue; + + *nevents = *nevents + 1; + } + } + + err = UVWASI_ESUCCESS; + +exit: + uvwasi__poll_oneoff_state_cleanup(&state); + return err; } uvwasi_errno_t uvwasi_proc_exit(uvwasi_t* uvwasi, uvwasi_exitcode_t rval) { + DEBUG("uvwasi_proc_exit(uvwasi=%p, rval=%d)\n", uvwasi, rval); exit(rval); return UVWASI_ESUCCESS; /* This doesn't happen. */ } @@ -1937,6 +2322,8 @@ uvwasi_errno_t uvwasi_proc_exit(uvwasi_t* uvwasi, uvwasi_exitcode_t rval) { uvwasi_errno_t uvwasi_proc_raise(uvwasi_t* uvwasi, uvwasi_signal_t sig) { int r; + DEBUG("uvwasi_proc_raise(uvwasi=%p, sig=%d)\n", uvwasi, sig); + if (uvwasi == NULL) return UVWASI_EINVAL; @@ -1952,9 +2339,16 @@ uvwasi_errno_t uvwasi_proc_raise(uvwasi_t* uvwasi, uvwasi_signal_t sig) { } -uvwasi_errno_t uvwasi_random_get(uvwasi_t* uvwasi, void* buf, size_t buf_len) { +uvwasi_errno_t uvwasi_random_get(uvwasi_t* uvwasi, + void* buf, + uvwasi_size_t buf_len) { int r; + DEBUG("uvwasi_random_get(uvwasi=%p, buf=%p, buf_len=%zu)\n", + uvwasi, + buf, + buf_len); + if (uvwasi == NULL || buf == NULL) return UVWASI_EINVAL; @@ -1967,6 +2361,8 @@ uvwasi_errno_t uvwasi_random_get(uvwasi_t* uvwasi, void* buf, size_t buf_len) { uvwasi_errno_t uvwasi_sched_yield(uvwasi_t* uvwasi) { + DEBUG("uvwasi_sched_yield(uvwasi=%p)\n", uvwasi); + if (uvwasi == NULL) return UVWASI_EINVAL; @@ -1984,12 +2380,13 @@ uvwasi_errno_t uvwasi_sched_yield(uvwasi_t* uvwasi) { uvwasi_errno_t uvwasi_sock_recv(uvwasi_t* uvwasi, uvwasi_fd_t sock, const uvwasi_iovec_t* ri_data, - size_t ri_data_len, + uvwasi_size_t ri_data_len, uvwasi_riflags_t ri_flags, - size_t* ro_datalen, + uvwasi_size_t* ro_datalen, uvwasi_roflags_t* ro_flags) { /* TODO(cjihrig): Waiting to implement, pending https://github.com/WebAssembly/WASI/issues/4 */ + DEBUG("uvwasi_sock_recv(uvwasi=%p, unimplemented)\n", uvwasi); return UVWASI_ENOTSUP; } @@ -1997,11 +2394,12 @@ uvwasi_errno_t uvwasi_sock_recv(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_sock_send(uvwasi_t* uvwasi, uvwasi_fd_t sock, const uvwasi_ciovec_t* si_data, - size_t si_data_len, + uvwasi_size_t si_data_len, uvwasi_siflags_t si_flags, - size_t* so_datalen) { + uvwasi_size_t* so_datalen) { /* TODO(cjihrig): Waiting to implement, pending https://github.com/WebAssembly/WASI/issues/4 */ + DEBUG("uvwasi_sock_send(uvwasi=%p, unimplemented)\n", uvwasi); return UVWASI_ENOTSUP; } @@ -2011,6 +2409,7 @@ uvwasi_errno_t uvwasi_sock_shutdown(uvwasi_t* uvwasi, uvwasi_sdflags_t how) { /* TODO(cjihrig): Waiting to implement, pending https://github.com/WebAssembly/WASI/issues/4 */ + DEBUG("uvwasi_sock_shutdown(uvwasi=%p, unimplemented)\n", uvwasi); return UVWASI_ENOTSUP; } diff --git a/deps/uvwasi/src/wasi_serdes.c b/deps/uvwasi/src/wasi_serdes.c new file mode 100644 index 00000000000000..96253fc5af0623 --- /dev/null +++ b/deps/uvwasi/src/wasi_serdes.c @@ -0,0 +1,259 @@ +#include "wasi_serdes.h" +#include "wasi_types.h" + +void uvwasi_serdes_write_uint64_t(void* ptr, + size_t offset, + uint64_t value) { + uvwasi_serdes_write_uint32_t(ptr, offset, (uint32_t) value); + uvwasi_serdes_write_uint32_t(ptr, offset + 4, value >> 32); +} + +void uvwasi_serdes_write_uint32_t(void* ptr, + size_t offset, + uint32_t value) { + uvwasi_serdes_write_uint16_t(ptr, offset, (uint16_t) value); + uvwasi_serdes_write_uint16_t(ptr, offset + 2, value >> 16); +} + +void uvwasi_serdes_write_uint16_t(void* ptr, + size_t offset, + uint16_t value) { + uvwasi_serdes_write_uint8_t(ptr, offset, (uint8_t) value); + uvwasi_serdes_write_uint8_t(ptr, offset + 1, value >> 8); +} + +void uvwasi_serdes_write_uint8_t(void* ptr, + size_t offset, + uint8_t value) { + ((uint8_t*) ptr)[offset] = value; +} + +uint64_t uvwasi_serdes_read_uint64_t(const void* ptr, size_t offset) { + uint64_t low = uvwasi_serdes_read_uint32_t(ptr, offset); + uint64_t high = uvwasi_serdes_read_uint32_t(ptr, offset + 4); + return low | (high << 32); +} + +uint32_t uvwasi_serdes_read_uint32_t(const void* ptr, size_t offset) { + uint32_t low = uvwasi_serdes_read_uint16_t(ptr, offset); + uint32_t high = uvwasi_serdes_read_uint16_t(ptr, offset + 2); + return low | (high << 16); +} + +uint16_t uvwasi_serdes_read_uint16_t(const void* ptr, size_t offset) { + uint16_t low = uvwasi_serdes_read_uint8_t(ptr, offset); + uint16_t high = uvwasi_serdes_read_uint8_t(ptr, offset + 1); + return low | (high << 8); +} + +uint8_t uvwasi_serdes_read_uint8_t(const void* ptr, size_t offset) { + return ((const uint8_t*) ptr)[offset]; +} + +#define TYPE_SWITCH switch (value->type) + +#define ALL_TYPES(STRUCT, FIELD, ALIAS) \ + \ + ALIAS(advice_t, uint8_t) \ + ALIAS(clockid_t, uint32_t) \ + ALIAS(device_t, uint64_t) \ + ALIAS(dircookie_t, uint64_t) \ + ALIAS(errno_t, uint16_t) \ + ALIAS(eventrwflags_t, uint16_t) \ + ALIAS(eventtype_t, uint8_t) \ + ALIAS(exitcode_t, uint32_t) \ + ALIAS(fd_t, uint32_t) \ + ALIAS(fdflags_t, uint16_t) \ + ALIAS(filesize_t, uint64_t) \ + ALIAS(filetype_t, uint8_t) \ + ALIAS(fstflags_t, uint16_t) \ + ALIAS(inode_t, uint64_t) \ + ALIAS(linkcount_t, uint64_t) \ + ALIAS(lookupflags_t, uint32_t) \ + ALIAS(oflags_t, uint16_t) \ + ALIAS(preopentype_t, uint8_t) \ + ALIAS(riflags_t, uint16_t) \ + ALIAS(rights_t, uint64_t) \ + ALIAS(roflags_t, uint16_t) \ + ALIAS(sdflags_t, uint8_t) \ + ALIAS(siflags_t, uint16_t) \ + ALIAS(signal_t, uint8_t) \ + ALIAS(size_t, uint32_t) \ + ALIAS(subclockflags_t, uint16_t) \ + ALIAS(timestamp_t, uint64_t) \ + ALIAS(userdata_t, uint64_t) \ + ALIAS(whence_t, uint8_t) \ + \ + STRUCT(fdstat_t) { \ + FIELD( 0, filetype_t, fs_filetype); \ + FIELD( 2, fdflags_t, fs_flags); \ + FIELD( 8, rights_t, fs_rights_base); \ + FIELD(16, rights_t, fs_rights_inheriting); \ + } \ + \ + STRUCT(filestat_t) { \ + FIELD( 0, device_t, st_dev); \ + FIELD( 8, inode_t, st_ino); \ + FIELD(16, filetype_t, st_filetype); \ + FIELD(24, linkcount_t, st_nlink); \ + FIELD(32, filesize_t, st_size); \ + FIELD(40, timestamp_t, st_atim); \ + FIELD(48, timestamp_t, st_mtim); \ + FIELD(56, timestamp_t, st_ctim); \ + } \ + \ + STRUCT(prestat_t) { \ + FIELD(0, preopentype_t, pr_type); \ + FIELD(4, uint32_t, u.dir.pr_name_len); \ + } \ + \ + STRUCT(event_t) { \ + FIELD( 0, userdata_t, userdata); \ + FIELD( 8, errno_t, error); \ + FIELD(10, eventtype_t, type); \ + TYPE_SWITCH { \ + case UVWASI_EVENTTYPE_FD_READ: \ + case UVWASI_EVENTTYPE_FD_WRITE: \ + FIELD(16, filesize_t, u.fd_readwrite.nbytes); \ + FIELD(24, eventrwflags_t, u.fd_readwrite.flags); \ + } \ + } \ + \ + STRUCT(subscription_t) { \ + FIELD(0, userdata_t, userdata); \ + FIELD(8, eventtype_t, type); \ + TYPE_SWITCH { \ + case UVWASI_EVENTTYPE_CLOCK: \ + FIELD(16, clockid_t, u.clock.clock_id); \ + FIELD(24, timestamp_t, u.clock.timeout); \ + FIELD(32, timestamp_t, u.clock.precision); \ + FIELD(40, subclockflags_t, u.clock.flags); \ + break; \ + case UVWASI_EVENTTYPE_FD_READ: \ + case UVWASI_EVENTTYPE_FD_WRITE: \ + FIELD(16, fd_t, u.fd_readwrite.fd); \ + } \ + } \ + +#define WRITE_STRUCT(name) \ + void uvwasi_serdes_write_##name(void* ptr, \ + size_t offset, \ + const uvwasi_##name* value) \ + +#define READ_STRUCT(name) \ + void uvwasi_serdes_read_##name(const void* ptr, \ + size_t offset, \ + uvwasi_##name* value) \ + +#define WRITE_FIELD(field_offset, type, field) \ + do { \ + uvwasi_serdes_write_##type(ptr, offset + field_offset, value->field); \ + } while (0) \ + +#define READ_FIELD(field_offset, type, field) \ + do { \ + value->field = uvwasi_serdes_read_##type(ptr, offset + field_offset); \ + } while (0) \ + +#define WRITE_ALIAS(new_name, old_name) \ + void uvwasi_serdes_write_##new_name(void* ptr, \ + size_t offset, \ + uvwasi_##new_name value) { \ + uvwasi_serdes_write_##old_name(ptr, offset, value); \ + } \ + +#define READ_ALIAS(new_name, old_name) \ + uvwasi_##new_name uvwasi_serdes_read_##new_name(const void* ptr, \ + size_t offset) { \ + return uvwasi_serdes_read_##old_name(ptr, offset); \ + } \ + +ALL_TYPES(WRITE_STRUCT, WRITE_FIELD, WRITE_ALIAS) +ALL_TYPES(READ_STRUCT, READ_FIELD, READ_ALIAS) + + +uvwasi_errno_t uvwasi_serdes_read_ciovec_t(const void* ptr, + size_t end, + size_t offset, + uvwasi_ciovec_t* value) { + uint32_t buf_ptr; + + buf_ptr = uvwasi_serdes_read_uint32_t(ptr, offset); + value->buf_len = uvwasi_serdes_read_size_t(ptr, offset + 4); + + if (!uvwasi_serdes_check_bounds(buf_ptr, end, value->buf_len)) + return UVWASI_EOVERFLOW; + + value->buf = ((uint8_t*) ptr + buf_ptr); + return UVWASI_ESUCCESS; +} + + +uvwasi_errno_t uvwasi_serdes_read_iovec_t(const void* ptr, + size_t end, + size_t offset, + uvwasi_iovec_t* value) { + uint32_t buf_ptr; + + buf_ptr = uvwasi_serdes_read_uint32_t(ptr, offset); + value->buf_len = uvwasi_serdes_read_size_t(ptr, offset + 4); + + if (!uvwasi_serdes_check_bounds(buf_ptr, end, value->buf_len)) + return UVWASI_EOVERFLOW; + + value->buf = ((uint8_t*) ptr + buf_ptr); + return UVWASI_ESUCCESS; +} + + +uvwasi_errno_t uvwasi_serdes_readv_ciovec_t(const void* ptr, + size_t end, + size_t offset, + uvwasi_ciovec_t* iovs, + uvwasi_size_t iovs_len) { + uvwasi_errno_t err; + uvwasi_size_t i; + + for (i = 0; i < iovs_len; i++) { + err = uvwasi_serdes_read_ciovec_t(ptr, end, offset, &iovs[i]); + if (err != UVWASI_ESUCCESS) + return err; + offset += UVWASI_SERDES_SIZE_ciovec_t; + } + + return UVWASI_ESUCCESS; +} + + +uvwasi_errno_t uvwasi_serdes_readv_iovec_t(const void* ptr, + size_t end, + size_t offset, + uvwasi_iovec_t* iovs, + uvwasi_size_t iovs_len) { + uvwasi_errno_t err; + uvwasi_size_t i; + + for (i = 0; i < iovs_len; i++) { + err = uvwasi_serdes_read_iovec_t(ptr, end, offset, &iovs[i]); + if (err != UVWASI_ESUCCESS) + return err; + offset += UVWASI_SERDES_SIZE_iovec_t; + } + + return UVWASI_ESUCCESS; +} + + +int uvwasi_serdes_check_bounds(size_t offset, size_t end, size_t size) { + return end > offset && size <= (end - offset); +} + + +int uvwasi_serdes_check_array_bounds(size_t offset, + size_t end, + size_t size, + size_t count) { + return end > offset && + ((count * size) / size == count) && + (count * size <= end - offset); +} diff --git a/deps/uvwasi/uvwasi.gyp b/deps/uvwasi/uvwasi.gyp index 42769095ecbafd..d4189eeee2fc94 100644 --- a/deps/uvwasi/uvwasi.gyp +++ b/deps/uvwasi/uvwasi.gyp @@ -12,9 +12,11 @@ 'src/clocks.c', 'src/fd_table.c', 'src/path_resolver.c', + 'src/poll_oneoff.c', 'src/uv_mapping.c', 'src/uvwasi.c', 'src/wasi_rights.c', + 'src/wasi_serdes.c', ], 'dependencies': [ '../uv/uv.gyp:libuv', diff --git a/deps/v8/.git-blame-ignore-revs b/deps/v8/.git-blame-ignore-revs index 5ae39770316425..4c53e208e3acec 100644 --- a/deps/v8/.git-blame-ignore-revs +++ b/deps/v8/.git-blame-ignore-revs @@ -23,3 +23,6 @@ e50b49a0e38b34e2b28e026f4d1c7e0da0c7bb1a # Rewrite code base to use "." instead of "->" to access Object members. 878ccb33bd3cf0e6dc018ff8d15843f585ac07be + +# Move test/mjsunit/regress-*.js => test/mjsunit/regress/ +cb67be1a3842fcf6a0da18aee444e3b7ea789e04 diff --git a/deps/v8/AUTHORS b/deps/v8/AUTHORS index 819d147096c496..7036ecd42bc461 100644 --- a/deps/v8/AUTHORS +++ b/deps/v8/AUTHORS @@ -77,11 +77,13 @@ Daniel Andersson Daniel Bevenius Daniel James David Carlier +David Manouchehri Deepak Mohan Deon Dior Dominic Farolini Douglas Crosher Dusan Milosavljevic +Eric Rannaud Erich Ocean Evan Lucas Fedor Indutny @@ -97,12 +99,14 @@ Henrique Ferreiro Hirofumi Mako Honggyu Kim Huáng Jùnliàng +Iain Ireland Ingvar Stepanyan Ioseb Dzmanashvili Isiah Meadows Jaime Bernardo Jan de Mooij Jan Krems +Janusz Majnert Jay Freeman James Pike James M Snell @@ -151,6 +155,7 @@ Oliver Dunk Paolo Giarrusso Patrick Gansterer Peng Fei +Peng-Yu Chen Peter Rybin Peter Varga Peter Wong @@ -195,6 +200,7 @@ Vladimir Krivosheev Vladimir Shutoff Wenlu Wang Wiktor Garbacz +Wouter Vermeiren Xiaoyin Liu Yannic Bonenberger Yong Wang diff --git a/deps/v8/BUILD.gn b/deps/v8/BUILD.gn index 13bf2b0fc344b4..b2dde3f9d70312 100644 --- a/deps/v8/BUILD.gn +++ b/deps/v8/BUILD.gn @@ -107,7 +107,7 @@ declare_args() { # Enable pointer compression (sets -dV8_COMPRESS_POINTERS). v8_enable_pointer_compression = "" - v8_enable_31bit_smis_on_64bit_arch = true + v8_enable_31bit_smis_on_64bit_arch = false # Sets -dOBJECT_PRINT. v8_enable_object_print = "" @@ -128,7 +128,7 @@ declare_args() { v8_enable_concurrent_marking = true # Sets -dV8_ARRAY_BUFFER_EXTENSION - v8_enable_array_buffer_extension = false + v8_enable_array_buffer_extension = true # Enables various testing features. v8_enable_test_features = "" @@ -211,6 +211,13 @@ declare_args() { # Enable additional targets necessary for verification of torque # file generation v8_verify_torque_generation_invariance = false + + # Disable all snapshot compression. + v8_enable_snapshot_compression = true + + # Enable control-flow integrity features, such as pointer authentication for + # ARM64. + v8_control_flow_integrity = false } # Derived defaults. @@ -270,6 +277,9 @@ assert(!v8_disable_write_barriers || v8_enable_single_generation, assert(v8_current_cpu != "x86" || !v8_untrusted_code_mitigations, "Untrusted code mitigations are unsupported on ia32") +assert(v8_current_cpu == "arm64" || !v8_control_flow_integrity, + "Control-flow integrity is only supported on arm64") + assert( !v8_enable_pointer_compression || !v8_enable_shared_ro_heap, "Pointer compression is not supported with shared read-only heap enabled") @@ -298,6 +308,7 @@ config("internal_config") { "//build/config/compiler:wexit_time_destructors", ":internal_config_base", ":v8_header_features", + ":v8_tracing_config", ] if (is_component_build) { @@ -305,6 +316,17 @@ config("internal_config") { } } +# Should be applied to all targets that write trace events. +config("v8_tracing_config") { + if (v8_use_perfetto) { + include_dirs = [ + "third_party/perfetto/include", + "$root_gen_dir/third_party/perfetto", + "$root_gen_dir/third_party/perfetto/build_config", + ] + } +} + # This config should be applied to code using the libplatform. config("libplatform_config") { include_dirs = [ "include" ] @@ -501,6 +523,15 @@ config("features") { if (v8_enable_regexp_interpreter_threaded_dispatch) { defines += [ "V8_ENABLE_REGEXP_INTERPRETER_THREADED_DISPATCH" ] } + if (v8_enable_snapshot_compression) { + defines += [ "V8_SNAPSHOT_COMPRESSION" ] + } + if (v8_control_flow_integrity) { + defines += [ "V8_ENABLE_CONTROL_FLOW_INTEGRITY" ] + } + if (v8_enable_wasm_gdb_remote_debugging) { + defines += [ "V8_ENABLE_WASM_GDB_REMOTE_DEBUGGING" ] + } } config("toolchain") { @@ -543,6 +574,12 @@ config("toolchain") { } if (v8_current_cpu == "arm64") { defines += [ "V8_TARGET_ARCH_ARM64" ] + if (v8_control_flow_integrity) { + # TODO(v8:10026): Enable this in src/build. + if (current_cpu == "arm64") { + cflags += [ "-mbranch-protection=standard" ] + } + } } # Mips64el/mipsel simulators. @@ -618,6 +655,7 @@ config("toolchain") { } if (v8_current_cpu == "s390" || v8_current_cpu == "s390x") { defines += [ "V8_TARGET_ARCH_S390" ] + cflags += [ "-ffp-contract=off" ] if (v8_current_cpu == "s390x") { defines += [ "V8_TARGET_ARCH_S390X" ] } @@ -628,8 +666,9 @@ config("toolchain") { } } if (v8_current_cpu == "ppc" || v8_current_cpu == "ppc64") { - defines += [ "V8_TARGET_ARCH_PPC" ] - if (v8_current_cpu == "ppc64") { + if (v8_current_cpu == "ppc") { + defines += [ "V8_TARGET_ARCH_PPC" ] + } else if (v8_current_cpu == "ppc64") { defines += [ "V8_TARGET_ARCH_PPC64" ] } if (host_byteorder == "little") { @@ -1138,11 +1177,14 @@ template("run_torque") { "bit-fields-tq.h", "builtin-definitions-tq.h", "interface-descriptors-tq.inc", + "factory-tq.cc", + "factory-tq.inc", "field-offsets-tq.h", "class-verifiers-tq.cc", "class-verifiers-tq.h", "enum-verifiers-tq.cc", "objects-printer-tq.cc", + "objects-body-descriptors-tq-inl.h", "class-definitions-tq.cc", "class-definitions-tq-inl.h", "class-definitions-tq.h", @@ -1264,6 +1306,7 @@ v8_source_set("torque_generated_definitions") { "$target_gen_dir/torque-generated/class-definitions-tq.cc", "$target_gen_dir/torque-generated/class-verifiers-tq.cc", "$target_gen_dir/torque-generated/class-verifiers-tq.h", + "$target_gen_dir/torque-generated/factory-tq.cc", "$target_gen_dir/torque-generated/objects-printer-tq.cc", ] @@ -1631,11 +1674,16 @@ v8_source_set("v8_initializers") { ### gcmole(arch:mips64el) ### "src/builtins/mips64/builtins-mips64.cc", ] - } else if (v8_current_cpu == "ppc" || v8_current_cpu == "ppc64") { + } else if (v8_current_cpu == "ppc") { sources += [ ### gcmole(arch:ppc) ### "src/builtins/ppc/builtins-ppc.cc", ] + } else if (v8_current_cpu == "ppc64") { + sources += [ + ### gcmole(arch:ppc64) ### + "src/builtins/ppc/builtins-ppc.cc", + ] } else if (v8_current_cpu == "s390" || v8_current_cpu == "s390x") { sources += [ ### gcmole(arch:s390) ### @@ -1684,6 +1732,7 @@ v8_header_set("v8_headers") { public_configs = [ ":v8_header_features" ] sources = [ + "include/v8-fast-api-calls.h", "include/v8-internal.h", "include/v8.h", "include/v8config.h", @@ -1865,7 +1914,6 @@ v8_compiler_sources = [ "src/compiler/memory-optimizer.cc", "src/compiler/memory-optimizer.h", "src/compiler/node-aux-data.h", - "src/compiler/node-cache.cc", "src/compiler/node-cache.h", "src/compiler/node-marker.cc", "src/compiler/node-marker.h", @@ -2005,6 +2053,7 @@ v8_source_set("v8_base_without_compiler") { ### gcmole(all) ### "$target_gen_dir/builtins-generated/bytecodes-builtins-list.h", + "include/v8-fast-api-calls.h", "include/v8-inspector-protocol.h", "include/v8-inspector.h", "include/v8-internal.h", @@ -2235,6 +2284,9 @@ v8_source_set("v8_base_without_compiler") { "src/execution/messages.h", "src/execution/microtask-queue.cc", "src/execution/microtask-queue.h", + "src/execution/off-thread-isolate.cc", + "src/execution/off-thread-isolate.h", + "src/execution/pointer-authentication.h", "src/execution/protectors-inl.h", "src/execution/protectors.cc", "src/execution/protectors.h", @@ -2273,6 +2325,9 @@ v8_source_set("v8_base_without_compiler") { "src/handles/handles-inl.h", "src/handles/handles.cc", "src/handles/handles.h", + "src/handles/local-handles-inl.h", + "src/handles/local-handles.cc", + "src/handles/local-handles.h", "src/handles/maybe-handles-inl.h", "src/handles/maybe-handles.h", "src/heap/array-buffer-collector.cc", @@ -2298,8 +2353,8 @@ v8_source_set("v8_base_without_compiler") { "src/heap/factory-inl.h", "src/heap/factory.cc", "src/heap/factory.h", - "src/heap/finalization-group-cleanup-task.cc", - "src/heap/finalization-group-cleanup-task.h", + "src/heap/finalization-registry-cleanup-task.cc", + "src/heap/finalization-registry-cleanup-task.h", "src/heap/gc-idle-time-handler.cc", "src/heap/gc-idle-time-handler.h", "src/heap/gc-tracer.cc", @@ -2323,6 +2378,8 @@ v8_source_set("v8_base_without_compiler") { "src/heap/item-parallel-job.h", "src/heap/local-allocator-inl.h", "src/heap/local-allocator.h", + "src/heap/local-heap.cc", + "src/heap/local-heap.h", "src/heap/mark-compact-inl.h", "src/heap/mark-compact.cc", "src/heap/mark-compact.h", @@ -2348,6 +2405,8 @@ v8_source_set("v8_base_without_compiler") { "src/heap/read-only-heap.cc", "src/heap/read-only-heap.h", "src/heap/remembered-set.h", + "src/heap/safepoint.cc", + "src/heap/safepoint.h", "src/heap/scavenge-job.cc", "src/heap/scavenge-job.h", "src/heap/scavenger-inl.h", @@ -2448,6 +2507,7 @@ v8_source_set("v8_base_without_compiler") { "src/logging/log-utils.h", "src/logging/log.cc", "src/logging/log.h", + "src/logging/off-thread-logger.h", "src/numbers/bignum-dtoa.cc", "src/numbers/bignum-dtoa.h", "src/numbers/bignum.cc", @@ -2690,6 +2750,7 @@ v8_source_set("v8_base_without_compiler") { "src/objects/tagged-impl-inl.h", "src/objects/tagged-impl.cc", "src/objects/tagged-impl.h", + "src/objects/tagged-index.h", "src/objects/tagged-value-inl.h", "src/objects/tagged-value.h", "src/objects/template-objects-inl.h", @@ -2775,6 +2836,8 @@ v8_source_set("v8_base_without_compiler") { "src/regexp/regexp-compiler.h", "src/regexp/regexp-dotprinter.cc", "src/regexp/regexp-dotprinter.h", + "src/regexp/regexp-error.cc", + "src/regexp/regexp-error.h", "src/regexp/regexp-interpreter.cc", "src/regexp/regexp-interpreter.h", "src/regexp/regexp-macro-assembler-arch.h", @@ -2860,6 +2923,8 @@ v8_source_set("v8_base_without_compiler") { "src/snapshot/serializer.cc", "src/snapshot/serializer.h", "src/snapshot/snapshot-common.cc", + "src/snapshot/snapshot-compression.cc", + "src/snapshot/snapshot-compression.h", "src/snapshot/snapshot-source-sink.cc", "src/snapshot/snapshot-source-sink.h", "src/snapshot/snapshot.h", @@ -2966,6 +3031,8 @@ v8_source_set("v8_base_without_compiler") { "src/wasm/wasm-code-manager.cc", "src/wasm/wasm-code-manager.h", "src/wasm/wasm-constants.h", + "src/wasm/wasm-debug-evaluate.cc", + "src/wasm/wasm-debug-evaluate.h", "src/wasm/wasm-debug.cc", "src/wasm/wasm-engine.cc", "src/wasm/wasm-engine.h", @@ -3012,10 +3079,30 @@ v8_source_set("v8_base_without_compiler") { "src/zone/zone.h", ] + if (!v8_control_flow_integrity) { + sources += [ "src/execution/pointer-authentication-dummy.h" ] + } + if (v8_enable_third_party_heap) { sources += v8_third_party_heap_files } + if (v8_enable_wasm_gdb_remote_debugging) { + sources += [ + "src/debug/wasm/gdb-server/gdb-server-thread.cc", + "src/debug/wasm/gdb-server/gdb-server-thread.h", + "src/debug/wasm/gdb-server/gdb-server.cc", + "src/debug/wasm/gdb-server/gdb-server.h", + "src/debug/wasm/gdb-server/session.cc", + "src/debug/wasm/gdb-server/session.h", + "src/debug/wasm/gdb-server/target.cc", + "src/debug/wasm/gdb-server/target.h", + "src/debug/wasm/gdb-server/transport.cc", + "src/debug/wasm/gdb-server/transport.h", + "src/debug/wasm/gdb-server/util.h", + ] + } + if (v8_check_header_includes) { # This file will be generated by tools/generate-header-include-checks.py # if the "check_v8_header_includes" gclient variable is set. @@ -3169,6 +3256,9 @@ v8_source_set("v8_base_without_compiler") { "src/regexp/arm64/regexp-macro-assembler-arm64.h", "src/wasm/baseline/arm64/liftoff-assembler-arm64.h", ] + if (v8_control_flow_integrity) { + sources += [ "src/execution/arm64/pointer-authentication-arm64.h" ] + } if (is_win) { sources += [ "src/diagnostics/unwinding-info-win64.cc", @@ -3229,7 +3319,7 @@ v8_source_set("v8_base_without_compiler") { "src/regexp/mips64/regexp-macro-assembler-mips64.h", "src/wasm/baseline/mips64/liftoff-assembler-mips64.h", ] - } else if (v8_current_cpu == "ppc" || v8_current_cpu == "ppc64") { + } else if (v8_current_cpu == "ppc") { sources += [ ### gcmole(arch:ppc) ### "src/codegen/ppc/assembler-ppc-inl.h", "src/codegen/ppc/assembler-ppc.cc", @@ -3259,6 +3349,36 @@ v8_source_set("v8_base_without_compiler") { "src/regexp/ppc/regexp-macro-assembler-ppc.h", "src/wasm/baseline/ppc/liftoff-assembler-ppc.h", ] + } else if (v8_current_cpu == "ppc64") { + sources += [ ### gcmole(arch:ppc64) ### + "src/codegen/ppc/assembler-ppc-inl.h", + "src/codegen/ppc/assembler-ppc.cc", + "src/codegen/ppc/assembler-ppc.h", + "src/codegen/ppc/constants-ppc.cc", + "src/codegen/ppc/constants-ppc.h", + "src/codegen/ppc/cpu-ppc.cc", + "src/codegen/ppc/interface-descriptors-ppc.cc", + "src/codegen/ppc/macro-assembler-ppc.cc", + "src/codegen/ppc/macro-assembler-ppc.h", + "src/codegen/ppc/register-ppc.h", + "src/compiler/backend/ppc/code-generator-ppc.cc", + "src/compiler/backend/ppc/instruction-codes-ppc.h", + "src/compiler/backend/ppc/instruction-scheduler-ppc.cc", + "src/compiler/backend/ppc/instruction-selector-ppc.cc", + "src/compiler/backend/ppc/unwinding-info-writer-ppc.cc", + "src/compiler/backend/ppc/unwinding-info-writer-ppc.h", + "src/debug/ppc/debug-ppc.cc", + "src/deoptimizer/ppc/deoptimizer-ppc.cc", + "src/diagnostics/ppc/disasm-ppc.cc", + "src/diagnostics/ppc/eh-frame-ppc.cc", + "src/execution/ppc/frame-constants-ppc.cc", + "src/execution/ppc/frame-constants-ppc.h", + "src/execution/ppc/simulator-ppc.cc", + "src/execution/ppc/simulator-ppc.h", + "src/regexp/ppc/regexp-macro-assembler-ppc.cc", + "src/regexp/ppc/regexp-macro-assembler-ppc.h", + "src/wasm/baseline/ppc/liftoff-assembler-ppc.h", + ] } else if (v8_current_cpu == "s390" || v8_current_cpu == "s390x") { sources += [ ### gcmole(arch:s390) ### "src/codegen/s390/assembler-s390-inl.h", @@ -3359,7 +3479,10 @@ v8_source_set("v8_base_without_compiler") { ] } - deps += [ "//third_party/zlib" ] + deps += [ + "//third_party/zlib", + "//third_party/zlib/google:compression_utils_portable", + ] if (v8_postmortem_support) { sources += [ "$target_gen_dir/debug-support.cc" ] @@ -3521,6 +3644,7 @@ v8_component("v8_libbase") { "src/base/atomicops_internals_std.h", "src/base/base-export.h", "src/base/bit-field.h", + "src/base/bits-iterator.h", "src/base/bits.cc", "src/base/bits.h", "src/base/bounded-page-allocator.cc", @@ -3799,6 +3923,47 @@ v8_source_set("fuzzer_support") { ] } +v8_source_set("cppgc_base") { + visibility = [ ":*" ] + + sources = [ + "include/cppgc/allocation.h", + "include/cppgc/api-constants.h", + "include/cppgc/finalizer-trait.h", + "include/cppgc/garbage-collected.h", + "include/cppgc/gc-info.h", + "include/cppgc/heap.h", + "include/cppgc/platform.h", + "include/v8config.h", + "src/heap/cppgc/allocation.cc", + "src/heap/cppgc/gc-info-table.cc", + "src/heap/cppgc/gc-info-table.h", + "src/heap/cppgc/gc-info.cc", + "src/heap/cppgc/heap-inl.h", + "src/heap/cppgc/heap-object-header-inl.h", + "src/heap/cppgc/heap-object-header.cc", + "src/heap/cppgc/heap-object-header.h", + "src/heap/cppgc/heap.cc", + "src/heap/cppgc/heap.h", + "src/heap/cppgc/platform.cc", + "src/heap/cppgc/sanitizers.h", + "src/heap/cppgc/stack.cc", + "src/heap/cppgc/stack.h", + ] + + if (target_cpu == "x64") { + if (is_win) { + sources += [ "src/heap/cppgc/asm/x64/push_registers_win.S" ] + } else { + sources += [ "src/heap/cppgc/asm/x64/push_registers.S" ] + } + } + + configs = [ ":internal_config" ] + + public_deps = [ ":v8_libbase" ] +} + ############################################################################### # Produce a single static library for embedders # @@ -3845,6 +4010,12 @@ v8_static_library("wee8") { ] } +v8_static_library("cppgc") { + deps = [ ":cppgc_base" ] + + configs = [ ":internal_config" ] +} + ############################################################################### # Executables # @@ -4076,7 +4247,7 @@ group("v8_archive") { if (is_fuchsia && !build_with_chromium) { import("//build/config/fuchsia/rules.gni") - fuchsia_package("d8_fuchsia_pkg") { + cr_fuchsia_package("d8_fuchsia_pkg") { testonly = true binary = ":d8" package_name_override = "d8" @@ -4136,6 +4307,15 @@ if (is_component_build) { public_configs = [ ":external_config" ] } + + v8_component("cppgc_for_testing") { + testonly = true + + public_deps = [ ":cppgc_base" ] + + configs = [ ":internal_config" ] + public_configs = [ ":external_config" ] + } } else { group("v8") { public_deps = [ @@ -4159,6 +4339,14 @@ if (is_component_build) { public_configs = [ ":external_config" ] } + + group("cppgc_for_testing") { + testonly = true + + public_deps = [ ":cppgc_base" ] + + public_configs = [ ":external_config" ] + } } v8_executable("d8") { @@ -4179,6 +4367,7 @@ v8_executable("d8") { # the :external_config applied to it by virtue of depending on :v8, and # you can't have both applied to the same target. ":internal_config_base", + ":v8_tracing_config", ] deps = [ @@ -4205,7 +4394,7 @@ v8_executable("d8") { } if (v8_use_perfetto) { - deps += [ "//third_party/perfetto/include/perfetto/tracing" ] + deps += [ "//third_party/perfetto/src/tracing:in_process_backend" ] } } diff --git a/deps/v8/COMMON_OWNERS b/deps/v8/COMMON_OWNERS index cf53fe80e0bad7..1eee48173a1576 100644 --- a/deps/v8/COMMON_OWNERS +++ b/deps/v8/COMMON_OWNERS @@ -29,9 +29,11 @@ petermarshall@chromium.org rmcilroy@chromium.org sigurds@chromium.org solanes@chromium.org +syg@chromium.org szuend@chromium.org tebbi@chromium.org -titzer@chromium.org ulan@chromium.org verwaest@chromium.org +victorgomes@chromium.org yangguo@chromium.org +zhin@chromium.org diff --git a/deps/v8/DEPS b/deps/v8/DEPS index 880ff6c4b82d59..1bc687beaf6ead 100644 --- a/deps/v8/DEPS +++ b/deps/v8/DEPS @@ -4,13 +4,9 @@ gclient_gn_args_file = 'v8/build/config/gclient_args.gni' gclient_gn_args = [ - 'checkout_aemu' ] vars = { - # By Default, do not checkout AEMU, as it is too big, as is done in Chromium. - 'checkout_aemu': False, - # Fetches only the SDK boot images which match at least one of the whitelist # entries in a comma-separated list. # @@ -35,10 +31,10 @@ vars = { 'check_v8_header_includes': False, # GN CIPD package version. - 'gn_version': 'git_revision:97cc440d84f050f99ff0161f9414bfa2ffa38f65', + 'gn_version': 'git_revision:5ed3c9cc67b090d5e311e4bd2aba072173e82db9', # luci-go CIPD package version. - 'luci_go': 'git_revision:37a855b64d59b7f079c9a0e5368f2757099d14d3', + 'luci_go': 'git_revision:de73cf6c4bde86f0a9c8d54151b69b0154a398f1', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling android_sdk_build-tools_version @@ -69,10 +65,6 @@ vars = { # and whatever else without interference from each other. 'android_sdk_sources_version': '4gxhM8E62bvZpQs7Q3d0DinQaW0RLCIefhXrQBFkNy8C', # Three lines of non-changing comments so that - # the commit queue can handle CLs rolling android_sdk_tools_version - # and whatever else without interference from each other. - 'android_sdk_tools_version': 'wYcRQC2WHsw2dKWs4EA7fw9Qsyzu1ds1_fRjKmGxe5QC', - # Three lines of non-changing comments so that # the commit queue can handle CLs rolling android_sdk_tools-lint_version # and whatever else without interference from each other. 'android_sdk_tools-lint_version': '89hXqZYzCum3delB5RV7J_QyWkaRodqdtQS0s3LMh3wC', @@ -80,15 +72,15 @@ vars = { deps = { 'v8/build': - Var('chromium_url') + '/chromium/src/build.git' + '@' + '2f17606c25956e800b6c4670c294a03620e78551', + Var('chromium_url') + '/chromium/src/build.git' + '@' + '26e9d485d01d6e0eb9dadd21df767a63494c8fea', 'v8/third_party/depot_tools': - Var('chromium_url') + '/chromium/tools/depot_tools.git' + '@' + 'ea8b58b970c0c94b4a36270b806ee307547cd77e', + Var('chromium_url') + '/chromium/tools/depot_tools.git' + '@' + '2b2aec6506a810f8d7bd018609de2c2450b3c121', 'v8/third_party/icu': - Var('chromium_url') + '/chromium/deps/icu.git' + '@' + 'dbd3825b31041d782c5b504c59dcfb5ac7dda08c', + Var('chromium_url') + '/chromium/deps/icu.git' + '@' + 'd7aff76cf6bb0fbef3afa6c07718f78a80a70f8f', 'v8/third_party/instrumented_libraries': Var('chromium_url') + '/chromium/src/third_party/instrumented_libraries.git' + '@' + 'bb3f1802c237dd19105dd0f7919f99e536a39d10', 'v8/buildtools': - Var('chromium_url') + '/chromium/src/buildtools.git' + '@' + 'afc5b798c72905e85f9991152be878714c579958', + Var('chromium_url') + '/chromium/src/buildtools.git' + '@' + '7977eb176752aeec29d888cfe8e677ac12ed1c41', 'v8/buildtools/clang_format/script': Var('chromium_url') + '/chromium/llvm-project/cfe/tools/clang-format.git' + '@' + '96636aa0e9f047f17447f2d45a094d0b59ed7917', 'v8/buildtools/linux64': { @@ -112,11 +104,11 @@ deps = { 'condition': 'host_os == "mac"', }, 'v8/buildtools/third_party/libc++/trunk': - Var('chromium_url') + '/chromium/llvm-project/libcxx.git' + '@' + '78d6a7767ed57b50122a161b91f59f19c9bd0d19', + Var('chromium_url') + '/external/github.com/llvm/llvm-project/libcxx.git' + '@' + 'd9040c75cfea5928c804ab7c235fed06a63f743a', 'v8/buildtools/third_party/libc++abi/trunk': - Var('chromium_url') + '/chromium/llvm-project/libcxxabi.git' + '@' + '0d529660e32d77d9111912d73f2c74fc5fa2a858', + Var('chromium_url') + '/external/github.com/llvm/llvm-project/libcxxabi.git' + '@' + '196ba1aaa8ac285d94f4ea8d9836390a45360533', 'v8/buildtools/third_party/libunwind/trunk': - Var('chromium_url') + '/external/llvm.org/libunwind.git' + '@' + '69d9b84cca8354117b9fe9705a4430d789ee599b', + Var('chromium_url') + '/external/github.com/llvm/llvm-project/libunwind.git' + '@' + '43bb9f872232f531bac80093ceb4de61c64b9ab7', 'v8/buildtools/win': { 'packages': [ { @@ -128,7 +120,7 @@ deps = { 'condition': 'host_os == "win"', }, 'v8/base/trace_event/common': - Var('chromium_url') + '/chromium/src/base/trace_event/common.git' + '@' + 'bd79231eb1f9e7de2efb4ad79e530d9a7e70d9a5', + Var('chromium_url') + '/chromium/src/base/trace_event/common.git' + '@' + 'dab187b372fc17e51f5b9fad8201813d0aed5129', 'v8/third_party/android_ndk': { 'url': Var('chromium_url') + '/android_ndk.git' + '@' + '27c0a8d090c666a50e40fceb4ee5b40b1a2d3f87', 'condition': 'checkout_android', @@ -167,10 +159,6 @@ deps = { 'package': 'chromium/third_party/android_sdk/public/sources/android-29', 'version': Var('android_sdk_sources_version'), }, - { - 'package': 'chromium/third_party/android_sdk/public/tools', - 'version': Var('android_sdk_tools_version'), - }, { 'package': 'chromium/third_party/android_sdk/public/tools-lint', 'version': Var('android_sdk_tools-lint_version'), @@ -180,7 +168,7 @@ deps = { 'dep_type': 'cipd', }, 'v8/third_party/catapult': { - 'url': Var('chromium_url') + '/catapult.git' + '@' + '2e0a0cb9ad546be8c835e65d7537507cb7896e03', + 'url': Var('chromium_url') + '/catapult.git' + '@' + '032c78376792ef343ea361bca2181ba6dec6b95f', 'condition': 'checkout_android', }, 'v8/third_party/colorama/src': { @@ -188,23 +176,23 @@ deps = { 'condition': 'checkout_android', }, 'v8/third_party/fuchsia-sdk': { - 'url': Var('chromium_url') + '/chromium/src/third_party/fuchsia-sdk.git' + '@' + '19c8ac5e150fbd147ec5987425a41aa9e97098b2', + 'url': Var('chromium_url') + '/chromium/src/third_party/fuchsia-sdk.git' + '@' + '2457e41d8dc379f74662d3157e76339ba92cee06', 'condition': 'checkout_fuchsia', }, 'v8/third_party/googletest/src': - Var('chromium_url') + '/external/github.com/google/googletest.git' + '@' + '306f3754a71d6d1ac644681d3544d06744914228', + Var('chromium_url') + '/external/github.com/google/googletest.git' + '@' + '10b1902d893ea8cc43c69541d70868f91af3646b', 'v8/third_party/jinja2': Var('chromium_url') + '/chromium/src/third_party/jinja2.git' + '@' + 'b41863e42637544c2941b574c7877d3e1f663e25', 'v8/third_party/markupsafe': Var('chromium_url') + '/chromium/src/third_party/markupsafe.git' + '@' + '8f45f5cfa0009d2a70589bcda0349b8cb2b72783', 'v8/tools/swarming_client': - Var('chromium_url') + '/infra/luci/client-py.git' + '@' + '885b3febcc170a60f25795304e60927b77d1e92d', + Var('chromium_url') + '/infra/luci/client-py.git' + '@' + 'cc958279ffd6853e0a1b227a7e957ca334fe56af', 'v8/test/benchmarks/data': Var('chromium_url') + '/v8/deps/third_party/benchmarks.git' + '@' + '05d7188267b4560491ff9155c5ee13e207ecd65f', 'v8/test/mozilla/data': Var('chromium_url') + '/v8/deps/third_party/mozilla-tests.git' + '@' + 'f6c578a10ea707b1a8ab0b88943fe5115ce2b9be', 'v8/test/test262/data': - Var('chromium_url') + '/external/github.com/tc39/test262.git' + '@' + '28b4fcca4b1b1d278dfe0cc0e69c7d9d59b31aab', + Var('chromium_url') + '/external/github.com/tc39/test262.git' + '@' + 'f6b2ccdd091ff82da54150796297c3a96d7edb41', 'v8/test/test262/harness': Var('chromium_url') + '/external/github.com/test262-utils/test262-harness-py.git' + '@' + '4555345a943d0c99a9461182705543fb171dda4b', 'v8/third_party/qemu-linux-x64': { @@ -227,8 +215,28 @@ deps = { 'condition': 'host_os == "mac" and checkout_fuchsia', 'dep_type': 'cipd', }, + 'v8/third_party/aemu-linux-x64': { + 'packages': [ + { + 'package': 'fuchsia/third_party/aemu/linux-amd64', + 'version': '7YlCgase5GlIanqHn-nZClSlZ5kQETJyVUYRF7Jjy6UC' + }, + ], + 'condition': 'host_os == "linux" and checkout_fuchsia', + 'dep_type': 'cipd', + }, + 'v8/third_party/aemu-mac-x64': { + 'packages': [ + { + 'package': 'fuchsia/third_party/aemu/mac-amd64', + 'version': 'T9bWxf8aUC5TwCFgPxpuW29Mfy-7Z9xCfXB9QO8MfU0C' + }, + ], + 'condition': 'host_os == "mac" and checkout_fuchsia', + 'dep_type': 'cipd', + }, 'v8/tools/clang': - Var('chromium_url') + '/chromium/src/tools/clang.git' + '@' + '535dbf16a84c7fc238f7ed11b5a75381407e38f6', + Var('chromium_url') + '/chromium/src/tools/clang.git' + '@' + '105a8460911176861a422738eee4daad8dfe88a2', 'v8/tools/luci-go': { 'packages': [ { @@ -258,11 +266,11 @@ deps = { 'dep_type': 'cipd', }, 'v8/third_party/perfetto': - Var('android_url') + '/platform/external/perfetto.git' + '@' + '12dc10e0278cded35205cf84f80a821348cb6c56', + Var('android_url') + '/platform/external/perfetto.git' + '@' + 'b9b24d1b0b80aafec393af085067e9eae829412f', 'v8/third_party/protobuf': Var('chromium_url') + '/external/github.com/google/protobuf'+ '@' + 'b68a347f56137b4b1a746e8c7438495a6ac1bd91', 'v8/third_party/zlib': - Var('chromium_url') + '/chromium/src/third_party/zlib.git'+ '@' + 'b9b9a5af7cca2e683e5f2aead8418e5bf9d5a7d5', + Var('chromium_url') + '/chromium/src/third_party/zlib.git'+ '@' + '156be8c52f80cde343088b4a69a80579101b6e67', 'v8/third_party/ittapi': { # Force checkout ittapi libraries to pass v8 header includes check on # bots that has check_v8_header_includes enabled. diff --git a/deps/v8/base/trace_event/common/trace_event_common.h b/deps/v8/base/trace_event/common/trace_event_common.h index 3f741d816f722d..a7bffbdbeb44c7 100644 --- a/deps/v8/base/trace_event/common/trace_event_common.h +++ b/deps/v8/base/trace_event/common/trace_event_common.h @@ -61,28 +61,30 @@ // current process id, thread id, and a timestamp in microseconds. // // To trace an asynchronous procedure such as an IPC send/receive, use -// ASYNC_BEGIN and ASYNC_END: +// NESTABLE_ASYNC_BEGIN and NESTABLE_ASYNC_END: // [single threaded sender code] // static int send_count = 0; // ++send_count; -// TRACE_EVENT_ASYNC_BEGIN0("ipc", "message", send_count); +// TRACE_EVENT_NESTABLE_ASYNC_BEGIN0( +// "ipc", "message", TRACE_ID_LOCAL(send_count)); // Send(new MyMessage(send_count)); // [receive code] // void OnMyMessage(send_count) { -// TRACE_EVENT_ASYNC_END0("ipc", "message", send_count); +// TRACE_NESTABLE_EVENT_ASYNC_END0( +// "ipc", "message", TRACE_ID_LOCAL(send_count)); // } -// The third parameter is a unique ID to match ASYNC_BEGIN/ASYNC_END pairs. -// ASYNC_BEGIN and ASYNC_END can occur on any thread of any traced process. -// Pointers can be used for the ID parameter, and they will be annotated -// internally so that the same pointer on two different processes will not -// match. For example: +// The third parameter is a unique ID to match NESTABLE_ASYNC_BEGIN/ASYNC_END +// pairs. NESTABLE_ASYNC_BEGIN and ASYNC_END can occur on any thread of any +// traced process. // Pointers can be used for the ID parameter, and they will +// be annotated internally so that the same pointer on two different processes +// will not match. For example: // class MyTracedClass { // public: // MyTracedClass() { -// TRACE_EVENT_ASYNC_BEGIN0("category", "MyTracedClass", this); +// TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("category", "MyTracedClass", this); // } // ~MyTracedClass() { -// TRACE_EVENT_ASYNC_END0("category", "MyTracedClass", this); +// TRACE_EVENT_NESTABLE_ASYNC_END0("category", "MyTracedClass", this); // } // } // @@ -512,9 +514,11 @@ name, id, TRACE_EVENT_FLAG_NONE, arg1_name, \ arg1_val) -// ASYNC_STEP_* APIs should be only used by legacy code. New code should -// consider using NESTABLE_ASYNC_* APIs to describe substeps within an async -// event. +// -- TRACE_EVENT_ASYNC is DEPRECATED! -- +// +// TRACE_EVENT_ASYNC_* APIs should be only used by legacy code. New code should +// use TRACE_EVENT_NESTABLE_ASYNC_* APIs instead. +// // Records a single ASYNC_BEGIN event called "name" immediately, with 0, 1 or 2 // associated arguments. If the category is not enabled, then this // does nothing. @@ -566,9 +570,6 @@ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \ TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, \ TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, arg2_name, arg2_val) -#define TRACE_EVENT_ASYNC_BEGIN_WITH_FLAGS0(category_group, name, id, flags) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ - category_group, name, id, flags) // Similar to TRACE_EVENT_ASYNC_BEGINx but with a custom |at| timestamp // provided. @@ -595,11 +596,6 @@ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, \ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_COPY) -#define TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP_AND_FLAGS0( \ - category_group, name, id, timestamp, flags) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, \ - TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, flags) // Records a single ASYNC_STEP_INTO event for |step| immediately. If the // category is not enabled, then this does nothing. The |name| and |id| must @@ -671,9 +667,6 @@ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \ TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, \ TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, arg2_name, arg2_val) -#define TRACE_EVENT_ASYNC_END_WITH_FLAGS0(category_group, name, id, flags) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ - category_group, name, id, flags) // Similar to TRACE_EVENT_ASYNC_ENDx but with a custom |at| timestamp provided. #define TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP0(category_group, name, id, \ @@ -699,11 +692,6 @@ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, \ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_COPY) -#define TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP_AND_FLAGS0(category_group, name, \ - id, timestamp, flags) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, \ - TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, flags) // NESTABLE_ASYNC_* APIs are used to describe an async operation, which can // be nested within a NESTABLE_ASYNC event and/or have inner NESTABLE_ASYNC @@ -742,6 +730,10 @@ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \ TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, category_group, name, id, \ TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val) +#define TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_FLAGS0(category_group, name, id, \ + flags) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, \ + category_group, name, id, flags) // Records a single NESTABLE_ASYNC_END event called "name" immediately, with 0 // or 2 associated arguments. If the category is not enabled, then this does // nothing. @@ -761,6 +753,10 @@ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \ TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, category_group, name, id, \ TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val) +#define TRACE_EVENT_NESTABLE_ASYNC_END_WITH_FLAGS0(category_group, name, id, \ + flags) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, \ + category_group, name, id, flags) // Records a single NESTABLE_ASYNC_INSTANT event called "name" immediately, // with none, one or two associated argument. If the category is not enabled, @@ -808,6 +804,11 @@ TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, category_group, name, id, \ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, \ arg1_name, arg1_val) +#define TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP_AND_FLAGS0( \ + category_group, name, id, timestamp, flags) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ + TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, category_group, name, id, \ + TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, flags) #define TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(category_group, name, \ id, timestamp) \ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ @@ -826,6 +827,11 @@ TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, category_group, name, id, \ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, \ arg1_name, arg1_val, arg2_name, arg2_val) +#define TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP_AND_FLAGS0( \ + category_group, name, id, timestamp, flags) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ + TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, category_group, name, id, \ + TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, flags) #define TRACE_EVENT_NESTABLE_ASYNC_INSTANT_WITH_TIMESTAMP0( \ category_group, name, id, timestamp) \ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ diff --git a/deps/v8/gni/proto_library.gni b/deps/v8/gni/proto_library.gni index b16d8f93bd8fcd..eca3ffb84e55ac 100644 --- a/deps/v8/gni/proto_library.gni +++ b/deps/v8/gni/proto_library.gni @@ -124,9 +124,13 @@ template("proto_library") { rebase_path(proto_in_dir, root_build_dir), ] if (generate_cc) { + cc_generator_options_ = "" + if (defined(invoker.cc_generator_options)) { + cc_generator_options_ = invoker.cc_generator_options + } args += [ "--cpp_out", - rel_cc_out_dir, + cc_generator_options_ + rel_cc_out_dir, ] } if (generate_descriptor != "") { @@ -153,13 +157,9 @@ template("proto_library") { args += rebase_path(proto_sources, root_build_dir) - inputs = [ - protoc_path, - ] + inputs = [ protoc_path ] - deps = [ - protoc_label, - ] + deps = [ protoc_label ] if (generate_with_plugin) { inputs += [ plugin_path ] if (defined(plugin_host_label)) { @@ -201,21 +201,23 @@ template("proto_library") { public_configs = [] } - public_configs += [ - "//:protobuf_gen_config", - ":$config_name", - ] + public_configs += [ "//:protobuf_gen_config" ] + + propagate_imports_configs = !defined(invoker.propagate_imports_configs) || + invoker.propagate_imports_configs + if (propagate_imports_configs) { + public_configs += [ ":$config_name" ] + } else { + # Embedder handles include directory propagation to dependents. + configs += [ ":$config_name" ] + } # Use protobuf_full only for tests. if (defined(invoker.use_protobuf_full) && invoker.use_protobuf_full == true) { - deps = [ - "//:protobuf_full", - ] + deps = [ "//:protobuf_full" ] } else { - deps = [ - "//:protobuf_lite", - ] + deps = [ "//:protobuf_lite" ] } deps += [ ":$action_name" ] diff --git a/deps/v8/gni/v8.gni b/deps/v8/gni/v8.gni index eaf76a471b3395..0b2806ca949b77 100644 --- a/deps/v8/gni/v8.gni +++ b/deps/v8/gni/v8.gni @@ -57,6 +57,12 @@ declare_args() { # Use Perfetto (https://perfetto.dev) as the default TracingController. Not # currently implemented. v8_use_perfetto = false + + # Override global symbol level setting for v8 + v8_symbol_level = symbol_level + + # Enable WebAssembly debugging via GDB-remote protocol. + v8_enable_wasm_gdb_remote_debugging = false } if (v8_use_external_startup_data == "") { @@ -109,6 +115,13 @@ if (is_debug && !v8_optimized_debug) { } } +if (!is_debug) { + v8_remove_configs += [ + # Too much performance impact, unclear security benefit. + "//build/config/compiler:default_init_stack_vars", + ] +} + if (v8_code_coverage && !is_clang) { v8_add_configs += [ v8_path_prefix + ":v8_gcov_coverage_cflags", @@ -116,6 +129,19 @@ if (v8_code_coverage && !is_clang) { ] } +if (v8_symbol_level != symbol_level) { + v8_remove_configs += [ "//build/config/compiler:default_symbols" ] + if (v8_symbol_level == 0) { + v8_add_configs += [ "//build/config/compiler:no_symbols" ] + } else if (v8_symbol_level == 1) { + v8_add_configs += [ "//build/config/compiler:minimal_symbols" ] + } else if (v8_symbol_level == 2) { + v8_add_configs += [ "//build/config/compiler:symbols" ] + } else { + assert(false) + } +} + if ((is_posix || is_fuchsia) && (v8_enable_backtrace || v8_monolithic || v8_expose_symbols)) { v8_remove_configs += [ "//build/config/gcc:symbol_visibility_hidden" ] @@ -217,6 +243,25 @@ template("v8_component") { } } +template("v8_shared_library") { + shared_library(target_name) { + forward_variables_from(invoker, + "*", + [ + "configs", + "remove_configs", + ]) + configs -= v8_remove_configs + configs += v8_add_configs + if (defined(invoker.remove_configs)) { + configs -= invoker.remove_configs + } + if (defined(invoker.configs)) { + configs += invoker.configs + } + } +} + template("v8_static_library") { static_library(target_name) { complete_static_lib = true diff --git a/deps/v8/include/OWNERS b/deps/v8/include/OWNERS index 1e0794df7a2796..4f90a5c8c70692 100644 --- a/deps/v8/include/OWNERS +++ b/deps/v8/include/OWNERS @@ -1,5 +1,6 @@ adamk@chromium.org danno@chromium.org +mlippautz@chromium.org ulan@chromium.org verwaest@chromium.org yangguo@chromium.org diff --git a/deps/v8/include/cppgc/README.md b/deps/v8/include/cppgc/README.md new file mode 100644 index 00000000000000..3a2db6dfa97ece --- /dev/null +++ b/deps/v8/include/cppgc/README.md @@ -0,0 +1,5 @@ +# C++ Garbage Collection + +This directory provides an open-source garbage collection library for C++. + +The library is under construction, meaning that *all APIs in this directory are incomplete and considered unstable and should not be used*. \ No newline at end of file diff --git a/deps/v8/include/cppgc/allocation.h b/deps/v8/include/cppgc/allocation.h new file mode 100644 index 00000000000000..3e717ad7d428f8 --- /dev/null +++ b/deps/v8/include/cppgc/allocation.h @@ -0,0 +1,91 @@ +// Copyright 2020 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef INCLUDE_CPPGC_ALLOCATION_H_ +#define INCLUDE_CPPGC_ALLOCATION_H_ + +#include +#include + +#include "include/cppgc/garbage-collected.h" +#include "include/cppgc/gc-info.h" +#include "include/cppgc/heap.h" +#include "include/cppgc/internals.h" + +namespace cppgc { + +template +class MakeGarbageCollectedTraitBase; + +namespace internal { + +class V8_EXPORT MakeGarbageCollectedTraitInternal { + protected: + static inline void MarkObjectAsFullyConstructed(const void* payload) { + // See api_constants for an explanation of the constants. + std::atomic* atomic_mutable_bitfield = + reinterpret_cast*>( + const_cast(reinterpret_cast( + reinterpret_cast(payload) - + api_constants::kFullyConstructedBitFieldOffsetFromPayload))); + uint16_t value = atomic_mutable_bitfield->load(std::memory_order_relaxed); + value = value | api_constants::kFullyConstructedBitMask; + atomic_mutable_bitfield->store(value, std::memory_order_release); + } + + static void* Allocate(cppgc::Heap* heap, size_t size, GCInfoIndex index); + + friend class HeapObjectHeader; +}; + +} // namespace internal + +// Users with custom allocation needs (e.g. overriding size) should override +// MakeGarbageCollectedTrait (see below) and inherit their trait from +// MakeGarbageCollectedTraitBase to get access to low-level primitives. +template +class MakeGarbageCollectedTraitBase + : private internal::MakeGarbageCollectedTraitInternal { + protected: + // Allocates an object of |size| bytes on |heap|. + // + // TODO(mlippautz): Allow specifying arena for specific embedder uses. + static void* Allocate(Heap* heap, size_t size) { + return internal::MakeGarbageCollectedTraitInternal::Allocate( + heap, size, internal::GCInfoTrait::Index()); + } + + // Marks an object as being fully constructed, resulting in precise handling + // by the garbage collector. + static void MarkObjectAsFullyConstructed(const void* payload) { + // internal::MarkObjectAsFullyConstructed(payload); + internal::MakeGarbageCollectedTraitInternal::MarkObjectAsFullyConstructed( + payload); + } +}; + +template +class MakeGarbageCollectedTrait : public MakeGarbageCollectedTraitBase { + public: + template + static T* Call(Heap* heap, Args&&... args) { + static_assert(internal::IsGarbageCollectedType::value, + "T needs to be a garbage collected object"); + void* memory = MakeGarbageCollectedTraitBase::Allocate(heap, sizeof(T)); + T* object = ::new (memory) T(std::forward(args)...); + MakeGarbageCollectedTraitBase::MarkObjectAsFullyConstructed(object); + return object; + } +}; + +// Default MakeGarbageCollected: Constructs an instance of T, which is a garbage +// collected type. +template +T* MakeGarbageCollected(Heap* heap, Args&&... args) { + return MakeGarbageCollectedTrait::Call(heap, std::forward(args)...); +} + +} // namespace cppgc + +#endif // INCLUDE_CPPGC_ALLOCATION_H_ diff --git a/deps/v8/include/cppgc/finalizer-trait.h b/deps/v8/include/cppgc/finalizer-trait.h new file mode 100644 index 00000000000000..12216ed84ed9f6 --- /dev/null +++ b/deps/v8/include/cppgc/finalizer-trait.h @@ -0,0 +1,90 @@ +// Copyright 2020 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef INCLUDE_CPPGC_FINALIZER_TRAIT_H_ +#define INCLUDE_CPPGC_FINALIZER_TRAIT_H_ + +#include + +#include "include/cppgc/internals.h" + +namespace cppgc { +namespace internal { + +using FinalizationCallback = void (*)(void*); + +template +struct HasFinalizeGarbageCollectedObject : std::false_type {}; + +template +struct HasFinalizeGarbageCollectedObject< + T, void_t().FinalizeGarbageCollectedObject())>> + : std::true_type {}; + +// The FinalizerTraitImpl specifies how to finalize objects. +template +struct FinalizerTraitImpl; + +template +struct FinalizerTraitImpl { + private: + // Dispatch to custom FinalizeGarbageCollectedObject(). + struct Custom { + static void Call(void* obj) { + static_cast(obj)->FinalizeGarbageCollectedObject(); + } + }; + + // Dispatch to regular destructor. + struct Destructor { + static void Call(void* obj) { static_cast(obj)->~T(); } + }; + + using FinalizeImpl = + std::conditional_t::value, Custom, + Destructor>; + + public: + static void Finalize(void* obj) { + static_assert(sizeof(T), "T must be fully defined"); + FinalizeImpl::Call(obj); + } +}; + +template +struct FinalizerTraitImpl { + static void Finalize(void* obj) { + static_assert(sizeof(T), "T must be fully defined"); + } +}; + +// The FinalizerTrait is used to determine if a type requires finalization and +// what finalization means. +template +struct FinalizerTrait { + private: + // Object has a finalizer if it has + // - a custom FinalizeGarbageCollectedObject method, or + // - a destructor. + static constexpr bool kNonTrivialFinalizer = + internal::HasFinalizeGarbageCollectedObject::value || + !std::is_trivially_destructible::type>::value; + + static void Finalize(void* obj) { + internal::FinalizerTraitImpl::Finalize(obj); + } + + public: + // The callback used to finalize an object of type T. + static constexpr FinalizationCallback kCallback = + kNonTrivialFinalizer ? Finalize : nullptr; +}; + +template +constexpr FinalizationCallback FinalizerTrait::kCallback; + +} // namespace internal +} // namespace cppgc + +#endif // INCLUDE_CPPGC_FINALIZER_TRAIT_H_ diff --git a/deps/v8/include/cppgc/garbage-collected.h b/deps/v8/include/cppgc/garbage-collected.h new file mode 100644 index 00000000000000..6c62daafdc5d8d --- /dev/null +++ b/deps/v8/include/cppgc/garbage-collected.h @@ -0,0 +1,53 @@ +// Copyright 2020 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef INCLUDE_CPPGC_GARBAGE_COLLECTED_H_ +#define INCLUDE_CPPGC_GARBAGE_COLLECTED_H_ + +#include + +#include "include/cppgc/internals.h" +#include "include/cppgc/platform.h" + +namespace cppgc { +namespace internal { + +template +struct IsGarbageCollectedType : std::false_type { + static_assert(sizeof(T), "T must be fully defined"); +}; + +template +struct IsGarbageCollectedType< + T, void_t::IsGarbageCollectedTypeMarker>> + : std::true_type { + static_assert(sizeof(T), "T must be fully defined"); +}; + +} // namespace internal + +template +class GarbageCollected { + public: + using IsGarbageCollectedTypeMarker = void; + + // Must use MakeGarbageCollected. + void* operator new(size_t) = delete; + void* operator new[](size_t) = delete; + // The garbage collector is taking care of reclaiming the object. Also, + // virtual destructor requires an unambiguous, accessible 'operator delete'. + void operator delete(void*) { +#ifdef V8_ENABLE_CHECKS + internal::Abort(); +#endif // V8_ENABLE_CHECKS + } + void operator delete[](void*) = delete; + + protected: + GarbageCollected() = default; +}; + +} // namespace cppgc + +#endif // INCLUDE_CPPGC_GARBAGE_COLLECTED_H_ diff --git a/deps/v8/include/cppgc/gc-info.h b/deps/v8/include/cppgc/gc-info.h new file mode 100644 index 00000000000000..987ba34fa4254c --- /dev/null +++ b/deps/v8/include/cppgc/gc-info.h @@ -0,0 +1,43 @@ +// Copyright 2020 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef INCLUDE_CPPGC_GC_INFO_H_ +#define INCLUDE_CPPGC_GC_INFO_H_ + +#include + +#include "include/cppgc/finalizer-trait.h" +#include "include/v8config.h" + +namespace cppgc { +namespace internal { + +using GCInfoIndex = uint16_t; + +class V8_EXPORT RegisteredGCInfoIndex final { + public: + RegisteredGCInfoIndex(FinalizationCallback finalization_callback, + bool has_v_table); + GCInfoIndex GetIndex() const { return index_; } + + private: + const GCInfoIndex index_; +}; + +// Trait determines how the garbage collector treats objects wrt. to traversing, +// finalization, and naming. +template +struct GCInfoTrait { + static GCInfoIndex Index() { + static_assert(sizeof(T), "T must be fully defined"); + static const RegisteredGCInfoIndex registered_index( + FinalizerTrait::kCallback, std::is_polymorphic::value); + return registered_index.GetIndex(); + } +}; + +} // namespace internal +} // namespace cppgc + +#endif // INCLUDE_CPPGC_GC_INFO_H_ diff --git a/deps/v8/include/cppgc/heap.h b/deps/v8/include/cppgc/heap.h new file mode 100644 index 00000000000000..a0568d534fbee2 --- /dev/null +++ b/deps/v8/include/cppgc/heap.h @@ -0,0 +1,31 @@ +// Copyright 2020 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef INCLUDE_CPPGC_HEAP_H_ +#define INCLUDE_CPPGC_HEAP_H_ + +#include + +#include "include/v8config.h" + +namespace cppgc { +namespace internal { +class Heap; +} // namespace internal + +class V8_EXPORT Heap { + public: + static std::unique_ptr Create(); + + virtual ~Heap() = default; + + private: + Heap() = default; + + friend class internal::Heap; +}; + +} // namespace cppgc + +#endif // INCLUDE_CPPGC_HEAP_H_ diff --git a/deps/v8/include/cppgc/internals.h b/deps/v8/include/cppgc/internals.h new file mode 100644 index 00000000000000..1e57779758b6c7 --- /dev/null +++ b/deps/v8/include/cppgc/internals.h @@ -0,0 +1,41 @@ +// Copyright 2020 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef INCLUDE_CPPGC_INTERNALS_H_ +#define INCLUDE_CPPGC_INTERNALS_H_ + +#include +#include + +#include "include/v8config.h" + +namespace cppgc { +namespace internal { + +// Pre-C++17 custom implementation of std::void_t. +template +struct make_void { + typedef void type; +}; +template +using void_t = typename make_void::type; + +// Embedders should not rely on this code! + +// Internal constants to avoid exposing internal types on the API surface. +namespace api_constants { +// Offset of the uint16_t bitfield from the payload contaning the +// in-construction bit. This is subtracted from the payload pointer to get +// to the right bitfield. +static constexpr size_t kFullyConstructedBitFieldOffsetFromPayload = + 2 * sizeof(uint16_t); +// Mask for in-construction bit. +static constexpr size_t kFullyConstructedBitMask = size_t{1}; + +} // namespace api_constants + +} // namespace internal +} // namespace cppgc + +#endif // INCLUDE_CPPGC_INTERNALS_H_ diff --git a/deps/v8/include/cppgc/platform.h b/deps/v8/include/cppgc/platform.h new file mode 100644 index 00000000000000..f216c2730a4dea --- /dev/null +++ b/deps/v8/include/cppgc/platform.h @@ -0,0 +1,31 @@ +// Copyright 2020 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef INCLUDE_CPPGC_PLATFORM_H_ +#define INCLUDE_CPPGC_PLATFORM_H_ + +#include "include/v8-platform.h" +#include "include/v8config.h" + +namespace cppgc { + +// TODO(v8:10346): Put PageAllocator in a non-V8 include header to avoid +// depending on namespace v8. +using PageAllocator = v8::PageAllocator; + +// Initializes the garbage collector with the provided platform. Must be called +// before creating a Heap. +V8_EXPORT void InitializePlatform(PageAllocator* page_allocator); + +// Must be called after destroying the last used heap. +V8_EXPORT void ShutdownPlatform(); + +namespace internal { + +V8_EXPORT void Abort(); + +} // namespace internal +} // namespace cppgc + +#endif // INCLUDE_CPPGC_PLATFORM_H_ diff --git a/deps/v8/include/js_protocol.pdl b/deps/v8/include/js_protocol.pdl index 28b8e610767142..3f5410d1e1f787 100644 --- a/deps/v8/include/js_protocol.pdl +++ b/deps/v8/include/js_protocol.pdl @@ -119,6 +119,7 @@ domain Debugger script eval module + wasm-expression-stack # Object representing the scope. For `global` and `with` scopes it represents the actual # object; for the rest of the scopes, it is artificial transient object enumerating scope # variables as its properties. @@ -273,6 +274,13 @@ domain Debugger # Resumes JavaScript execution. command resume + parameters + # Set to true to terminate execution upon resuming execution. In contrast + # to Runtime.terminateExecution, this will allows to execute further + # JavaScript (i.e. via evaluation) until execution of the paused code + # is actually resumed, at which point termination is triggered. + # If execution is currently not paused, this parameter has no effect. + optional boolean terminateOnResume # Searches for given string in script content. command searchInContent @@ -496,6 +504,12 @@ domain Debugger # Fired when the virtual machine resumed execution. event resumed + # Enum of possible script languages. + type ScriptLanguage extends string + enum + JavaScript + WebAssembly + # Fired when virtual machine fails to parse the script. event scriptFailedToParse parameters @@ -527,6 +541,10 @@ domain Debugger optional integer length # JavaScript top stack frame of where the script parsed event was triggered if available. experimental optional Runtime.StackTrace stackTrace + # If the scriptLanguage is WebAssembly, the code section offset in the module. + experimental optional integer codeOffset + # The language of the script. + experimental optional Debugger.ScriptLanguage scriptLanguage # Fired when virtual machine parses script. This event is also fired for all known and uncollected # scripts upon enabling debugger. @@ -562,6 +580,10 @@ domain Debugger optional integer length # JavaScript top stack frame of where the script parsed event was triggered if available. experimental optional Runtime.StackTrace stackTrace + # If the scriptLanguage is WebAssembly, the code section offset in the module. + experimental optional integer codeOffset + # The language of the script. + experimental optional Debugger.ScriptLanguage scriptLanguage experimental domain HeapProfiler depends on Runtime @@ -824,6 +846,8 @@ domain Profiler optional boolean callCount # Collect block-based coverage. optional boolean detailed + # Allow the backend to send updates on its own initiative + optional boolean allowTriggeredUpdates returns # Monotonically increasing time (in seconds) when the coverage update was taken in the backend. number timestamp @@ -931,7 +955,8 @@ domain Runtime boolean symbol bigint - # Object subtype hint. Specified for `object` type values only. + wasm + # Object subtype hint. Specified for `object` or `wasm` type values only. optional enum subtype array null @@ -950,6 +975,11 @@ domain Runtime typedarray arraybuffer dataview + i32 + i64 + f32 + f64 + v128 # Object class (constructor) name. Specified for `object` type values only. optional string className # Remote object value in case of primitive values or JSON values (if it was requested). @@ -1306,7 +1336,9 @@ domain Runtime experimental optional TimeDelta timeout # Disable breakpoints during execution. experimental optional boolean disableBreaks - # Reserved flag for future REPL mode support. Setting this flag has currently no effect. + # Setting this flag to true enables `let` re-declaration and top-level `await`. + # Note that `let` variables can only be re-declared if they originate from + # `replMode` themselves. experimental optional boolean replMode returns # Evaluation result. diff --git a/deps/v8/include/v8-fast-api-calls.h b/deps/v8/include/v8-fast-api-calls.h new file mode 100644 index 00000000000000..79a5d4d82a764d --- /dev/null +++ b/deps/v8/include/v8-fast-api-calls.h @@ -0,0 +1,412 @@ +// Copyright 2020 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * This file provides additional API on top of the default one for making + * API calls, which come from embedder C++ functions. The functions are being + * called directly from optimized code, doing all the necessary typechecks + * in the compiler itself, instead of on the embedder side. Hence the "fast" + * in the name. Example usage might look like: + * + * \code + * void FastMethod(int param, bool another_param); + * + * v8::FunctionTemplate::New(isolate, SlowCallback, data, + * signature, length, constructor_behavior + * side_effect_type, + * &v8::CFunction::Make(FastMethod)); + * \endcode + * + * An example for custom embedder type support might employ a way to wrap/ + * unwrap various C++ types in JSObject instances, e.g: + * + * \code + * + * // Represents the way this type system maps C++ and JS values. + * struct WrapperTypeInfo { + * // Store e.g. a method to map from exposed C++ types to the already + * // created v8::FunctionTemplate's for instantiating them. + * }; + * + * // Helper method with a sanity check. + * template + * inline T* GetInternalField(v8::Local wrapper) { + * assert(offset < wrapper->InternalFieldCount()); + * return reinterpret_cast( + * wrapper->GetAlignedPointerFromInternalField(offset)); + * } + * + * // Returns the type info from a wrapper JS object. + * inline const WrapperTypeInfo* ToWrapperTypeInfo( + * v8::Local wrapper) { + * return GetInternalField(wrapper); + * } + * + * class CustomEmbedderType { + * public: + * static constexpr const WrapperTypeInfo* GetWrapperTypeInfo() { + * return &custom_type_wrapper_type_info; + * } + * // Returns the raw C object from a wrapper JS object. + * static CustomEmbedderType* Unwrap(v8::Local wrapper) { + * return GetInternalField(wrapper); + * } + * static void FastMethod(CustomEmbedderType* receiver, int param) { + * assert(receiver != nullptr); + * // Type checks are already done by the optimized code. + * // Then call some performance-critical method like: + * // receiver->Method(param); + * } + * + * static void SlowMethod( + * const v8::FunctionCallbackInfo& info) { + * v8::Local instance = + * v8::Local::Cast(info.Holder()); + * CustomEmbedderType* receiver = Unwrap(instance); + * // TODO: Do type checks and extract {param}. + * FastMethod(receiver, param); + * } + * + * private: + * static const WrapperTypeInfo custom_type_wrapper_type_info; + * }; + * + * // Support for custom embedder types via specialization of WrapperTraits. + * namespace v8 { + * template <> + * class WrapperTraits { + * public: + * static const void* GetTypeInfo() { + * // We use the already defined machinery for the custom type. + * return CustomEmbedderType::GetWrapperTypeInfo(); + * } + * }; + * } // namespace v8 + * + * // The constants kV8EmbedderWrapperTypeIndex and + * // kV8EmbedderWrapperObjectIndex describe the offsets for the type info + * // struct (the one returned by WrapperTraits::GetTypeInfo) and the + * // native object, when expressed as internal field indices within a + * // JSObject. The existance of this helper function assumes that all + * // embedder objects have their JSObject-side type info at the same + * // offset, but this is not a limitation of the API itself. For a detailed + * // use case, see the third example. + * static constexpr int kV8EmbedderWrapperTypeIndex = 0; + * static constexpr int kV8EmbedderWrapperObjectIndex = 1; + * + * // The following setup function can be templatized based on + * // the {embedder_object} argument. + * void SetupCustomEmbedderObject(v8::Isolate* isolate, + * v8::Local context, + * CustomEmbedderType* embedder_object) { + * isolate->set_embedder_wrapper_type_index( + * kV8EmbedderWrapperTypeIndex); + * isolate->set_embedder_wrapper_object_index( + * kV8EmbedderWrapperObjectIndex); + * + * v8::CFunction c_func = + * MakeV8CFunction(CustomEmbedderType::FastMethod); + * + * Local method_template = + * v8::FunctionTemplate::New( + * isolate, CustomEmbedderType::SlowMethod, v8::Local(), + * v8::Local(), 1, v8::ConstructorBehavior::kAllow, + * v8::SideEffectType::kHasSideEffect, &c_func); + * + * v8::Local object_template = + * v8::ObjectTemplate::New(isolate); + * object_template->SetInternalFieldCount( + * kV8EmbedderWrapperObjectIndex + 1); + * object_template->Set( + v8::String::NewFromUtf8Literal(isolate, "method"), method_template); + * + * // Instantiate the wrapper JS object. + * v8::Local object = + * object_template->NewInstance(context).ToLocalChecked(); + * object->SetAlignedPointerInInternalField( + * kV8EmbedderWrapperObjectIndex, + * reinterpret_cast(embedder_object)); + * + * // TODO: Expose {object} where it's necessary. + * } + * \endcode + * + * For instance if {object} is exposed via a global "obj" variable, + * one could write in JS: + * function hot_func() { + * obj.method(42); + * } + * and once {hot_func} gets optimized, CustomEmbedderType::FastMethod + * will be called instead of the slow version, with the following arguments: + * receiver := the {embedder_object} from above + * param := 42 + * + * Currently only void return types are supported. + * Currently supported argument types: + * - pointer to an embedder type + * - bool + * - int32_t + * - uint32_t + * To be supported types: + * - int64_t + * - uint64_t + * - float32_t + * - float64_t + * - arrays of C types + * - arrays of embedder types + */ + +#ifndef INCLUDE_V8_FAST_API_CALLS_H_ +#define INCLUDE_V8_FAST_API_CALLS_H_ + +#include +#include + +#include "v8config.h" // NOLINT(build/include) + +namespace v8 { + +class CTypeInfo { + public: + enum class Type : char { + kVoid, + kBool, + kInt32, + kUint32, + kInt64, + kUint64, + kFloat32, + kFloat64, + kUnwrappedApiObject, + }; + + enum class ArgFlags : uint8_t { + kNone = 0, + kIsArrayBit = 1 << 0, // This argument is first in an array of values. + }; + + static CTypeInfo FromWrapperType(const void* wrapper_type_info, + ArgFlags flags = ArgFlags::kNone) { + uintptr_t wrapper_type_info_ptr = + reinterpret_cast(wrapper_type_info); + // Check that the lower kIsWrapperTypeBit bits are 0's. + CHECK_EQ( + wrapper_type_info_ptr & ~(static_cast(~0) + << static_cast(kIsWrapperTypeBit)), + 0u); + // TODO(mslekova): Refactor the manual bit manipulations to use + // PointerWithPayload instead. + return CTypeInfo(wrapper_type_info_ptr | static_cast(flags) | + kIsWrapperTypeBit); + } + + static constexpr CTypeInfo FromCType(Type ctype, + ArgFlags flags = ArgFlags::kNone) { + // ctype cannot be Type::kUnwrappedApiObject. + return CTypeInfo( + ((static_cast(ctype) << kTypeOffset) & kTypeMask) | + static_cast(flags)); + } + + const void* GetWrapperInfo() const; + + constexpr Type GetType() const { + if (payload_ & kIsWrapperTypeBit) { + return Type::kUnwrappedApiObject; + } + return static_cast((payload_ & kTypeMask) >> kTypeOffset); + } + + constexpr bool IsArray() const { + return payload_ & static_cast(ArgFlags::kIsArrayBit); + } + + private: + explicit constexpr CTypeInfo(uintptr_t payload) : payload_(payload) {} + + // That must be the last bit after ArgFlags. + static constexpr uintptr_t kIsWrapperTypeBit = 1 << 1; + static constexpr uintptr_t kWrapperTypeInfoMask = static_cast(~0) + << 2; + + static constexpr unsigned int kTypeOffset = kIsWrapperTypeBit; + static constexpr unsigned int kTypeSize = 8 - kTypeOffset; + static constexpr uintptr_t kTypeMask = + (~(static_cast(~0) << kTypeSize)) << kTypeOffset; + + const uintptr_t payload_; +}; + +class CFunctionInfo { + public: + virtual const CTypeInfo& ReturnInfo() const = 0; + virtual unsigned int ArgumentCount() const = 0; + virtual const CTypeInfo& ArgumentInfo(unsigned int index) const = 0; +}; + +template +class WrapperTraits { + public: + static const void* GetTypeInfo() { + static_assert(sizeof(T) != sizeof(T), + "WrapperTraits must be specialized for this type."); + return nullptr; + } +}; + +namespace internal { + +template +struct GetCType { + static_assert(sizeof(T) != sizeof(T), "Unsupported CType"); +}; + +#define SPECIALIZE_GET_C_TYPE_FOR(ctype, ctypeinfo) \ + template <> \ + struct GetCType { \ + static constexpr CTypeInfo Get() { \ + return CTypeInfo::FromCType(CTypeInfo::Type::ctypeinfo); \ + } \ + }; + +#define SUPPORTED_C_TYPES(V) \ + V(void, kVoid) \ + V(bool, kBool) \ + V(int32_t, kInt32) \ + V(uint32_t, kUint32) \ + V(int64_t, kInt64) \ + V(uint64_t, kUint64) \ + V(float, kFloat32) \ + V(double, kFloat64) + +SUPPORTED_C_TYPES(SPECIALIZE_GET_C_TYPE_FOR) + +template +struct EnableIfHasWrapperTypeInfo {}; + +template +struct EnableIfHasWrapperTypeInfo::GetTypeInfo(), + void())> { + typedef void type; +}; + +// T* where T is a primitive (array of primitives). +template +struct GetCTypePointerImpl { + static constexpr CTypeInfo Get() { + return CTypeInfo::FromCType(GetCType::Get().GetType(), + CTypeInfo::ArgFlags::kIsArrayBit); + } +}; + +// T* where T is an API object. +template +struct GetCTypePointerImpl::type> { + static constexpr CTypeInfo Get() { + return CTypeInfo::FromWrapperType(WrapperTraits::GetTypeInfo()); + } +}; + +// T** where T is a primitive. Not allowed. +template +struct GetCTypePointerPointerImpl { + static_assert(sizeof(T**) != sizeof(T**), "Unsupported type"); +}; + +// T** where T is an API object (array of API objects). +template +struct GetCTypePointerPointerImpl< + T, typename EnableIfHasWrapperTypeInfo::type> { + static constexpr CTypeInfo Get() { + return CTypeInfo::FromWrapperType(WrapperTraits::GetTypeInfo(), + CTypeInfo::ArgFlags::kIsArrayBit); + } +}; + +template +struct GetCType : public GetCTypePointerPointerImpl {}; + +template +struct GetCType : public GetCTypePointerImpl {}; + +template +class CFunctionInfoImpl : public CFunctionInfo { + public: + CFunctionInfoImpl() + : return_info_(internal::GetCType::Get()), + arg_count_(sizeof...(Args)), + arg_info_{internal::GetCType::Get()...} { + static_assert( + internal::GetCType::Get().GetType() == CTypeInfo::Type::kVoid, + "Only void return types are currently supported."); + } + + const CTypeInfo& ReturnInfo() const override { return return_info_; } + unsigned int ArgumentCount() const override { return arg_count_; } + const CTypeInfo& ArgumentInfo(unsigned int index) const override { + CHECK_LT(index, ArgumentCount()); + return arg_info_[index]; + } + + private: + CTypeInfo return_info_; + const unsigned int arg_count_; + CTypeInfo arg_info_[sizeof...(Args)]; +}; + +} // namespace internal + +class V8_EXPORT CFunction { + public: + constexpr CFunction() : address_(nullptr), type_info_(nullptr) {} + + const CTypeInfo& ReturnInfo() const { return type_info_->ReturnInfo(); } + + const CTypeInfo& ArgumentInfo(unsigned int index) const { + return type_info_->ArgumentInfo(index); + } + + unsigned int ArgumentCount() const { return type_info_->ArgumentCount(); } + + const void* GetAddress() const { return address_; } + const CFunctionInfo* GetTypeInfo() const { return type_info_; } + + template + static CFunction Make(F* func) { + return ArgUnwrap::Make(func); + } + + private: + const void* address_; + const CFunctionInfo* type_info_; + + CFunction(const void* address, const CFunctionInfo* type_info); + + template + static CFunctionInfo* GetCFunctionInfo() { + static internal::CFunctionInfoImpl instance; + return &instance; + } + + template + class ArgUnwrap { + static_assert(sizeof(F) != sizeof(F), + "CFunction must be created from a function pointer."); + }; + + template + class ArgUnwrap { + public: + static CFunction Make(R (*func)(Args...)) { + return CFunction(reinterpret_cast(func), + GetCFunctionInfo()); + } + }; +}; + +} // namespace v8 + +#endif // INCLUDE_V8_FAST_API_CALLS_H_ diff --git a/deps/v8/include/v8-inspector.h b/deps/v8/include/v8-inspector.h index 99333cb7319e62..01274625c1f476 100644 --- a/deps/v8/include/v8-inspector.h +++ b/deps/v8/include/v8-inspector.h @@ -145,9 +145,6 @@ class V8_EXPORT V8InspectorSession { virtual void breakProgram(StringView breakReason, StringView breakDetails) = 0; virtual void setSkipAllPauses(bool) = 0; - - // NOTE: setTerminateOnResume is not implemented on the base version of - // Node.js v14.0.0 / V8 8.1. virtual void resume(bool setTerminateOnResume = false) = 0; virtual void stepOver() = 0; virtual std::vector> diff --git a/deps/v8/include/v8-version.h b/deps/v8/include/v8-version.h index f21a0b8dd0fd69..64f184866537b5 100644 --- a/deps/v8/include/v8-version.h +++ b/deps/v8/include/v8-version.h @@ -9,9 +9,9 @@ // NOTE these macros are used by some of the tool scripts and the build // system so their names cannot be changed without changing the scripts. #define V8_MAJOR_VERSION 8 -#define V8_MINOR_VERSION 1 -#define V8_BUILD_NUMBER 307 -#define V8_PATCH_LEVEL 31 +#define V8_MINOR_VERSION 3 +#define V8_BUILD_NUMBER 110 +#define V8_PATCH_LEVEL 9 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) diff --git a/deps/v8/include/v8.h b/deps/v8/include/v8.h index d09055e15d2fbd..406c47383b714d 100644 --- a/deps/v8/include/v8.h +++ b/deps/v8/include/v8.h @@ -120,6 +120,8 @@ class EscapableHandleScope; template class ReturnValue; namespace internal { +enum class ArgumentsType; +template class Arguments; class DeferredHandles; class Heap; @@ -149,11 +151,6 @@ class ConsoleCallArguments; // --- Handles --- -#define TYPE_CHECK(T, S) \ - while (false) { \ - *(static_cast(0)) = static_cast(0); \ - } - /** * An object reference managed by the v8 garbage collector. * @@ -197,7 +194,7 @@ class Local { * handles. For example, converting from a Local to a * Local. */ - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); } /** @@ -363,7 +360,7 @@ class MaybeLocal { template V8_INLINE MaybeLocal(Local that) : val_(reinterpret_cast(*that)) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); } V8_INLINE bool IsEmpty() const { return val_ == nullptr; } @@ -532,11 +529,16 @@ template class PersistentBase { } /** - * Install a finalization callback on this object. - * NOTE: There is no guarantee as to *when* or even *if* the callback is - * invoked. The invocation is performed solely on a best effort basis. - * As always, GC-based finalization should *not* be relied upon for any - * critical form of resource management! + * Install a finalization callback on this object. + * NOTE: There is no guarantee as to *when* or even *if* the callback is + * invoked. The invocation is performed solely on a best effort basis. + * As always, GC-based finalization should *not* be relied upon for any + * critical form of resource management! + * + * The callback is supposed to reset the handle. No further V8 API may be + * called in this callback. In case additional work involving V8 needs to be + * done, a second callback can be scheduled using + * WeakCallbackInfo::SetSecondPassCallback. */ template V8_INLINE void SetWeak(P* parameter, @@ -618,11 +620,8 @@ class NonCopyablePersistentTraits { template V8_INLINE static void Copy(const Persistent& source, NonCopyablePersistent* dest) { - Uncompilable(); - } - // TODO(dcarney): come up with a good compile error here. - template V8_INLINE static void Uncompilable() { - TYPE_CHECK(O, Primitive); + static_assert(sizeof(S) < 0, + "NonCopyablePersistentTraits::Copy is not instantiable"); } }; @@ -665,7 +664,7 @@ template class Persistent : public PersistentBase { template V8_INLINE Persistent(Isolate* isolate, Local that) : PersistentBase(PersistentBase::New(isolate, *that)) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); } /** * Construct a Persistent from a Persistent. @@ -675,7 +674,7 @@ template class Persistent : public PersistentBase { template V8_INLINE Persistent(Isolate* isolate, const Persistent& that) : PersistentBase(PersistentBase::New(isolate, *that)) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); } /** * The copy constructors and assignment operator create a Persistent @@ -760,7 +759,7 @@ class Global : public PersistentBase { template V8_INLINE Global(Isolate* isolate, Local that) : PersistentBase(PersistentBase::New(isolate, *that)) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); } /** @@ -771,7 +770,7 @@ class Global : public PersistentBase { template V8_INLINE Global(Isolate* isolate, const PersistentBase& that) : PersistentBase(PersistentBase::New(isolate, that.val_)) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); } /** @@ -951,7 +950,7 @@ class TracedGlobal : public TracedReferenceBase { TracedGlobal(Isolate* isolate, Local that) : TracedReferenceBase() { this->val_ = this->New(isolate, that.val_, &this->val_, TracedReferenceBase::kWithDestructor); - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); } /** @@ -1074,7 +1073,7 @@ class TracedReference : public TracedReferenceBase { TracedReference(Isolate* isolate, Local that) : TracedReferenceBase() { this->val_ = this->New(isolate, that.val_, &this->val_, TracedReferenceBase::kWithoutDestructor); - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); } /** @@ -3176,6 +3175,23 @@ class V8_EXPORT String : public Name { V8_INLINE static String* Cast(v8::Value* obj); + /** + * Allocates a new string from a UTF-8 literal. This is equivalent to calling + * String::NewFromUtf(isolate, "...").ToLocalChecked(), but without the check + * overhead. + * + * When called on a string literal containing '\0', the inferred length is the + * length of the input array minus 1 (for the final '\0') and not the value + * returned by strlen. + **/ + template + static V8_WARN_UNUSED_RESULT Local NewFromUtf8Literal( + Isolate* isolate, const char (&literal)[N], + NewStringType type = NewStringType::kNormal) { + static_assert(N <= kMaxLength, "String is too long"); + return NewFromUtf8Literal(isolate, literal, type, N - 1); + } + /** Allocates a new string from UTF-8 data. Only returns an empty value when * length > kMaxLength. **/ static V8_WARN_UNUSED_RESULT MaybeLocal NewFromUtf8( @@ -3310,9 +3326,20 @@ class V8_EXPORT String : public Name { ExternalStringResourceBase* GetExternalStringResourceBaseSlow( String::Encoding* encoding_out) const; + static Local NewFromUtf8Literal(Isolate* isolate, + const char* literal, + NewStringType type, int length); + static void CheckCast(v8::Value* obj); }; +// Zero-length string specialization (templated string size includes +// terminator). +template <> +inline V8_WARN_UNUSED_RESULT Local String::NewFromUtf8Literal( + Isolate* isolate, const char (&literal)[1], NewStringType type) { + return String::Empty(isolate); +} /** * A JavaScript symbol (ECMA-262 edition 6) @@ -4019,6 +4046,13 @@ class V8_EXPORT Object : public Value { */ bool IsApiWrapper(); + /** + * True if this object was created from an object template which was marked + * as undetectable. See v8::ObjectTemplate::MarkAsUndetectable for more + * information. + */ + bool IsUndetectable(); + /** * Call an Object as a function if a callback is set by the * ObjectTemplate::SetCallAsFunctionHandler method. @@ -4175,7 +4209,7 @@ class ReturnValue { public: template V8_INLINE ReturnValue(const ReturnValue& that) : value_(that.value_) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); } // Local setters template @@ -4939,6 +4973,25 @@ class V8_EXPORT BackingStore : public v8::internal::BackingStoreBase { v8::Isolate* isolate, std::unique_ptr backing_store, size_t byte_length); + /** + * This callback is used only if the memory block for a BackingStore cannot be + * allocated with an ArrayBuffer::Allocator. In such cases the destructor of + * the BackingStore invokes the callback to free the memory block. + */ + using DeleterCallback = void (*)(void* data, size_t length, + void* deleter_data); + + /** + * If the memory block of a BackingStore is static or is managed manually, + * then this empty deleter along with nullptr deleter_data can be passed to + * ArrayBuffer::NewBackingStore to indicate that. + * + * The manually managed case should be used with caution and only when it + * is guaranteed that the memory block freeing happens after detaching its + * ArrayBuffer. + */ + static void EmptyDeleter(void* data, size_t length, void* deleter_data); + private: /** * See [Shared]ArrayBuffer::GetBackingStore and @@ -4947,14 +5000,13 @@ class V8_EXPORT BackingStore : public v8::internal::BackingStoreBase { BackingStore(); }; -/** - * This callback is used only if the memory block for this backing store cannot - * be allocated with an ArrayBuffer::Allocator. In such cases the destructor - * of this backing store object invokes the callback to free the memory block. - */ +#if !defined(V8_IMMINENT_DEPRECATION_WARNINGS) +// Use v8::BackingStore::DeleterCallback instead. using BackingStoreDeleterCallback = void (*)(void* data, size_t length, void* deleter_data); +#endif + /** * An instance of the built-in ArrayBuffer constructor (ES6 draft 15.13.5). */ @@ -5142,7 +5194,7 @@ class V8_EXPORT ArrayBuffer : public Object { * to the buffer must not be passed again to any V8 API function. */ static std::unique_ptr NewBackingStore( - void* data, size_t byte_length, BackingStoreDeleterCallback deleter, + void* data, size_t byte_length, v8::BackingStore::DeleterCallback deleter, void* deleter_data); /** @@ -5624,7 +5676,7 @@ class V8_EXPORT SharedArrayBuffer : public Object { * to the buffer must not be passed again to any V8 functions. */ static std::unique_ptr NewBackingStore( - void* data, size_t byte_length, BackingStoreDeleterCallback deleter, + void* data, size_t byte_length, v8::BackingStore::DeleterCallback deleter, void* deleter_data); /** @@ -5884,14 +5936,15 @@ class V8_EXPORT RegExp : public Object { }; /** - * An instance of the built-in FinalizationGroup constructor. + * An instance of the built-in FinalizationRegistry constructor. * - * This API is experimental and may change significantly. + * The C++ name is FinalizationGroup for backwards compatibility. This API is + * experimental and deprecated. */ class V8_EXPORT FinalizationGroup : public Object { public: /** - * Runs the cleanup callback of the given FinalizationGroup. + * Runs the cleanup callback of the given FinalizationRegistry. * * V8 will inform the embedder that there are finalizer callbacks be * called through HostCleanupFinalizationGroupCallback. @@ -6315,11 +6368,12 @@ class CFunction; * proto_t->Set(isolate, "proto_const", v8::Number::New(isolate, 2)); * * v8::Local instance_t = t->InstanceTemplate(); - * instance_t->SetAccessor(String::NewFromUtf8(isolate, "instance_accessor"), - * InstanceAccessorCallback); + * instance_t->SetAccessor( + String::NewFromUtf8Literal(isolate, "instance_accessor"), + * InstanceAccessorCallback); * instance_t->SetHandler( * NamedPropertyHandlerConfiguration(PropertyHandlerCallback)); - * instance_t->Set(String::NewFromUtf8(isolate, "instance_property"), + * instance_t->Set(String::NewFromUtf8Literal(isolate, "instance_property"), * Number::New(isolate, 3)); * * v8::Local function = t->GetFunction(); @@ -6379,6 +6433,12 @@ class CFunction; * child_instance.instance_accessor calls 'InstanceAccessorCallback' * child_instance.instance_property == 3; * \endcode + * + * The additional 'c_function' parameter refers to a fast API call, which + * must not trigger GC or JavaScript execution, or call into V8 in other + * ways. For more information how to define them, see + * include/v8-fast-api-calls.h. Please note that this feature is still + * experimental. */ class V8_EXPORT FunctionTemplate : public Template { public: @@ -6389,7 +6449,7 @@ class V8_EXPORT FunctionTemplate : public Template { Local signature = Local(), int length = 0, ConstructorBehavior behavior = ConstructorBehavior::kAllow, SideEffectType side_effect_type = SideEffectType::kHasSideEffect, - const CFunction* not_available_in_node_v14_yet = nullptr); + const CFunction* c_function = nullptr); /** * Creates a function template backed/cached by a private property. @@ -6416,12 +6476,13 @@ class V8_EXPORT FunctionTemplate : public Template { /** * Set the call-handler callback for a FunctionTemplate. This * callback is called whenever the function created from this - * FunctionTemplate is called. + * FunctionTemplate is called. The 'c_function' represents a fast + * API call, see the comment above the class declaration. */ void SetCallHandler( FunctionCallback callback, Local data = Local(), SideEffectType side_effect_type = SideEffectType::kHasSideEffect, - const CFunction* not_available_in_node_v14_yet = nullptr); + const CFunction* c_function = nullptr); /** Set the predefined length property for the FunctionTemplate. */ void SetLength(int length); @@ -7452,7 +7513,7 @@ typedef void (*WasmStreamingCallback)(const FunctionCallbackInfo&); // --- Callback for checking if WebAssembly threads are enabled --- typedef bool (*WasmThreadsEnabledCallback)(Local context); -// --- Callback for loading source map file for WASM profiling support +// --- Callback for loading source map file for Wasm profiling support typedef Local (*WasmLoadSourceMapCallback)(Isolate* isolate, const char* name); @@ -8117,7 +8178,6 @@ class V8_EXPORT Isolate { embedder_wrapper_type_index(-1), embedder_wrapper_object_index(-1) {} - /** * Allows the host application to provide the address of a function that is * notified each time code is added, moved or removed. @@ -8181,7 +8241,11 @@ class V8_EXPORT Isolate { */ bool only_terminate_in_safe_scope; - // Not available in Node v14 yet. + /** + * The following parameters describe the offsets for addressing type info + * for wrapped API objects and are used by the fast C API + * (for details see v8-fast-api-calls.h). + */ int embedder_wrapper_type_index; int embedder_wrapper_object_index; }; @@ -8486,12 +8550,12 @@ class V8_EXPORT Isolate { AbortOnUncaughtExceptionCallback callback); /** - * This specifies the callback to be called when finalization groups + * This specifies the callback to be called when FinalizationRegistries * are ready to be cleaned up and require FinalizationGroup::Cleanup() * to be called in a future task. */ V8_DEPRECATED( - "FinalizationGroup cleanup is automatic if " + "FinalizationRegistry cleanup is automatic if " "HostCleanupFinalizationGroupCallback is not set") void SetHostCleanupFinalizationGroupCallback( HostCleanupFinalizationGroupCallback callback); @@ -9106,7 +9170,7 @@ class V8_EXPORT Isolate { /** * Optional notification that a context has been disposed. V8 uses these - * notifications to guide the GC heuristic and cancel FinalizationGroup + * notifications to guide the GC heuristic and cancel FinalizationRegistry * cleanup tasks. Returns the number of context disposals - including this one * - since the last time V8 had a chance to clean up. * @@ -9740,6 +9804,11 @@ class V8_EXPORT V8 { /** * Helper class to create a snapshot data blob. + * + * The Isolate used by a SnapshotCreator is owned by it, and will be entered + * and exited by the constructor and destructor, respectively; The destructor + * will also destroy the Isolate. Experimental language features, including + * those available by default, are not available while creating a snapshot. */ class V8_EXPORT SnapshotCreator { public: @@ -9768,6 +9837,10 @@ class V8_EXPORT SnapshotCreator { SnapshotCreator(const intptr_t* external_references = nullptr, StartupData* existing_blob = nullptr); + /** + * Destroy the snapshot creator, and exit and dispose of the Isolate + * associated with it. + */ ~SnapshotCreator(); /** @@ -10359,6 +10432,18 @@ class V8_EXPORT Context { Local context); void SetAbortScriptExecution(AbortScriptExecutionCallback callback); + /** + * Returns the value that was set or restored by + * SetContinuationPreservedEmbedderData(), if any. + */ + Local GetContinuationPreservedEmbedderData() const; + + /** + * Sets a value that will be stored on continuations and reset while the + * continuation runs. + */ + void SetContinuationPreservedEmbedderData(Local context); + /** * Stack-allocated class which sets the execution context for all * operations executed within a local scope. @@ -10645,7 +10730,7 @@ Local Local::New(Isolate* isolate, T* that) { template template void Eternal::Set(Isolate* isolate, Local handle) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); val_ = reinterpret_cast( V8::Eternalize(isolate, reinterpret_cast(*handle))); } @@ -10689,7 +10774,7 @@ T* PersistentBase::New(Isolate* isolate, T* that) { template template void Persistent::Copy(const Persistent& that) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); this->Reset(); if (that.IsEmpty()) return; internal::Address* p = reinterpret_cast(that.val_); @@ -10717,7 +10802,7 @@ void PersistentBase::Reset() { template template void PersistentBase::Reset(Isolate* isolate, const Local& other) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); Reset(); if (other.IsEmpty()) return; this->val_ = New(isolate, other.val_); @@ -10728,7 +10813,7 @@ template template void PersistentBase::Reset(Isolate* isolate, const PersistentBase& other) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); Reset(); if (other.IsEmpty()) return; this->val_ = New(isolate, other.val_); @@ -10794,7 +10879,7 @@ Global::Global(Global&& other) : PersistentBase(other.val_) { template template Global& Global::operator=(Global&& rhs) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); if (this != &rhs) { this->Reset(); if (rhs.val_ != nullptr) { @@ -10829,7 +10914,7 @@ void TracedReferenceBase::Reset() { template template void TracedGlobal::Reset(Isolate* isolate, const Local& other) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); Reset(); if (other.IsEmpty()) return; this->val_ = this->New(isolate, other.val_, &this->val_, @@ -10839,7 +10924,7 @@ void TracedGlobal::Reset(Isolate* isolate, const Local& other) { template template TracedGlobal& TracedGlobal::operator=(TracedGlobal&& rhs) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); *this = std::move(rhs.template As()); return *this; } @@ -10847,7 +10932,7 @@ TracedGlobal& TracedGlobal::operator=(TracedGlobal&& rhs) { template template TracedGlobal& TracedGlobal::operator=(const TracedGlobal& rhs) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); *this = rhs.template As(); return *this; } @@ -10878,7 +10963,7 @@ TracedGlobal& TracedGlobal::operator=(const TracedGlobal& rhs) { template template void TracedReference::Reset(Isolate* isolate, const Local& other) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); Reset(); if (other.IsEmpty()) return; this->val_ = this->New(isolate, other.val_, &this->val_, @@ -10888,7 +10973,7 @@ void TracedReference::Reset(Isolate* isolate, const Local& other) { template template TracedReference& TracedReference::operator=(TracedReference&& rhs) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); *this = std::move(rhs.template As()); return *this; } @@ -10897,7 +10982,7 @@ template template TracedReference& TracedReference::operator=( const TracedReference& rhs) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); *this = rhs.template As(); return *this; } @@ -10956,7 +11041,7 @@ ReturnValue::ReturnValue(internal::Address* slot) : value_(slot) {} template template void ReturnValue::Set(const Global& handle) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); if (V8_UNLIKELY(handle.IsEmpty())) { *value_ = GetDefaultValue(); } else { @@ -10967,7 +11052,7 @@ void ReturnValue::Set(const Global& handle) { template template void ReturnValue::Set(const TracedReferenceBase& handle) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); if (V8_UNLIKELY(handle.IsEmpty())) { *value_ = GetDefaultValue(); } else { @@ -10978,7 +11063,8 @@ void ReturnValue::Set(const TracedReferenceBase& handle) { template template void ReturnValue::Set(const Local handle) { - TYPE_CHECK(T, S); + static_assert(std::is_void::value || std::is_base_of::value, + "type check"); if (V8_UNLIKELY(handle.IsEmpty())) { *value_ = GetDefaultValue(); } else { @@ -10988,13 +11074,13 @@ void ReturnValue::Set(const Local handle) { template void ReturnValue::Set(double i) { - TYPE_CHECK(T, Number); + static_assert(std::is_base_of::value, "type check"); Set(Number::New(GetIsolate(), i)); } template void ReturnValue::Set(int32_t i) { - TYPE_CHECK(T, Integer); + static_assert(std::is_base_of::value, "type check"); typedef internal::Internals I; if (V8_LIKELY(I::IsValidSmi(i))) { *value_ = I::IntToSmi(i); @@ -11005,7 +11091,7 @@ void ReturnValue::Set(int32_t i) { template void ReturnValue::Set(uint32_t i) { - TYPE_CHECK(T, Integer); + static_assert(std::is_base_of::value, "type check"); // Can't simply use INT32_MAX here for whatever reason. bool fits_into_int32_t = (i & (1U << 31)) == 0; if (V8_LIKELY(fits_into_int32_t)) { @@ -11017,7 +11103,7 @@ void ReturnValue::Set(uint32_t i) { template void ReturnValue::Set(bool value) { - TYPE_CHECK(T, Boolean); + static_assert(std::is_base_of::value, "type check"); typedef internal::Internals I; int root_index; if (value) { @@ -11030,21 +11116,21 @@ void ReturnValue::Set(bool value) { template void ReturnValue::SetNull() { - TYPE_CHECK(T, Primitive); + static_assert(std::is_base_of::value, "type check"); typedef internal::Internals I; *value_ = *I::GetRoot(GetIsolate(), I::kNullValueRootIndex); } template void ReturnValue::SetUndefined() { - TYPE_CHECK(T, Primitive); + static_assert(std::is_base_of::value, "type check"); typedef internal::Internals I; *value_ = *I::GetRoot(GetIsolate(), I::kUndefinedValueRootIndex); } template void ReturnValue::SetEmptyString() { - TYPE_CHECK(T, String); + static_assert(std::is_base_of::value, "type check"); typedef internal::Internals I; *value_ = *I::GetRoot(GetIsolate(), I::kEmptyStringRootIndex); } @@ -11066,8 +11152,7 @@ Local ReturnValue::Get() const { template template void ReturnValue::Set(S* whatever) { - // Uncompilable to prevent inadvertent misuse. - TYPE_CHECK(S*, Primitive); + static_assert(sizeof(S) < 0, "incompilable to prevent inadvertent misuse"); } template @@ -11084,14 +11169,24 @@ FunctionCallbackInfo::FunctionCallbackInfo(internal::Address* implicit_args, template Local FunctionCallbackInfo::operator[](int i) const { + // values_ points to the first argument (not the receiver). if (i < 0 || length_ <= i) return Local(*Undefined(GetIsolate())); +#ifdef V8_REVERSE_JSARGS + return Local(reinterpret_cast(values_ + i)); +#else return Local(reinterpret_cast(values_ - i)); +#endif } template Local FunctionCallbackInfo::This() const { + // values_ points to the first argument (not the receiver). +#ifdef V8_REVERSE_JSARGS + return Local(reinterpret_cast(values_ - 1)); +#else return Local(reinterpret_cast(values_ + 1)); +#endif } @@ -11968,8 +12063,4 @@ size_t SnapshotCreator::AddData(Local object) { } // namespace v8 - -#undef TYPE_CHECK - - #endif // INCLUDE_V8_H_ diff --git a/deps/v8/infra/testing/builders.pyl b/deps/v8/infra/testing/builders.pyl index b26f1a1f08a2dc..6c3379b5cbc34e 100644 --- a/deps/v8/infra/testing/builders.pyl +++ b/deps/v8/infra/testing/builders.pyl @@ -288,7 +288,8 @@ {'name': 'test262', 'variant': 'extra', 'shards': 3}, {'name': 'v8testing', 'shards': 3}, {'name': 'v8testing', 'variant': 'extra', 'shards': 3}, - {'name': 'v8testing', 'variant': 'minor_mc', 'shards': 1}, + {'name': 'v8testing', 'variant': 'minor_mc'}, + {'name': 'v8testing', 'variant': 'no_lfa'}, {'name': 'v8testing', 'variant': 'stress_instruction_scheduling'}, ], }, @@ -346,6 +347,7 @@ {'name': 'v8testing', 'shards': 2}, {'name': 'v8testing', 'variant': 'assert_types'}, {'name': 'v8testing', 'variant': 'extra'}, + {'name': 'v8testing', 'variant': 'no_lfa'}, {'name': 'v8testing', 'variant': 'stress_instruction_scheduling'}, ], }, @@ -381,6 +383,7 @@ {'name': 'v8testing', 'shards': 2}, {'name': 'v8testing', 'variant': 'extra', 'shards': 2}, {'name': 'v8testing', 'variant': 'minor_mc'}, + {'name': 'v8testing', 'variant': 'no_lfa'}, {'name': 'v8testing', 'variant': 'slow_path'}, {'name': 'v8testing', 'variant': 'stress_instruction_scheduling'}, ], @@ -849,7 +852,8 @@ {'name': 'v8testing'}, {'name': 'v8testing', 'variant': 'assert_types'}, {'name': 'v8testing', 'variant': 'extra'}, - {'name': 'v8testing', 'variant': 'minor_mc', 'shards': 1}, + {'name': 'v8testing', 'variant': 'minor_mc'}, + {'name': 'v8testing', 'variant': 'no_lfa'}, {'name': 'v8testing', 'variant': 'stress_instruction_scheduling'}, # Noavx. { @@ -906,8 +910,9 @@ {'name': 'test262', 'variant': 'extra', 'shards': 3}, {'name': 'v8testing', 'shards': 2}, {'name': 'v8testing', 'variant': 'extra', 'shards': 2}, - {'name': 'v8testing', 'variant': 'minor_mc', 'shards': 1}, - {'name': 'v8testing', 'variant': 'slow_path', 'shards': 1}, + {'name': 'v8testing', 'variant': 'minor_mc'}, + {'name': 'v8testing', 'variant': 'no_lfa'}, + {'name': 'v8testing', 'variant': 'slow_path'}, {'name': 'v8testing', 'variant': 'stress_instruction_scheduling'}, # Noavx. { @@ -1417,7 +1422,7 @@ {'name': 'mozilla'}, {'name': 'test262', 'variant': 'default'}, {'name': 'v8testing', 'shards': 3}, - {'name': 'v8testing', 'variant': 'extra'}, + {'name': 'v8testing', 'variant': 'extra', 'shards': 2}, {'name': 'v8testing', 'variant': 'trusted'}, ], }, diff --git a/deps/v8/samples/hello-world.cc b/deps/v8/samples/hello-world.cc index d75dcb3c3cc4ef..6e506475e45182 100644 --- a/deps/v8/samples/hello-world.cc +++ b/deps/v8/samples/hello-world.cc @@ -37,9 +37,7 @@ int main(int argc, char* argv[]) { { // Create a string containing the JavaScript source code. v8::Local source = - v8::String::NewFromUtf8(isolate, "'Hello' + ', World!'", - v8::NewStringType::kNormal) - .ToLocalChecked(); + v8::String::NewFromUtf8Literal(isolate, "'Hello' + ', World!'"); // Compile the source code. v8::Local script = @@ -63,7 +61,7 @@ int main(int argc, char* argv[]) { // get_local 1 // i32.add) // - const char* csource = R"( + const char csource[] = R"( let bytes = new Uint8Array([ 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x07, 0x01, 0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f, 0x03, 0x02, 0x01, 0x00, 0x07, @@ -77,8 +75,7 @@ int main(int argc, char* argv[]) { // Create a string containing the JavaScript source code. v8::Local source = - v8::String::NewFromUtf8(isolate, csource, v8::NewStringType::kNormal) - .ToLocalChecked(); + v8::String::NewFromUtf8Literal(isolate, csource); // Compile the source code. v8::Local script = diff --git a/deps/v8/samples/process.cc b/deps/v8/samples/process.cc index e4f6fd9cee733d..b23329dc107f12 100644 --- a/deps/v8/samples/process.cc +++ b/deps/v8/samples/process.cc @@ -183,8 +183,7 @@ bool JsHttpRequestProcessor::Initialize(map* opts, // Create a template for the global object where we set the // built-in global functions. Local global = ObjectTemplate::New(GetIsolate()); - global->Set(String::NewFromUtf8(GetIsolate(), "log", NewStringType::kNormal) - .ToLocalChecked(), + global->Set(String::NewFromUtf8Literal(GetIsolate(), "log"), FunctionTemplate::New(GetIsolate(), LogCallback)); // Each processor gets its own context so different processors don't @@ -210,8 +209,7 @@ bool JsHttpRequestProcessor::Initialize(map* opts, // The script compiled and ran correctly. Now we fetch out the // Process function from the global object. Local process_name = - String::NewFromUtf8(GetIsolate(), "Process", NewStringType::kNormal) - .ToLocalChecked(); + String::NewFromUtf8Literal(GetIsolate(), "Process"); Local process_val; // If there is no Process function, or if it is not a function, // bail out @@ -276,17 +274,13 @@ bool JsHttpRequestProcessor::InstallMaps(map* opts, // Set the options object as a property on the global object. context->Global() - ->Set(context, - String::NewFromUtf8(GetIsolate(), "options", NewStringType::kNormal) - .ToLocalChecked(), + ->Set(context, String::NewFromUtf8Literal(GetIsolate(), "options"), opts_obj) .FromJust(); Local output_obj = WrapMap(output); context->Global() - ->Set(context, - String::NewFromUtf8(GetIsolate(), "output", NewStringType::kNormal) - .ToLocalChecked(), + ->Set(context, String::NewFromUtf8Literal(GetIsolate(), "output"), output_obj) .FromJust(); @@ -563,21 +557,17 @@ Local JsHttpRequestProcessor::MakeRequestTemplate( // Add accessors for each of the fields of the request. result->SetAccessor( - String::NewFromUtf8(isolate, "path", NewStringType::kInternalized) - .ToLocalChecked(), + String::NewFromUtf8Literal(isolate, "path", NewStringType::kInternalized), GetPath); + result->SetAccessor(String::NewFromUtf8Literal(isolate, "referrer", + NewStringType::kInternalized), + GetReferrer); result->SetAccessor( - String::NewFromUtf8(isolate, "referrer", NewStringType::kInternalized) - .ToLocalChecked(), - GetReferrer); - result->SetAccessor( - String::NewFromUtf8(isolate, "host", NewStringType::kInternalized) - .ToLocalChecked(), + String::NewFromUtf8Literal(isolate, "host", NewStringType::kInternalized), GetHost); - result->SetAccessor( - String::NewFromUtf8(isolate, "userAgent", NewStringType::kInternalized) - .ToLocalChecked(), - GetUserAgent); + result->SetAccessor(String::NewFromUtf8Literal(isolate, "userAgent", + NewStringType::kInternalized), + GetUserAgent); // Again, return the result through the current handle scope. return handle_scope.Escape(result); diff --git a/deps/v8/samples/shell.cc b/deps/v8/samples/shell.cc index 81b028720c8d2f..aed050ceccd283 100644 --- a/deps/v8/samples/shell.cc +++ b/deps/v8/samples/shell.cc @@ -108,27 +108,20 @@ v8::Local CreateShellContext(v8::Isolate* isolate) { // Create a template for the global object. v8::Local global = v8::ObjectTemplate::New(isolate); // Bind the global 'print' function to the C++ Print callback. - global->Set( - v8::String::NewFromUtf8(isolate, "print", v8::NewStringType::kNormal) - .ToLocalChecked(), - v8::FunctionTemplate::New(isolate, Print)); + global->Set(v8::String::NewFromUtf8Literal(isolate, "print"), + v8::FunctionTemplate::New(isolate, Print)); // Bind the global 'read' function to the C++ Read callback. - global->Set(v8::String::NewFromUtf8( - isolate, "read", v8::NewStringType::kNormal).ToLocalChecked(), + global->Set(v8::String::NewFromUtf8Literal(isolate, "read"), v8::FunctionTemplate::New(isolate, Read)); // Bind the global 'load' function to the C++ Load callback. - global->Set(v8::String::NewFromUtf8( - isolate, "load", v8::NewStringType::kNormal).ToLocalChecked(), + global->Set(v8::String::NewFromUtf8Literal(isolate, "load"), v8::FunctionTemplate::New(isolate, Load)); // Bind the 'quit' function - global->Set(v8::String::NewFromUtf8( - isolate, "quit", v8::NewStringType::kNormal).ToLocalChecked(), + global->Set(v8::String::NewFromUtf8Literal(isolate, "quit"), v8::FunctionTemplate::New(isolate, Quit)); // Bind the 'version' function - global->Set( - v8::String::NewFromUtf8(isolate, "version", v8::NewStringType::kNormal) - .ToLocalChecked(), - v8::FunctionTemplate::New(isolate, Version)); + global->Set(v8::String::NewFromUtf8Literal(isolate, "version"), + v8::FunctionTemplate::New(isolate, Version)); return v8::Context::New(isolate, NULL, global); } @@ -161,22 +154,19 @@ void Print(const v8::FunctionCallbackInfo& args) { void Read(const v8::FunctionCallbackInfo& args) { if (args.Length() != 1) { args.GetIsolate()->ThrowException( - v8::String::NewFromUtf8(args.GetIsolate(), "Bad parameters", - v8::NewStringType::kNormal).ToLocalChecked()); + v8::String::NewFromUtf8Literal(args.GetIsolate(), "Bad parameters")); return; } v8::String::Utf8Value file(args.GetIsolate(), args[0]); if (*file == NULL) { - args.GetIsolate()->ThrowException( - v8::String::NewFromUtf8(args.GetIsolate(), "Error loading file", - v8::NewStringType::kNormal).ToLocalChecked()); + args.GetIsolate()->ThrowException(v8::String::NewFromUtf8Literal( + args.GetIsolate(), "Error loading file")); return; } v8::Local source; if (!ReadFile(args.GetIsolate(), *file).ToLocal(&source)) { - args.GetIsolate()->ThrowException( - v8::String::NewFromUtf8(args.GetIsolate(), "Error loading file", - v8::NewStringType::kNormal).ToLocalChecked()); + args.GetIsolate()->ThrowException(v8::String::NewFromUtf8Literal( + args.GetIsolate(), "Error loading file")); return; } @@ -191,22 +181,19 @@ void Load(const v8::FunctionCallbackInfo& args) { v8::HandleScope handle_scope(args.GetIsolate()); v8::String::Utf8Value file(args.GetIsolate(), args[i]); if (*file == NULL) { - args.GetIsolate()->ThrowException( - v8::String::NewFromUtf8(args.GetIsolate(), "Error loading file", - v8::NewStringType::kNormal).ToLocalChecked()); + args.GetIsolate()->ThrowException(v8::String::NewFromUtf8Literal( + args.GetIsolate(), "Error loading file")); return; } v8::Local source; if (!ReadFile(args.GetIsolate(), *file).ToLocal(&source)) { - args.GetIsolate()->ThrowException( - v8::String::NewFromUtf8(args.GetIsolate(), "Error loading file", - v8::NewStringType::kNormal).ToLocalChecked()); + args.GetIsolate()->ThrowException(v8::String::NewFromUtf8Literal( + args.GetIsolate(), "Error loading file")); return; } if (!ExecuteString(args.GetIsolate(), source, args[i], false, false)) { - args.GetIsolate()->ThrowException( - v8::String::NewFromUtf8(args.GetIsolate(), "Error executing file", - v8::NewStringType::kNormal).ToLocalChecked()); + args.GetIsolate()->ThrowException(v8::String::NewFromUtf8Literal( + args.GetIsolate(), "Error executing file")); return; } } @@ -228,8 +215,8 @@ void Quit(const v8::FunctionCallbackInfo& args) { void Version(const v8::FunctionCallbackInfo& args) { args.GetReturnValue().Set( - v8::String::NewFromUtf8(args.GetIsolate(), v8::V8::GetVersion(), - v8::NewStringType::kNormal).ToLocalChecked()); + v8::String::NewFromUtf8(args.GetIsolate(), v8::V8::GetVersion()) + .ToLocalChecked()); } @@ -276,12 +263,9 @@ int RunMain(v8::Isolate* isolate, v8::Platform* platform, int argc, } else if (strcmp(str, "-e") == 0 && i + 1 < argc) { // Execute argument given to -e option directly. v8::Local file_name = - v8::String::NewFromUtf8(isolate, "unnamed", - v8::NewStringType::kNormal).ToLocalChecked(); + v8::String::NewFromUtf8Literal(isolate, "unnamed"); v8::Local source; - if (!v8::String::NewFromUtf8(isolate, argv[++i], - v8::NewStringType::kNormal) - .ToLocal(&source)) { + if (!v8::String::NewFromUtf8(isolate, argv[++i]).ToLocal(&source)) { return 1; } bool success = ExecuteString(isolate, source, file_name, false, true); @@ -290,8 +274,7 @@ int RunMain(v8::Isolate* isolate, v8::Platform* platform, int argc, } else { // Use all other arguments as names of files to load and run. v8::Local file_name = - v8::String::NewFromUtf8(isolate, str, v8::NewStringType::kNormal) - .ToLocalChecked(); + v8::String::NewFromUtf8(isolate, str).ToLocalChecked(); v8::Local source; if (!ReadFile(isolate, str).ToLocal(&source)) { fprintf(stderr, "Error reading '%s'\n", str); @@ -313,8 +296,7 @@ void RunShell(v8::Local context, v8::Platform* platform) { // Enter the execution environment before evaluating any code. v8::Context::Scope context_scope(context); v8::Local name( - v8::String::NewFromUtf8(context->GetIsolate(), "(shell)", - v8::NewStringType::kNormal).ToLocalChecked()); + v8::String::NewFromUtf8Literal(context->GetIsolate(), "(shell)")); while (true) { char buffer[kBufferSize]; fprintf(stderr, "> "); @@ -323,8 +305,7 @@ void RunShell(v8::Local context, v8::Platform* platform) { v8::HandleScope handle_scope(context->GetIsolate()); ExecuteString( context->GetIsolate(), - v8::String::NewFromUtf8(context->GetIsolate(), str, - v8::NewStringType::kNormal).ToLocalChecked(), + v8::String::NewFromUtf8(context->GetIsolate(), str).ToLocalChecked(), name, true, true); while (v8::platform::PumpMessageLoop(platform, context->GetIsolate())) continue; diff --git a/deps/v8/src/DEPS b/deps/v8/src/DEPS index 3e802dac975826..772ad53b326066 100644 --- a/deps/v8/src/DEPS +++ b/deps/v8/src/DEPS @@ -16,6 +16,7 @@ include_rules = [ "+src/heap/heap-inl.h", "+src/heap/heap-write-barrier-inl.h", "+src/heap/heap-write-barrier.h", + "+src/heap/local-heap.h", "+src/heap/off-thread-factory-inl.h", "+src/heap/off-thread-factory.h", "+src/heap/read-only-heap-inl.h", diff --git a/deps/v8/src/api/api-inl.h b/deps/v8/src/api/api-inl.h index 217d21222def88..0d2ad2f8a0f8ce 100644 --- a/deps/v8/src/api/api-inl.h +++ b/deps/v8/src/api/api-inl.h @@ -86,7 +86,7 @@ MAKE_TO_LOCAL(ToLocal, JSArrayBufferView, ArrayBufferView) MAKE_TO_LOCAL(ToLocal, JSDataView, DataView) MAKE_TO_LOCAL(ToLocal, JSTypedArray, TypedArray) MAKE_TO_LOCAL(ToLocalShared, JSArrayBuffer, SharedArrayBuffer) -MAKE_TO_LOCAL(ToLocal, JSFinalizationGroup, FinalizationGroup) +MAKE_TO_LOCAL(ToLocal, JSFinalizationRegistry, FinalizationGroup) TYPED_ARRAYS(MAKE_TO_LOCAL_TYPED_ARRAY) diff --git a/deps/v8/src/api/api.cc b/deps/v8/src/api/api.cc index 9693e4c843ed18..1b59f2cf6457b2 100644 --- a/deps/v8/src/api/api.cc +++ b/deps/v8/src/api/api.cc @@ -13,6 +13,7 @@ #include "src/api/api-inl.h" +#include "include/v8-fast-api-calls.h" #include "include/v8-profiler.h" #include "include/v8-util.h" #include "src/api/api-natives.h" @@ -463,11 +464,13 @@ void i::V8::FatalProcessOutOfMemory(i::Isolate* isolate, const char* location, // BUG(1718): Don't use the take_snapshot since we don't support // HeapObjectIterator here without doing a special GC. isolate->heap()->RecordStats(&heap_stats, false); - char* first_newline = strchr(last_few_messages, '\n'); - if (first_newline == nullptr || first_newline[1] == '\0') - first_newline = last_few_messages; - PrintF("\n<--- Last few GCs --->\n%s\n", first_newline); - PrintF("\n<--- JS stacktrace --->\n%s\n", js_stacktrace); + if (!FLAG_correctness_fuzzer_suppressions) { + char* first_newline = strchr(last_few_messages, '\n'); + if (first_newline == nullptr || first_newline[1] == '\0') + first_newline = last_few_messages; + base::OS::PrintError("\n<--- Last few GCs --->\n%s\n", first_newline); + base::OS::PrintError("\n<--- JS stacktrace --->\n%s\n", js_stacktrace); + } } Utils::ReportOOMFailure(isolate, location, is_heap_oom); // If the fatal error handler returns, we stop execution. @@ -888,6 +891,8 @@ StartupData SnapshotCreator::CreateBlob( startup_serializer.SerializeWeakReferencesAndDeferred(); can_be_rehashed = can_be_rehashed && startup_serializer.can_be_rehashed(); + startup_serializer.CheckNoDirtyFinalizationRegistries(); + read_only_serializer.FinalizeSerialization(); can_be_rehashed = can_be_rehashed && read_only_serializer.can_be_rehashed(); @@ -1006,7 +1011,7 @@ void ResourceConstraints::ConfigureDefaultsFromHeapSize( set_initial_young_generation_size_in_bytes(young_generation); set_initial_old_generation_size_in_bytes(old_generation); } - if (i::kRequiresCodeRange) { + if (i::kPlatformRequiresCodeRange) { set_code_range_size_in_bytes( i::Min(i::kMaximalCodeRangeSize, maximum_heap_size_in_bytes)); } @@ -1021,7 +1026,7 @@ void ResourceConstraints::ConfigureDefaults(uint64_t physical_memory, set_max_young_generation_size_in_bytes(young_generation); set_max_old_generation_size_in_bytes(old_generation); - if (virtual_memory_limit > 0 && i::kRequiresCodeRange) { + if (virtual_memory_limit > 0 && i::kPlatformRequiresCodeRange) { set_code_range_size_in_bytes( i::Min(i::kMaximalCodeRangeSize, static_cast(virtual_memory_limit / 8))); @@ -1463,7 +1468,8 @@ static Local FunctionTemplateNew( i::Isolate* isolate, FunctionCallback callback, v8::Local data, v8::Local signature, int length, bool do_not_cache, v8::Local cached_property_name = v8::Local(), - SideEffectType side_effect_type = SideEffectType::kHasSideEffect) { + SideEffectType side_effect_type = SideEffectType::kHasSideEffect, + const CFunction* c_function = nullptr) { i::Handle struct_obj = isolate->factory()->NewStruct( i::FUNCTION_TEMPLATE_INFO_TYPE, i::AllocationType::kOld); i::Handle obj = @@ -1481,7 +1487,8 @@ static Local FunctionTemplateNew( obj->set_serial_number(i::Smi::FromInt(next_serial_number)); } if (callback != nullptr) { - Utils::ToLocal(obj)->SetCallHandler(callback, data, side_effect_type); + Utils::ToLocal(obj)->SetCallHandler(callback, data, side_effect_type, + c_function); } obj->set_undetectable(false); obj->set_needs_access_check(false); @@ -1499,14 +1506,15 @@ static Local FunctionTemplateNew( Local FunctionTemplate::New( Isolate* isolate, FunctionCallback callback, v8::Local data, v8::Local signature, int length, ConstructorBehavior behavior, - SideEffectType side_effect_type, const CFunction*) { + SideEffectType side_effect_type, const CFunction* c_function) { i::Isolate* i_isolate = reinterpret_cast(isolate); // Changes to the environment cannot be captured in the snapshot. Expect no // function templates when the isolate is created for serialization. LOG_API(i_isolate, FunctionTemplate, New); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); - auto templ = FunctionTemplateNew(i_isolate, callback, data, signature, length, - false, Local(), side_effect_type); + auto templ = + FunctionTemplateNew(i_isolate, callback, data, signature, length, false, + Local(), side_effect_type, c_function); if (behavior == ConstructorBehavior::kThrow) templ->RemovePrototype(); return templ; } @@ -1541,7 +1549,7 @@ Local AccessorSignature::New( void FunctionTemplate::SetCallHandler(FunctionCallback callback, v8::Local data, SideEffectType side_effect_type, - const CFunction*) { + const CFunction* c_function) { auto info = Utils::OpenHandle(this); EnsureNotInstantiated(info, "v8::FunctionTemplate::SetCallHandler"); i::Isolate* isolate = info->GetIsolate(); @@ -1555,6 +1563,16 @@ void FunctionTemplate::SetCallHandler(FunctionCallback callback, data = v8::Undefined(reinterpret_cast(isolate)); } obj->set_data(*Utils::OpenHandle(*data)); + // Blink passes CFunction's constructed with the default constructor + // for non-fast calls, so we should check the address too. + if (c_function != nullptr && c_function->GetAddress()) { + i::FunctionTemplateInfo::SetCFunction( + isolate, info, + i::handle(*FromCData(isolate, c_function->GetAddress()), isolate)); + i::FunctionTemplateInfo::SetCSignature( + isolate, info, + i::handle(*FromCData(isolate, c_function->GetTypeInfo()), isolate)); + } info->set_call_code(*obj); } @@ -3791,6 +3809,12 @@ std::unique_ptr v8::BackingStore::Reallocate( return backing_store; } +// static +void v8::BackingStore::EmptyDeleter(void* data, size_t length, + void* deleter_data) { + DCHECK_NULL(deleter_data); +} + std::shared_ptr v8::ArrayBuffer::GetBackingStore() { i::Handle self = Utils::OpenHandle(this); std::shared_ptr backing_store = self->GetBackingStore(); @@ -4807,6 +4831,11 @@ bool v8::Object::IsApiWrapper() { return self->IsApiWrapper(); } +bool v8::Object::IsUndetectable() { + auto self = i::Handle::cast(Utils::OpenHandle(this)); + return self->IsUndetectable(); +} + MaybeLocal Object::CallAsFunction(Local context, Local recv, int argc, Local argv[]) { @@ -5754,9 +5783,7 @@ HeapStatistics::HeapStatistics() peak_malloced_memory_(0), does_zap_garbage_(false), number_of_native_contexts_(0), - number_of_detached_contexts_(0), - total_global_handles_size_(0), - used_global_handles_size_(0) {} + number_of_detached_contexts_(0) {} HeapSpaceStatistics::HeapSpaceStatistics() : space_name_(nullptr), @@ -6112,6 +6139,24 @@ void Context::SetAbortScriptExecution( } } +Local Context::GetContinuationPreservedEmbedderData() const { + i::Handle context = Utils::OpenHandle(this); + i::Isolate* isolate = context->GetIsolate(); + i::Handle data( + context->native_context().continuation_preserved_embedder_data(), + isolate); + return ToApiHandle(data); +} + +void Context::SetContinuationPreservedEmbedderData(Local data) { + i::Handle context = Utils::OpenHandle(this); + i::Isolate* isolate = context->GetIsolate(); + if (data.IsEmpty()) + data = v8::Undefined(reinterpret_cast(isolate)); + context->native_context().set_continuation_preserved_embedder_data( + *i::Handle::cast(Utils::OpenHandle(*data))); +} + namespace { i::Address* GetSerializedDataFromFixedArray(i::Isolate* isolate, i::FixedArray list, size_t index) { @@ -6317,6 +6362,19 @@ STATIC_ASSERT(v8::String::kMaxLength == i::String::kMaxLength); result = Utils::ToLocal(handle_result); \ } +Local String::NewFromUtf8Literal(Isolate* isolate, const char* literal, + NewStringType type, int length) { + DCHECK_LE(length, i::String::kMaxLength); + i::Isolate* i_isolate = reinterpret_cast(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); + LOG_API(i_isolate, String, NewFromUtf8Literal); + i::Handle handle_result = + NewString(i_isolate->factory(), type, + i::Vector(literal, length)) + .ToHandleChecked(); + return Utils::ToLocal(handle_result); +} + MaybeLocal String::NewFromUtf8(Isolate* isolate, const char* data, NewStringType type, int length) { NEW_STRING(isolate, String, NewFromUtf8, char, data, type, length); @@ -7510,7 +7568,7 @@ std::unique_ptr v8::ArrayBuffer::NewBackingStore( } std::unique_ptr v8::ArrayBuffer::NewBackingStore( - void* data, size_t byte_length, BackingStoreDeleterCallback deleter, + void* data, size_t byte_length, v8::BackingStore::DeleterCallback deleter, void* deleter_data) { CHECK_LE(byte_length, i::JSArrayBuffer::kMaxByteLength); std::unique_ptr backing_store = @@ -7839,7 +7897,7 @@ std::unique_ptr v8::SharedArrayBuffer::NewBackingStore( } std::unique_ptr v8::SharedArrayBuffer::NewBackingStore( - void* data, size_t byte_length, BackingStoreDeleterCallback deleter, + void* data, size_t byte_length, v8::BackingStore::DeleterCallback deleter, void* deleter_data) { CHECK_LE(byte_length, i::JSArrayBuffer::kMaxByteLength); std::unique_ptr backing_store = @@ -8260,6 +8318,10 @@ void Isolate::Initialize(Isolate* isolate, } i_isolate->set_only_terminate_in_safe_scope( params.only_terminate_in_safe_scope); + i_isolate->set_embedder_wrapper_type_index( + params.embedder_wrapper_type_index); + i_isolate->set_embedder_wrapper_object_index( + params.embedder_wrapper_object_index); if (!i::V8::GetCurrentPlatform() ->GetForegroundTaskRunner(isolate) @@ -8319,16 +8381,17 @@ void Isolate::SetHostCleanupFinalizationGroupCallback( Maybe FinalizationGroup::Cleanup( Local finalization_group) { - i::Handle fg = Utils::OpenHandle(*finalization_group); - i::Isolate* isolate = fg->native_context().GetIsolate(); - i::Handle i_context(fg->native_context(), isolate); + i::Handle fr = + Utils::OpenHandle(*finalization_group); + i::Isolate* isolate = fr->native_context().GetIsolate(); + i::Handle i_context(fr->native_context(), isolate); Local context = Utils::ToLocal(i_context); ENTER_V8(isolate, context, FinalizationGroup, Cleanup, Nothing(), i::HandleScope); - i::Handle callback(fg->cleanup(), isolate); - fg->set_scheduled_for_cleanup(false); + i::Handle callback(fr->cleanup(), isolate); + fr->set_scheduled_for_cleanup(false); has_pending_exception = - i::JSFinalizationGroup::Cleanup(isolate, fg, callback).IsNothing(); + i::JSFinalizationRegistry::Cleanup(isolate, fr, callback).IsNothing(); RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool); return Just(true); } @@ -8446,6 +8509,8 @@ void Isolate::GetHeapStatistics(HeapStatistics* heap_statistics) { heap_statistics->total_physical_size_ = heap->CommittedPhysicalMemory(); heap_statistics->total_available_size_ = heap->Available(); heap_statistics->used_heap_size_ = heap->SizeOfObjects(); + heap_statistics->total_global_handles_size_ = heap->TotalGlobalHandlesSize(); + heap_statistics->used_global_handles_size_ = heap->UsedGlobalHandlesSize(); #ifndef V8_SHARED_RO_HEAP i::ReadOnlySpace* ro_space = heap->read_only_space(); @@ -9256,6 +9321,34 @@ MaybeLocal debug::GetInternalProperties(Isolate* v8_isolate, return Utils::ToLocal(result); } +namespace { +void CollectPrivateMethodsAndAccessorsFromContext( + i::Isolate* isolate, i::Handle context, + i::IsStaticFlag is_static_flag, std::vector>* names_out, + std::vector>* values_out) { + i::Handle scope_info(context->scope_info(), isolate); + int local_count = scope_info->ContextLocalCount(); + for (int j = 0; j < local_count; ++j) { + i::VariableMode mode = scope_info->ContextLocalMode(j); + i::IsStaticFlag flag = scope_info->ContextLocalIsStaticFlag(j); + if (!i::IsPrivateMethodOrAccessorVariableMode(mode) || + flag != is_static_flag) { + continue; + } + + i::Handle name(scope_info->ContextLocalName(j), isolate); + int context_index = scope_info->ContextHeaderLength() + j; + i::Handle slot_value(context->get(context_index), isolate); + DCHECK_IMPLIES(mode == i::VariableMode::kPrivateMethod, + slot_value->IsJSFunction()); + DCHECK_IMPLIES(mode != i::VariableMode::kPrivateMethod, + slot_value->IsAccessorPair()); + names_out->push_back(Utils::ToLocal(name)); + values_out->push_back(Utils::ToLocal(slot_value)); + } +} +} // anonymous namespace + bool debug::GetPrivateMembers(Local context, Local value, std::vector>* names_out, std::vector>* values_out) { @@ -9276,7 +9369,7 @@ bool debug::GetPrivateMembers(Local context, Local value, i::GetKeysConversion::kConvertToString), false); - // Estimate number of private entries to return in the FixedArray. + // Estimate number of private fields and private instance methods/accessors. int private_entries_count = 0; for (int i = 0; i < keys->length(); ++i) { // Exclude the private brand symbols. @@ -9296,10 +9389,42 @@ bool debug::GetPrivateMembers(Local context, Local value, } } + // Estimate number of static private methods/accessors for classes. + bool has_static_private_methods_or_accessors = false; + if (receiver->IsJSFunction()) { + i::Handle func(i::JSFunction::cast(*receiver), isolate); + i::Handle shared(func->shared(), isolate); + if (shared->is_class_constructor() && + shared->has_static_private_methods_or_accessors()) { + has_static_private_methods_or_accessors = true; + i::Handle context(func->context(), isolate); + i::Handle scope_info(context->scope_info(), isolate); + int local_count = scope_info->ContextLocalCount(); + for (int j = 0; j < local_count; ++j) { + i::VariableMode mode = scope_info->ContextLocalMode(j); + i::IsStaticFlag is_static_flag = + scope_info->ContextLocalIsStaticFlag(j); + if (i::IsPrivateMethodOrAccessorVariableMode(mode) && + is_static_flag == i::IsStaticFlag::kStatic) { + private_entries_count += local_count; + break; + } + } + } + } + DCHECK(names_out->empty()); names_out->reserve(private_entries_count); DCHECK(values_out->empty()); values_out->reserve(private_entries_count); + + if (has_static_private_methods_or_accessors) { + i::Handle context(i::JSFunction::cast(*receiver).context(), + isolate); + CollectPrivateMethodsAndAccessorsFromContext( + isolate, context, i::IsStaticFlag::kStatic, names_out, values_out); + } + for (int i = 0; i < keys->length(); ++i) { i::Handle obj_key(keys->get(i), isolate); i::Handle key(i::Symbol::cast(*obj_key), isolate); @@ -9311,25 +9436,8 @@ bool debug::GetPrivateMembers(Local context, Local value, if (key->is_private_brand()) { DCHECK(value->IsContext()); i::Handle context(i::Context::cast(*value), isolate); - i::Handle scope_info(context->scope_info(), isolate); - int local_count = scope_info->ContextLocalCount(); - - for (int j = 0; j < local_count; ++j) { - i::VariableMode mode = scope_info->ContextLocalMode(j); - if (!i::IsPrivateMethodOrAccessorVariableMode(mode)) { - continue; - } - - i::Handle name(scope_info->ContextLocalName(j), isolate); - int context_index = scope_info->ContextHeaderLength() + j; - i::Handle slot_value(context->get(context_index), isolate); - DCHECK_IMPLIES(mode == i::VariableMode::kPrivateMethod, - slot_value->IsJSFunction()); - DCHECK_IMPLIES(mode != i::VariableMode::kPrivateMethod, - slot_value->IsAccessorPair()); - names_out->push_back(Utils::ToLocal(name)); - values_out->push_back(Utils::ToLocal(slot_value)); - } + CollectPrivateMethodsAndAccessorsFromContext( + isolate, context, i::IsStaticFlag::kNotStatic, names_out, values_out); } else { // Private fields i::Handle name( i::String::cast(i::Symbol::cast(*key).description()), isolate); @@ -9388,6 +9496,12 @@ void debug::BreakRightNow(Isolate* v8_isolate) { isolate->debug()->HandleDebugBreak(i::kIgnoreIfAllFramesBlackboxed); } +void debug::SetTerminateOnResume(Isolate* v8_isolate) { + i::Isolate* isolate = reinterpret_cast(v8_isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); + isolate->debug()->SetTerminateOnResume(); +} + bool debug::AllFramesOnStackAreBlackboxed(Isolate* v8_isolate) { i::Isolate* isolate = reinterpret_cast(v8_isolate); ENTER_V8_DO_NOT_USE(isolate); @@ -9429,7 +9543,7 @@ std::vector debug::Script::LineEnds() const { i::Isolate* isolate = script->GetIsolate(); i::HandleScope scope(isolate); - i::Script::InitLineEnds(script); + i::Script::InitLineEnds(isolate, script); CHECK(script->line_ends().IsFixedArray()); i::Handle line_ends(i::FixedArray::cast(script->line_ends()), isolate); @@ -9521,9 +9635,9 @@ bool debug::Script::GetPossibleBreakpoints( locations); } - i::Script::InitLineEnds(script); - CHECK(script->line_ends().IsFixedArray()); i::Isolate* isolate = script->GetIsolate(); + i::Script::InitLineEnds(isolate, script); + CHECK(script->line_ends().IsFixedArray()); i::Handle line_ends = i::Handle::cast(i::handle(script->line_ends(), isolate)); CHECK(line_ends->length()); @@ -9576,7 +9690,7 @@ int debug::Script::GetSourceOffset(const debug::Location& location) const { column = std::max(0, column - script->column_offset()); } - i::Script::InitLineEnds(script); + i::Script::InitLineEnds(script->GetIsolate(), script); CHECK(script->line_ends().IsFixedArray()); i::Handle line_ends = i::Handle::cast( i::handle(script->line_ends(), script->GetIsolate())); @@ -9723,6 +9837,15 @@ uint32_t debug::WasmScript::GetFunctionHash(int function_index) { function_bytes.length(), 0); } +int debug::WasmScript::CodeOffset() const { + i::Handle script = Utils::OpenHandle(this); + DCHECK_EQ(i::Script::TYPE_WASM, script->type()); + i::wasm::NativeModule* native_module = script->wasm_native_module(); + const i::wasm::WasmModule* module = native_module->module(); + + return module->code.offset(); +} + debug::Location::Location(int line_number, int column_number) : line_number_(line_number), column_number_(column_number), @@ -9788,6 +9911,16 @@ MaybeLocal debug::CompileInspectorScript(Isolate* v8_isolate, RETURN_ESCAPED(ToApiHandle(result)); } +void debug::TierDownAllModulesPerIsolate(Isolate* v8_isolate) { + i::Isolate* isolate = reinterpret_cast(v8_isolate); + isolate->wasm_engine()->TierDownAllModulesPerIsolate(isolate); +} + +void debug::TierUpAllModulesPerIsolate(Isolate* v8_isolate) { + i::Isolate* isolate = reinterpret_cast(v8_isolate); + isolate->wasm_engine()->TierUpAllModulesPerIsolate(isolate); +} + void debug::SetDebugDelegate(Isolate* v8_isolate, debug::DebugDelegate* delegate) { i::Isolate* isolate = reinterpret_cast(v8_isolate); @@ -9902,7 +10035,7 @@ debug::ConsoleCallArguments::ConsoleCallArguments( : v8::FunctionCallbackInfo( nullptr, // Drop the first argument (receiver, i.e. the "console" object). - args.address_of_arg_at(args.length() > 1 ? 1 : 0), + args.length() > 1 ? args.address_of_first_argument() : nullptr, args.length() - 1) {} int debug::GetStackFrameId(v8::Local frame) { @@ -10817,6 +10950,34 @@ void EmbedderHeapTracer::ResetHandleInNonTracingGC( UNREACHABLE(); } +const void* CTypeInfo::GetWrapperInfo() const { + DCHECK(payload_ & kWrapperTypeInfoMask); + return reinterpret_cast(payload_ & kWrapperTypeInfoMask); +} + +CFunction::CFunction(const void* address, const CFunctionInfo* type_info) + : address_(address), type_info_(type_info) { + CHECK_NOT_NULL(address_); + CHECK_NOT_NULL(type_info_); + for (unsigned int i = 0; i < type_info_->ArgumentCount(); ++i) { + if (type_info_->ArgumentInfo(i).IsArray()) { + // Array args require an integer passed for their length + // as the next argument. + DCHECK_LT(i + 1, type_info_->ArgumentCount()); + switch (type_info_->ArgumentInfo(i + 1).GetType()) { + case CTypeInfo::Type::kInt32: + case CTypeInfo::Type::kUint32: + case CTypeInfo::Type::kInt64: + case CTypeInfo::Type::kUint64: + break; + default: + UNREACHABLE(); + break; + } + } + } +} + namespace internal { const size_t HandleScopeImplementer::kEnteredContextsOffset = @@ -10998,21 +11159,22 @@ void InvokeFunctionCallback(const v8::FunctionCallbackInfo& info, callback(info); } -void InvokeFinalizationGroupCleanupFromTask( - Handle context, Handle finalization_group, +void InvokeFinalizationRegistryCleanupFromTask( + Handle context, + Handle finalization_registry, Handle callback) { - Isolate* isolate = finalization_group->native_context().GetIsolate(); + Isolate* isolate = finalization_registry->native_context().GetIsolate(); RuntimeCallTimerScope timer( - isolate, RuntimeCallCounterId::kFinalizationGroupCleanupFromTask); + isolate, RuntimeCallCounterId::kFinalizationRegistryCleanupFromTask); // Do not use ENTER_V8 because this is always called from a running - // FinalizationGroupCleanupTask within V8 and we should not log it as an API - // call. This method is implemented here to avoid duplication of the exception - // handling and microtask running logic in CallDepthScope. + // FinalizationRegistryCleanupTask within V8 and we should not log it as an + // API call. This method is implemented here to avoid duplication of the + // exception handling and microtask running logic in CallDepthScope. if (IsExecutionTerminatingCheck(isolate)) return; Local api_context = Utils::ToLocal(context); CallDepthScope call_depth_scope(isolate, api_context); VMState state(isolate); - if (JSFinalizationGroup::Cleanup(isolate, finalization_group, callback) + if (JSFinalizationRegistry::Cleanup(isolate, finalization_registry, callback) .IsNothing()) { call_depth_scope.Escape(); } diff --git a/deps/v8/src/api/api.h b/deps/v8/src/api/api.h index b39cf1ce275777..4c383d3e43caf3 100644 --- a/deps/v8/src/api/api.h +++ b/deps/v8/src/api/api.h @@ -26,7 +26,7 @@ namespace v8 { namespace internal { class JSArrayBufferView; -class JSFinalizationGroup; +class JSFinalizationRegistry; } // namespace internal namespace debug { @@ -93,7 +93,7 @@ class RegisteredExtension { V(Data, Object) \ V(RegExp, JSRegExp) \ V(Object, JSReceiver) \ - V(FinalizationGroup, JSFinalizationGroup) \ + V(FinalizationGroup, JSFinalizationRegistry) \ V(Array, JSArray) \ V(Map, JSMap) \ V(Set, JSSet) \ @@ -206,7 +206,7 @@ class Utils { static inline Local ToLocalBigUint64Array( v8::internal::Handle obj); static inline Local ToLocal( - v8::internal::Handle obj); + v8::internal::Handle obj); static inline Local ToLocalShared( v8::internal::Handle obj); @@ -562,8 +562,9 @@ void InvokeAccessorGetterCallback( void InvokeFunctionCallback(const v8::FunctionCallbackInfo& info, v8::FunctionCallback callback); -void InvokeFinalizationGroupCleanupFromTask( - Handle context, Handle finalization_group, +void InvokeFinalizationRegistryCleanupFromTask( + Handle context, + Handle finalization_registry, Handle callback); } // namespace internal diff --git a/deps/v8/src/asmjs/asm-js.cc b/deps/v8/src/asmjs/asm-js.cc index 033efc45b3ad20..5a6846c33f4e5c 100644 --- a/deps/v8/src/asmjs/asm-js.cc +++ b/deps/v8/src/asmjs/asm-js.cc @@ -132,13 +132,11 @@ void Report(Handle - diff --git a/deps/v8/tools/heap-stats/details-selection.js b/deps/v8/tools/heap-stats/details-selection.js index 1e9cc83cff304d..f7e32733d97e7e 100644 --- a/deps/v8/tools/heap-stats/details-selection.js +++ b/deps/v8/tools/heap-stats/details-selection.js @@ -4,19 +4,18 @@ 'use strict'; -const details_selection_template = - document.currentScript.ownerDocument.querySelector( - '#details-selection-template'); +import {CATEGORIES, CATEGORY_NAMES} from './categories.js'; -const VIEW_BY_INSTANCE_TYPE = 'by-instance-type'; -const VIEW_BY_INSTANCE_CATEGORY = 'by-instance-category'; -const VIEW_BY_FIELD_TYPE = 'by-field-type'; +export const VIEW_BY_INSTANCE_TYPE = 'by-instance-type'; +export const VIEW_BY_INSTANCE_CATEGORY = 'by-instance-category'; +export const VIEW_BY_FIELD_TYPE = 'by-field-type'; -class DetailsSelection extends HTMLElement { +defineCustomElement('details-selection', (templateText) => + class DetailsSelection extends HTMLElement { constructor() { super(); const shadowRoot = this.attachShadow({mode: 'open'}); - shadowRoot.appendChild(details_selection_template.content.cloneNode(true)); + shadowRoot.innerHTML = templateText; this.isolateSelect.addEventListener( 'change', e => this.handleIsolateChange(e)); this.dataViewSelect.addEventListener( @@ -403,6 +402,4 @@ class DetailsSelection extends HTMLElement { link.click(); this.shadowRoot.removeChild(link); } -} - -customElements.define('details-selection', DetailsSelection); +}); diff --git a/deps/v8/tools/heap-stats/global-timeline.html b/deps/v8/tools/heap-stats/global-timeline-template.html similarity index 73% rename from deps/v8/tools/heap-stats/global-timeline.html rename to deps/v8/tools/heap-stats/global-timeline-template.html index 788f966735f921..bb11b44961fafe 100644 --- a/deps/v8/tools/heap-stats/global-timeline.html +++ b/deps/v8/tools/heap-stats/global-timeline-template.html @@ -1,7 +1,6 @@ -