diff --git a/.eslintrc.js b/.eslintrc.js index ba94036b0f50bc..f59f65f8065c58 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -129,6 +129,7 @@ module.exports = { 'no-dupe-else-if': 'error', 'no-duplicate-case': 'error', 'no-duplicate-imports': 'error', + 'no-else-return': ['error', { allowElseIf: true }], 'no-empty-character-class': 'error', 'no-ex-assign': 'error', 'no-extra-boolean-cast': 'error', @@ -189,34 +190,6 @@ module.exports = { // as well to lib/.eslintrc.yaml. 'no-restricted-syntax': [ 'error', - { - selector: "CallExpression[callee.property.name='deepStrictEqual'][arguments.2.type='Literal']", - message: 'Do not use a literal for the third argument of assert.deepStrictEqual()', - }, - { - selector: "CallExpression[callee.property.name='doesNotThrow']", - message: 'Do not use `assert.doesNotThrow()`. Write the code without the wrapper and add a comment instead.', - }, - { - selector: "CallExpression[callee.property.name='doesNotReject']", - message: 'Do not use `assert.doesNotReject()`. Write the code without the wrapper and add a comment instead.', - }, - { - selector: "CallExpression[callee.property.name='rejects'][arguments.length<2]", - message: '`assert.rejects()` must be invoked with at least two arguments.', - }, - { - selector: "CallExpression[callee.property.name='strictEqual'][arguments.2.type='Literal']", - message: 'Do not use a literal for the third argument of assert.strictEqual()', - }, - { - selector: "CallExpression[callee.property.name='throws'][arguments.1.type='Literal']:not([arguments.1.regex])", - message: 'Use an object as second argument of `assert.throws()`.', - }, - { - selector: "CallExpression[callee.property.name='throws'][arguments.length<2]", - message: '`assert.throws()` must be invoked with at least two arguments.', - }, { selector: "CallExpression[callee.name='setTimeout'][arguments.length<2]", message: '`setTimeout()` must be invoked with at least two arguments.', @@ -229,22 +202,6 @@ module.exports = { selector: 'ThrowStatement > CallExpression[callee.name=/Error$/]', message: 'Use `new` keyword when throwing an `Error`.', }, - { - selector: "CallExpression[callee.property.name='notDeepStrictEqual'][arguments.0.type='Literal']:not([arguments.1.type='Literal']):not([arguments.1.type='ObjectExpression']):not([arguments.1.type='ArrayExpression']):not([arguments.1.type='UnaryExpression'])", - message: 'The first argument should be the `actual`, not the `expected` value.', - }, - { - selector: "CallExpression[callee.property.name='notStrictEqual'][arguments.0.type='Literal']:not([arguments.1.type='Literal']):not([arguments.1.type='ObjectExpression']):not([arguments.1.type='ArrayExpression']):not([arguments.1.type='UnaryExpression'])", - message: 'The first argument should be the `actual`, not the `expected` value.', - }, - { - selector: "CallExpression[callee.property.name='deepStrictEqual'][arguments.0.type='Literal']:not([arguments.1.type='Literal']):not([arguments.1.type='ObjectExpression']):not([arguments.1.type='ArrayExpression']):not([arguments.1.type='UnaryExpression'])", - message: 'The first argument should be the `actual`, not the `expected` value.', - }, - { - selector: "CallExpression[callee.property.name='strictEqual'][arguments.0.type='Literal']:not([arguments.1.type='Literal']):not([arguments.1.type='ObjectExpression']):not([arguments.1.type='ArrayExpression']):not([arguments.1.type='UnaryExpression'])", - message: 'The first argument should be the `actual`, not the `expected` value.', - }, { selector: "CallExpression[callee.name='isNaN']", message: 'Use Number.isNaN() instead of the global isNaN() function.', diff --git a/.github/ISSUE_TEMPLATE/3-api-ref-docs-problem.md b/.github/ISSUE_TEMPLATE/3-api-ref-docs-problem.md new file mode 100644 index 00000000000000..3ec3959eb67173 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/3-api-ref-docs-problem.md @@ -0,0 +1,54 @@ +--- +name: "\U0001F4D7 Open an issue regarding the Node.js API reference docs" +about: Let us know about any problematic API reference documents +title: "doc: " +labels: doc +--- + +# 📗 API Reference Docs Problem + + + + + +- **Version**: ✍️ +- **Platform**: ✍️ +- **Subsystem**: ✍️ + +## Location + +_Section of the site where the content exists_ + +Affected URL(s): +- https://nodejs.org/api/✍️ + +## Problem description + +_Concise explanation of what you found to be problematic_ + + + +✍️ + +--- + + + +- [ ] I would like to work on this issue and submit a pull request. diff --git a/.github/workflows/test-linux.yml b/.github/workflows/test-linux.yml index 4b0bc052f0c190..cfe0ca4ab70334 100644 --- a/.github/workflows/test-linux.yml +++ b/.github/workflows/test-linux.yml @@ -18,6 +18,6 @@ jobs: - name: Environment Information run: npx envinfo - name: Build - run: make build-ci -j2 V=1 + run: make build-ci -j2 V=1 CONFIG_FLAGS="--error-on-warn" - name: Test run: make run-ci -j2 V=1 TEST_CI_ARGS="-p dots" diff --git a/.github/workflows/test-macos.yml b/.github/workflows/test-macos.yml index 8bb0ab6d71001e..c78ab45e4b2398 100644 --- a/.github/workflows/test-macos.yml +++ b/.github/workflows/test-macos.yml @@ -18,6 +18,6 @@ jobs: - name: Environment Information run: npx envinfo - name: Build - run: make build-ci -j8 V=1 + run: make build-ci -j8 V=1 CONFIG_FLAGS="--error-on-warn" - name: Test run: make run-ci -j8 V=1 TEST_CI_ARGS="-p dots" diff --git a/BUILDING.md b/BUILDING.md index a7dc040f5f385e..13caddbdc13e98 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -249,6 +249,8 @@ Installation via Linux package manager can be achieved with: FreeBSD and OpenBSD users may also need to install `libexecinfo`. +Python 3 users may also need to install `python3-distutils`. + #### macOS prerequisites * Xcode Command Line Tools >= 10 for macOS diff --git a/CHANGELOG.md b/CHANGELOG.md index 8bec924fac1fc6..f7b21ae6d6a2d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,7 +31,8 @@ release. -14.2.0
+14.3.0
+14.2.0
14.1.0
14.0.0
diff --git a/Makefile b/Makefile index 21794191d8b32c..43d23459284609 100644 --- a/Makefile +++ b/Makefile @@ -295,7 +295,7 @@ v8: tools/make-v8.sh $(V8_ARCH).$(BUILDTYPE_LOWER) $(V8_BUILD_OPTIONS) .PHONY: jstest -jstest: build-addons build-abort-tests build-js-native-api-tests build-node-api-tests ## Runs addon tests and JS tests +jstest: build-addons build-js-native-api-tests build-node-api-tests ## Runs addon tests and JS tests $(PYTHON) tools/test.py $(PARALLEL_ARGS) --mode=$(BUILDTYPE_LOWER) \ --skip-tests=$(CI_SKIP_TESTS) \ $(CI_JS_SUITES) \ @@ -319,7 +319,6 @@ test: all ## Runs default tests, linters, and builds docs. $(MAKE) -s tooltest $(MAKE) -s test-doc $(MAKE) -s build-addons - $(MAKE) -s build-abort-tests $(MAKE) -s build-js-native-api-tests $(MAKE) -s build-node-api-tests $(MAKE) -s cctest @@ -328,7 +327,6 @@ test: all ## Runs default tests, linters, and builds docs. .PHONY: test-only test-only: all ## For a quick test, does not run linter or build docs. $(MAKE) build-addons - $(MAKE) build-abort-tests $(MAKE) build-js-native-api-tests $(MAKE) build-node-api-tests $(MAKE) cctest @@ -338,7 +336,6 @@ test-only: all ## For a quick test, does not run linter or build docs. # Used by `make coverage-test` test-cov: all $(MAKE) build-addons - $(MAKE) build-abort-tests $(MAKE) build-js-native-api-tests $(MAKE) build-node-api-tests $(MAKE) cctest @@ -458,31 +455,6 @@ test/node-api/.buildstamp: $(ADDONS_PREREQS) \ # TODO(bnoordhuis) Force rebuild after gyp or node-gyp update. build-node-api-tests: | $(NODE_EXE) test/node-api/.buildstamp -ABORT_BINDING_GYPS := \ - $(filter-out test/abort/??_*/binding.gyp, \ - $(wildcard test/abort/*/binding.gyp)) - -ABORT_BINDING_SOURCES := \ - $(filter-out test/abort/??_*/*.c, $(wildcard test/abort/*/*.c)) \ - $(filter-out test/abort/??_*/*.cc, $(wildcard test/abort/*/*.cc)) \ - $(filter-out test/abort/??_*/*.h, $(wildcard test/abort/*/*.h)) - -# Implicitly depends on $(NODE_EXE), see the build-node-api-tests rule for rationale. -test/abort/.buildstamp: $(ADDONS_PREREQS) \ - $(ABORT_BINDING_GYPS) $(ABORT_BINDING_SOURCES) \ - src/node_api.h src/node_api_types.h src/js_native_api.h \ - src/js_native_api_types.h src/js_native_api_v8.h src/js_native_api_v8_internals.h - @$(call run_build_addons,"$$PWD/test/abort",$@) - -.PHONY: build-abort-tests -# .buildstamp needs $(NODE_EXE) but cannot depend on it -# directly because it calls make recursively. The parent make cannot know -# if the subprocess touched anything so it pessimistically assumes that -# .buildstamp is out of date and need a rebuild. -# Just goes to show that recursive make really is harmful... -# TODO(bnoordhuis) Force rebuild after gyp or node-gyp update. -build-abort-tests: | $(NODE_EXE) test/abort/.buildstamp - BENCHMARK_NAPI_BINDING_GYPS := $(wildcard benchmark/napi/*/binding.gyp) BENCHMARK_NAPI_BINDING_SOURCES := \ @@ -503,14 +475,12 @@ clear-stalled: echo $${PS_OUT} | xargs kill -9; \ fi -test-build: | all build-addons build-abort-tests build-js-native-api-tests build-node-api-tests +test-build: | all build-addons build-js-native-api-tests build-node-api-tests test-build-js-native-api: all build-js-native-api-tests test-build-node-api: all build-node-api-tests -test-build-abort: all build-abort-tests - .PHONY: test-all test-all: test-build ## Run default tests with both Debug and Release builds. $(PYTHON) tools/test.py $(PARALLEL_ARGS) --mode=debug,release @@ -523,7 +493,7 @@ test-all-suites: | clear-stalled test-build bench-addons-build doc-only ## Run a $(PYTHON) tools/test.py $(PARALLEL_ARGS) --mode=$(BUILDTYPE_LOWER) test/* # CI_* variables should be kept synchronized with the ones in vcbuild.bat -CI_NATIVE_SUITES ?= addons js-native-api node-api abort +CI_NATIVE_SUITES ?= addons js-native-api node-api CI_JS_SUITES ?= default ifeq ($(node_use_openssl), false) CI_DOC := doctool @@ -535,7 +505,7 @@ endif # Build and test addons without building anything else # Related CI job: node-test-commit-arm-fanned test-ci-native: LOGLEVEL := info -test-ci-native: | test/addons/.buildstamp test/js-native-api/.buildstamp test/node-api/.buildstamp test/abort/.buildstamp +test-ci-native: | test/addons/.buildstamp test/js-native-api/.buildstamp test/node-api/.buildstamp $(PYTHON) tools/test.py $(PARALLEL_ARGS) -p tap --logfile test.tap \ --mode=$(BUILDTYPE_LOWER) --flaky-tests=$(FLAKY_TESTS) \ $(TEST_CI_ARGS) $(CI_NATIVE_SUITES) @@ -557,7 +527,7 @@ test-ci-js: | clear-stalled .PHONY: test-ci # Related CI jobs: most CI tests, excluding node-test-commit-arm-fanned test-ci: LOGLEVEL := info -test-ci: | clear-stalled build-addons build-abort-tests build-js-native-api-tests build-node-api-tests doc-only +test-ci: | clear-stalled build-addons build-js-native-api-tests build-node-api-tests doc-only out/Release/cctest --gtest_output=xml:out/junit/cctest.xml $(PYTHON) tools/test.py $(PARALLEL_ARGS) -p tap --logfile test.tap \ --mode=$(BUILDTYPE_LOWER) --flaky-tests=$(FLAKY_TESTS) \ @@ -663,17 +633,8 @@ test-node-api-clean: $(RM) -r test/node-api/*/build $(RM) test/node-api/.buildstamp -.PHONY: test-abort -test-abort: test-build-abort - $(PYTHON) tools/test.py $(PARALLEL_ARGS) --mode=$(BUILDTYPE_LOWER) test-abort - -.PHONY: test-abort-clean -test-abort-clean: - $(RM) -r test/abort/*/build - $(RM) test/abort/.buildstamp - .PHONY: test-addons -test-addons: test-build test-js-native-api test-node-api test-abort +test-addons: test-build test-js-native-api test-node-api $(PYTHON) tools/test.py $(PARALLEL_ARGS) --mode=$(BUILDTYPE_LOWER) addons .PHONY: test-addons-clean @@ -683,7 +644,6 @@ test-addons-clean: $(RM) test/addons/.buildstamp test/addons/.docbuildstamp $(MAKE) test-js-native-api-clean $(MAKE) test-node-api-clean - $(MAKE) test-abort-clean test-async-hooks: $(PYTHON) tools/test.py $(PARALLEL_ARGS) --mode=$(BUILDTYPE_LOWER) async-hooks @@ -692,7 +652,6 @@ test-with-async-hooks: $(MAKE) build-addons $(MAKE) build-js-native-api-tests $(MAKE) build-node-api-tests - $(MAKE) build-abort-tests $(MAKE) cctest NODE_TEST_WITH_ASYNC_HOOKS=1 $(PYTHON) tools/test.py $(PARALLEL_ARGS) --mode=$(BUILDTYPE_LOWER) \ $(CI_JS_SUITES) \ diff --git a/benchmark/async_hooks/promises.js b/benchmark/async_hooks/promises.js index eb90ca0368e079..5632a6901d611b 100644 --- a/benchmark/async_hooks/promises.js +++ b/benchmark/async_hooks/promises.js @@ -2,10 +2,31 @@ const common = require('../common.js'); const { createHook } = require('async_hooks'); +let hook; +const tests = { + disabled() { + hook = createHook({ + promiseResolve() {} + }); + }, + enabled() { + hook = createHook({ + promiseResolve() {} + }).enable(); + }, + enabledWithDestroy() { + hook = createHook({ + promiseResolve() {}, + destroy() {} + }).enable(); + } +}; + const bench = common.createBenchmark(main, { n: [1e6], asyncHooks: [ 'enabled', + 'enabledWithDestroy', 'disabled', ] }); @@ -19,10 +40,8 @@ async function run(n) { } function main({ n, asyncHooks }) { - const hook = createHook({ promiseResolve() {} }); - if (asyncHooks !== 'disabled') { - hook.enable(); - } + if (hook) hook.disable(); + tests[asyncHooks](); bench.start(); run(n).then(() => { bench.end(n); diff --git a/benchmark/es/spread-bench.js b/benchmark/es/spread-bench.js index ae5b4abbb99c02..284debdfa09ad8 100644 --- a/benchmark/es/spread-bench.js +++ b/benchmark/es/spread-bench.js @@ -16,11 +16,10 @@ function makeTest(count, rest) { return function test(...args) { assert.strictEqual(count, args.length); }; - } else { - return function test() { - assert.strictEqual(count, arguments.length); - }; } + return function test() { + assert.strictEqual(count, arguments.length); + }; } function main({ n, context, count, rest, method }) { diff --git a/benchmark/scatter.js b/benchmark/scatter.js index ecbf8e0041c837..858169d7d68c3b 100644 --- a/benchmark/scatter.js +++ b/benchmark/scatter.js @@ -30,9 +30,8 @@ let printHeader = true; function csvEncodeValue(value) { if (typeof value === 'number') { return value.toString(); - } else { - return `"${value.replace(/"/g, '""')}"`; } + return `"${value.replace(/"/g, '""')}"`; } (function recursive(i) { diff --git a/benchmark/worker/atomics-wait.js b/benchmark/worker/atomics-wait.js new file mode 100644 index 00000000000000..a771b1813731ed --- /dev/null +++ b/benchmark/worker/atomics-wait.js @@ -0,0 +1,15 @@ +'use strict'; +/* global SharedArrayBuffer */ + +const common = require('../common.js'); +const bench = common.createBenchmark(main, { + n: [1e7] +}); + +function main({ n }) { + const i32arr = new Int32Array(new SharedArrayBuffer(4)); + bench.start(); + for (let i = 0; i < n; i++) + Atomics.wait(i32arr, 0, 1); // Will return immediately. + bench.end(n); +} diff --git a/deps/icu-small/README-FULL-ICU.txt b/deps/icu-small/README-FULL-ICU.txt index 52df74fba99fbf..bad8b0346d3e98 100644 --- a/deps/icu-small/README-FULL-ICU.txt +++ b/deps/icu-small/README-FULL-ICU.txt @@ -1,8 +1,8 @@ ICU sources - auto generated by shrink-icu-src.py This directory contains the ICU subset used by --with-intl=full-icu -It is a strict subset of ICU 66 source files with the following exception(s): -* deps/icu-small/source/data/in/icudt66l.dat.bz2 : compressed data file +It is a strict subset of ICU 67 source files with the following exception(s): +* deps/icu-small/source/data/in/icudt67l.dat.bz2 : compressed data file To rebuild this directory, see ../../tools/icu/README.md diff --git a/deps/icu-small/source/common/brkiter.cpp b/deps/icu-small/source/common/brkiter.cpp index 2fc4c345c7a038..7b8bff4b921c78 100644 --- a/deps/icu-small/source/common/brkiter.cpp +++ b/deps/icu-small/source/common/brkiter.cpp @@ -38,6 +38,7 @@ #include "uresimp.h" #include "uassert.h" #include "ubrkimpl.h" +#include "utracimp.h" #include "charstr.h" // ***************************************************************************** @@ -412,14 +413,23 @@ BreakIterator::makeInstance(const Locale& loc, int32_t kind, UErrorCode& status) BreakIterator *result = NULL; switch (kind) { case UBRK_CHARACTER: - result = BreakIterator::buildInstance(loc, "grapheme", status); + { + UTRACE_ENTRY(UTRACE_UBRK_CREATE_CHARACTER); + result = BreakIterator::buildInstance(loc, "grapheme", status); + UTRACE_EXIT_STATUS(status); + } break; case UBRK_WORD: - result = BreakIterator::buildInstance(loc, "word", status); + { + UTRACE_ENTRY(UTRACE_UBRK_CREATE_WORD); + result = BreakIterator::buildInstance(loc, "word", status); + UTRACE_EXIT_STATUS(status); + } break; case UBRK_LINE: - uprv_strcpy(lbType, "line"); { + UTRACE_ENTRY(UTRACE_UBRK_CREATE_LINE); + uprv_strcpy(lbType, "line"); char lbKeyValue[kKeyValueLenMax] = {0}; UErrorCode kvStatus = U_ZERO_ERROR; int32_t kLen = loc.getKeywordValue("lb", lbKeyValue, kKeyValueLenMax, kvStatus); @@ -427,13 +437,17 @@ BreakIterator::makeInstance(const Locale& loc, int32_t kind, UErrorCode& status) uprv_strcat(lbType, "_"); uprv_strcat(lbType, lbKeyValue); } + result = BreakIterator::buildInstance(loc, lbType, status); + + UTRACE_DATA1(UTRACE_INFO, "lb=%s", lbKeyValue); + UTRACE_EXIT_STATUS(status); } - result = BreakIterator::buildInstance(loc, lbType, status); break; case UBRK_SENTENCE: - result = BreakIterator::buildInstance(loc, "sentence", status); -#if !UCONFIG_NO_FILTERED_BREAK_ITERATION { + UTRACE_ENTRY(UTRACE_UBRK_CREATE_SENTENCE); + result = BreakIterator::buildInstance(loc, "sentence", status); +#if !UCONFIG_NO_FILTERED_BREAK_ITERATION char ssKeyValue[kKeyValueLenMax] = {0}; UErrorCode kvStatus = U_ZERO_ERROR; int32_t kLen = loc.getKeywordValue("ss", ssKeyValue, kKeyValueLenMax, kvStatus); @@ -444,11 +458,16 @@ BreakIterator::makeInstance(const Locale& loc, int32_t kind, UErrorCode& status) delete fbiBuilder; } } - } #endif + UTRACE_EXIT_STATUS(status); + } break; case UBRK_TITLE: - result = BreakIterator::buildInstance(loc, "title", status); + { + UTRACE_ENTRY(UTRACE_UBRK_CREATE_TITLE); + result = BreakIterator::buildInstance(loc, "title", status); + UTRACE_EXIT_STATUS(status); + } break; default: status = U_ILLEGAL_ARGUMENT_ERROR; diff --git a/deps/icu-small/source/common/cmemory.h b/deps/icu-small/source/common/cmemory.h index b24bd0ead2761c..38f99179631b10 100644 --- a/deps/icu-small/source/common/cmemory.h +++ b/deps/icu-small/source/common/cmemory.h @@ -274,7 +274,10 @@ inline T *LocalMemory::allocateInsteadAndCopy(int32_t newCapacity, int32_t le * * WARNING: MaybeStackArray only works with primitive (plain-old data) types. * It does NOT know how to call a destructor! If you work with classes with - * destructors, consider LocalArray in localpointer.h or MemoryPool. + * destructors, consider: + * + * - LocalArray in localpointer.h if you know the length ahead of time + * - MaybeStackVector if you know the length at runtime */ template class MaybeStackArray { @@ -684,26 +687,26 @@ inline H *MaybeStackHeaderAndArray::orphanOrClone(int32_t l template class MemoryPool : public UMemory { public: - MemoryPool() : count(0), pool() {} + MemoryPool() : fCount(0), fPool() {} ~MemoryPool() { - for (int32_t i = 0; i < count; ++i) { - delete pool[i]; + for (int32_t i = 0; i < fCount; ++i) { + delete fPool[i]; } } MemoryPool(const MemoryPool&) = delete; MemoryPool& operator=(const MemoryPool&) = delete; - MemoryPool(MemoryPool&& other) U_NOEXCEPT : count(other.count), - pool(std::move(other.pool)) { - other.count = 0; + MemoryPool(MemoryPool&& other) U_NOEXCEPT : fCount(other.fCount), + fPool(std::move(other.fPool)) { + other.fCount = 0; } MemoryPool& operator=(MemoryPool&& other) U_NOEXCEPT { - count = other.count; - pool = std::move(other.pool); - other.count = 0; + fCount = other.fCount; + fPool = std::move(other.fPool); + other.fCount = 0; return *this; } @@ -716,20 +719,101 @@ class MemoryPool : public UMemory { */ template T* create(Args&&... args) { - int32_t capacity = pool.getCapacity(); - if (count == capacity && - pool.resize(capacity == stackCapacity ? 4 * capacity : 2 * capacity, - capacity) == nullptr) { + int32_t capacity = fPool.getCapacity(); + if (fCount == capacity && + fPool.resize(capacity == stackCapacity ? 4 * capacity : 2 * capacity, + capacity) == nullptr) { return nullptr; } - return pool[count++] = new T(std::forward(args)...); + return fPool[fCount++] = new T(std::forward(args)...); } -private: - int32_t count; - MaybeStackArray pool; + /** + * @return Number of elements that have been allocated. + */ + int32_t count() const { + return fCount; + } + +protected: + int32_t fCount; + MaybeStackArray fPool; +}; + +/** + * An internal Vector-like implementation based on MemoryPool. + * + * Heap-allocates each element and stores pointers. + * + * To append an item to the vector, use emplaceBack. + * + * MaybeStackVector vector; + * MyType* element = vector.emplaceBack(); + * if (!element) { + * status = U_MEMORY_ALLOCATION_ERROR; + * } + * // do stuff with element + * + * To loop over the vector, use a for loop with indices: + * + * for (int32_t i = 0; i < vector.length(); i++) { + * MyType* element = vector[i]; + * } + */ +template +class MaybeStackVector : protected MemoryPool { +public: + using MemoryPool::MemoryPool; + using MemoryPool::operator=; + + template + T* emplaceBack(Args&&... args) { + return this->create(args...); + } + + int32_t length() const { + return this->fCount; + } + + T** getAlias() { + return this->fPool.getAlias(); + } + + /** + * Array item access (read-only). + * No index bounds check. + * @param i array index + * @return reference to the array item + */ + const T* operator[](ptrdiff_t i) const { + return this->fPool[i]; + } + + /** + * Array item access (writable). + * No index bounds check. + * @param i array index + * @return reference to the array item + */ + T* operator[](ptrdiff_t i) { + return this->fPool[i]; + } + + /** + * Append all the items from another MaybeStackVector to this one. + */ + void appendAll(const MaybeStackVector& other, UErrorCode& status) { + for (int32_t i = 0; i < other.fCount; i++) { + T* item = emplaceBack(*other[i]); + if (!item) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + } + } }; + U_NAMESPACE_END #endif /* __cplusplus */ diff --git a/deps/icu-small/source/common/cstring.h b/deps/icu-small/source/common/cstring.h index ed0b1a7c8b0be8..3a14e4216c8e51 100644 --- a/deps/icu-small/source/common/cstring.h +++ b/deps/icu-small/source/common/cstring.h @@ -52,6 +52,8 @@ U_CAPI UBool U_EXPORT2 uprv_isASCIILetter(char c); +// NOTE: For u_asciiToUpper that takes a UChar, see ustr_imp.h + U_CAPI char U_EXPORT2 uprv_toupper(char c); diff --git a/deps/icu-small/source/common/dictbe.cpp b/deps/icu-small/source/common/dictbe.cpp index 6ceba21a244047..6d3bc878078847 100644 --- a/deps/icu-small/source/common/dictbe.cpp +++ b/deps/icu-small/source/common/dictbe.cpp @@ -18,6 +18,7 @@ #include "unicode/uniset.h" #include "unicode/chariter.h" #include "unicode/ubrk.h" +#include "utracimp.h" #include "uvectr32.h" #include "uvector.h" #include "uassert.h" @@ -194,6 +195,8 @@ ThaiBreakEngine::ThaiBreakEngine(DictionaryMatcher *adoptDictionary, UErrorCode : DictionaryBreakEngine(), fDictionary(adoptDictionary) { + UTRACE_ENTRY(UTRACE_UBRK_CREATE_BREAK_ENGINE); + UTRACE_DATA1(UTRACE_INFO, "dictbe=%s", "Thai"); fThaiWordSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Thai:]&[:LineBreak=SA:]]"), status); if (U_SUCCESS(status)) { setCharacters(fThaiWordSet); @@ -213,6 +216,7 @@ ThaiBreakEngine::ThaiBreakEngine(DictionaryMatcher *adoptDictionary, UErrorCode fEndWordSet.compact(); fBeginWordSet.compact(); fSuffixSet.compact(); + UTRACE_EXIT_STATUS(status); } ThaiBreakEngine::~ThaiBreakEngine() { @@ -436,6 +440,8 @@ LaoBreakEngine::LaoBreakEngine(DictionaryMatcher *adoptDictionary, UErrorCode &s : DictionaryBreakEngine(), fDictionary(adoptDictionary) { + UTRACE_ENTRY(UTRACE_UBRK_CREATE_BREAK_ENGINE); + UTRACE_DATA1(UTRACE_INFO, "dictbe=%s", "Laoo"); fLaoWordSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Laoo:]&[:LineBreak=SA:]]"), status); if (U_SUCCESS(status)) { setCharacters(fLaoWordSet); @@ -452,6 +458,7 @@ LaoBreakEngine::LaoBreakEngine(DictionaryMatcher *adoptDictionary, UErrorCode &s fMarkSet.compact(); fEndWordSet.compact(); fBeginWordSet.compact(); + UTRACE_EXIT_STATUS(status); } LaoBreakEngine::~LaoBreakEngine() { @@ -632,6 +639,8 @@ BurmeseBreakEngine::BurmeseBreakEngine(DictionaryMatcher *adoptDictionary, UErro : DictionaryBreakEngine(), fDictionary(adoptDictionary) { + UTRACE_ENTRY(UTRACE_UBRK_CREATE_BREAK_ENGINE); + UTRACE_DATA1(UTRACE_INFO, "dictbe=%s", "Mymr"); fBurmeseWordSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Mymr:]&[:LineBreak=SA:]]"), status); if (U_SUCCESS(status)) { setCharacters(fBurmeseWordSet); @@ -645,6 +654,7 @@ BurmeseBreakEngine::BurmeseBreakEngine(DictionaryMatcher *adoptDictionary, UErro fMarkSet.compact(); fEndWordSet.compact(); fBeginWordSet.compact(); + UTRACE_EXIT_STATUS(status); } BurmeseBreakEngine::~BurmeseBreakEngine() { @@ -825,6 +835,8 @@ KhmerBreakEngine::KhmerBreakEngine(DictionaryMatcher *adoptDictionary, UErrorCod : DictionaryBreakEngine(), fDictionary(adoptDictionary) { + UTRACE_ENTRY(UTRACE_UBRK_CREATE_BREAK_ENGINE); + UTRACE_DATA1(UTRACE_INFO, "dictbe=%s", "Khmr"); fKhmerWordSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Khmr:]&[:LineBreak=SA:]]"), status); if (U_SUCCESS(status)) { setCharacters(fKhmerWordSet); @@ -850,6 +862,7 @@ KhmerBreakEngine::KhmerBreakEngine(DictionaryMatcher *adoptDictionary, UErrorCod fEndWordSet.compact(); fBeginWordSet.compact(); // fSuffixSet.compact(); + UTRACE_EXIT_STATUS(status); } KhmerBreakEngine::~KhmerBreakEngine() { @@ -1045,6 +1058,8 @@ KhmerBreakEngine::divideUpDictionaryRange( UText *text, static const uint32_t kuint32max = 0xFFFFFFFF; CjkBreakEngine::CjkBreakEngine(DictionaryMatcher *adoptDictionary, LanguageType type, UErrorCode &status) : DictionaryBreakEngine(), fDictionary(adoptDictionary) { + UTRACE_ENTRY(UTRACE_UBRK_CREATE_BREAK_ENGINE); + UTRACE_DATA1(UTRACE_INFO, "dictbe=%s", "Hani"); // Korean dictionary only includes Hangul syllables fHangulWordSet.applyPattern(UNICODE_STRING_SIMPLE("[\\uac00-\\ud7a3]"), status); fHanWordSet.applyPattern(UNICODE_STRING_SIMPLE("[:Han:]"), status); @@ -1066,6 +1081,7 @@ CjkBreakEngine::CjkBreakEngine(DictionaryMatcher *adoptDictionary, LanguageType setCharacters(cjSet); } } + UTRACE_EXIT_STATUS(status); } CjkBreakEngine::~CjkBreakEngine(){ diff --git a/deps/icu-small/source/common/localematcher.cpp b/deps/icu-small/source/common/localematcher.cpp index d975fe759b4ce1..85db8c8bf3246d 100644 --- a/deps/icu-small/source/common/localematcher.cpp +++ b/deps/icu-small/source/common/localematcher.cpp @@ -12,6 +12,7 @@ #include "unicode/localematcher.h" #include "unicode/locid.h" #include "unicode/stringpiece.h" +#include "unicode/uloc.h" #include "unicode/uobject.h" #include "cstring.h" #include "localeprioritylist.h" @@ -20,9 +21,10 @@ #include "lsr.h" #include "uassert.h" #include "uhash.h" +#include "ustr_imp.h" #include "uvector.h" -#define UND_LSR LSR("und", "", "") +#define UND_LSR LSR("und", "", "", LSR::EXPLICIT_LSR) /** * Indicator for the lifetime of desired-locale objects passed into the LocaleMatcher. @@ -129,7 +131,8 @@ LocaleMatcher::Builder::Builder(LocaleMatcher::Builder &&src) U_NOEXCEPT : thresholdDistance_(src.thresholdDistance_), demotion_(src.demotion_), defaultLocale_(src.defaultLocale_), - favor_(src.favor_) { + favor_(src.favor_), + direction_(src.direction_) { src.supportedLocales_ = nullptr; src.defaultLocale_ = nullptr; } @@ -148,6 +151,7 @@ LocaleMatcher::Builder &LocaleMatcher::Builder::operator=(LocaleMatcher::Builder demotion_ = src.demotion_; defaultLocale_ = src.defaultLocale_; favor_ = src.favor_; + direction_ = src.direction_; src.supportedLocales_ = nullptr; src.defaultLocale_ = nullptr; @@ -308,38 +312,53 @@ UBool compareLSRs(const UHashTok t1, const UHashTok t2) { return *lsr1 == *lsr2; } -bool putIfAbsent(UHashtable *lsrToIndex, const LSR &lsr, int32_t i, UErrorCode &errorCode) { - if (U_FAILURE(errorCode)) { return false; } - U_ASSERT(i > 0); - int32_t index = uhash_geti(lsrToIndex, &lsr); - if (index != 0) { - return false; - } else { - uhash_puti(lsrToIndex, const_cast(&lsr), i, &errorCode); - return U_SUCCESS(errorCode); +} // namespace + +int32_t LocaleMatcher::putIfAbsent(const LSR &lsr, int32_t i, int32_t suppLength, + UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { return suppLength; } + int32_t index = uhash_geti(supportedLsrToIndex, &lsr); + if (index == 0) { + uhash_puti(supportedLsrToIndex, const_cast(&lsr), i + 1, &errorCode); + if (U_SUCCESS(errorCode)) { + supportedLSRs[suppLength] = &lsr; + supportedIndexes[suppLength++] = i; + } } + return suppLength; } -} // namespace - LocaleMatcher::LocaleMatcher(const Builder &builder, UErrorCode &errorCode) : likelySubtags(*XLikelySubtags::getSingleton(errorCode)), localeDistance(*LocaleDistance::getSingleton(errorCode)), thresholdDistance(builder.thresholdDistance_), demotionPerDesiredLocale(0), favorSubtag(builder.favor_), + direction(builder.direction_), supportedLocales(nullptr), lsrs(nullptr), supportedLocalesLength(0), supportedLsrToIndex(nullptr), supportedLSRs(nullptr), supportedIndexes(nullptr), supportedLSRsLength(0), - ownedDefaultLocale(nullptr), defaultLocale(nullptr), defaultLocaleIndex(-1) { + ownedDefaultLocale(nullptr), defaultLocale(nullptr) { if (U_FAILURE(errorCode)) { return; } if (thresholdDistance < 0) { thresholdDistance = localeDistance.getDefaultScriptDistance(); } + const Locale *def = builder.defaultLocale_; + LSR builderDefaultLSR; + const LSR *defLSR = nullptr; + if (def != nullptr) { + ownedDefaultLocale = def->clone(); + if (ownedDefaultLocale == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; + } + def = ownedDefaultLocale; + builderDefaultLSR = getMaximalLsrOrUnd(likelySubtags, *def, errorCode); + if (U_FAILURE(errorCode)) { return; } + defLSR = &builderDefaultLSR; + } supportedLocalesLength = builder.supportedLocales_ != nullptr ? builder.supportedLocales_->size() : 0; - const Locale *def = builder.defaultLocale_; - int32_t idef = -1; if (supportedLocalesLength > 0) { // Store the supported locales in input order, // so that when different types are used (e.g., language tag strings) @@ -356,15 +375,6 @@ LocaleMatcher::LocaleMatcher(const Builder &builder, UErrorCode &errorCode) : } // If the constructor fails partway, we need null pointers for destructibility. uprv_memset(supportedLocales, 0, supportedLocalesLength * sizeof(const Locale *)); - // Also find the first supported locale whose LSR is - // the same as that for the default locale. - LSR builderDefaultLSR; - const LSR *defLSR = nullptr; - if (def != nullptr) { - builderDefaultLSR = getMaximalLsrOrUnd(likelySubtags, *def, errorCode); - if (U_FAILURE(errorCode)) { return; } - defLSR = &builderDefaultLSR; - } for (int32_t i = 0; i < supportedLocalesLength; ++i) { const Locale &locale = *static_cast(builder.supportedLocales_->elementAt(i)); supportedLocales[i] = locale.clone(); @@ -376,103 +386,74 @@ LocaleMatcher::LocaleMatcher(const Builder &builder, UErrorCode &errorCode) : LSR &lsr = lsrs[i] = getMaximalLsrOrUnd(likelySubtags, supportedLocale, errorCode); lsr.setHashCode(); if (U_FAILURE(errorCode)) { return; } - if (idef < 0 && defLSR != nullptr && lsr == *defLSR) { - idef = i; - defLSR = &lsr; // owned pointer to put into supportedLsrToIndex - if (*def == supportedLocale) { - def = &supportedLocale; // owned pointer to keep - } - } } // We need an unordered map from LSR to first supported locale with that LSR, - // and an ordered list of (LSR, supported index). - // We insert the supported locales in the following order: + // and an ordered list of (LSR, supported index) for + // the supported locales in the following order: // 1. Default locale, if it is supported. // 2. Priority locales (aka "paradigm locales") in builder order. // 3. Remaining locales in builder order. - // In Java, we use a LinkedHashMap for both map & ordered lists. - // In C++, we use separate structures. - // We over-allocate arrays of LSRs and indexes for simplicity. - // We reserve slots at the array starts for the default and paradigm locales, - // plus enough for all supported locales. - // If there are few paradigm locales and few duplicate supported LSRs, - // then the amount of wasted space is small. supportedLsrToIndex = uhash_openSize(hashLSR, compareLSRs, uhash_compareLong, supportedLocalesLength, &errorCode); if (U_FAILURE(errorCode)) { return; } - int32_t paradigmLimit = 1 + localeDistance.getParadigmLSRsLength(); - int32_t suppLSRsCapacity = paradigmLimit + supportedLocalesLength; supportedLSRs = static_cast( - uprv_malloc(suppLSRsCapacity * sizeof(const LSR *))); + uprv_malloc(supportedLocalesLength * sizeof(const LSR *))); supportedIndexes = static_cast( - uprv_malloc(suppLSRsCapacity * sizeof(int32_t))); + uprv_malloc(supportedLocalesLength * sizeof(int32_t))); if (supportedLSRs == nullptr || supportedIndexes == nullptr) { errorCode = U_MEMORY_ALLOCATION_ERROR; return; } - int32_t paradigmIndex = 0; - int32_t otherIndex = paradigmLimit; - if (idef >= 0) { - uhash_puti(supportedLsrToIndex, const_cast(defLSR), idef + 1, &errorCode); - supportedLSRs[0] = defLSR; - supportedIndexes[0] = idef; - paradigmIndex = 1; + int32_t suppLength = 0; + // Determine insertion order. + // Add locales immediately that are equivalent to the default. + MaybeStackArray order(supportedLocalesLength); + if (order.getAlias() == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; } + int32_t numParadigms = 0; for (int32_t i = 0; i < supportedLocalesLength; ++i) { - if (i == idef) { continue; } const Locale &locale = *supportedLocales[i]; const LSR &lsr = lsrs[i]; if (defLSR == nullptr) { U_ASSERT(i == 0); def = &locale; defLSR = &lsr; - idef = 0; - uhash_puti(supportedLsrToIndex, const_cast(&lsr), 0 + 1, &errorCode); - supportedLSRs[0] = &lsr; - supportedIndexes[0] = 0; - paradigmIndex = 1; - } else if (idef >= 0 && lsr == *defLSR) { - // lsr == *defLSR means that this supported locale is - // a duplicate of the default locale. - // Either an explicit default locale is supported, and we added it before the loop, - // or there is no explicit default locale, and this is - // a duplicate of the first supported locale. - // In both cases, idef >= 0 now, so otherwise we can skip the comparison. - // For a duplicate, putIfAbsent() is a no-op, so nothing to do. + order[i] = 1; + suppLength = putIfAbsent(lsr, 0, suppLength, errorCode); + } else if (lsr.isEquivalentTo(*defLSR)) { + order[i] = 1; + suppLength = putIfAbsent(lsr, i, suppLength, errorCode); + } else if (localeDistance.isParadigmLSR(lsr)) { + order[i] = 2; + ++numParadigms; } else { - if (putIfAbsent(supportedLsrToIndex, lsr, i + 1, errorCode)) { - if (localeDistance.isParadigmLSR(lsr)) { - supportedLSRs[paradigmIndex] = &lsr; - supportedIndexes[paradigmIndex++] = i; - } else { - supportedLSRs[otherIndex] = &lsr; - supportedIndexes[otherIndex++] = i; - } - } + order[i] = 3; } if (U_FAILURE(errorCode)) { return; } } - // Squeeze out unused array slots. - if (paradigmIndex < paradigmLimit && paradigmLimit < otherIndex) { - uprv_memmove(supportedLSRs + paradigmIndex, supportedLSRs + paradigmLimit, - (otherIndex - paradigmLimit) * sizeof(const LSR *)); - uprv_memmove(supportedIndexes + paradigmIndex, supportedIndexes + paradigmLimit, - (otherIndex - paradigmLimit) * sizeof(int32_t)); + // Add supported paradigm locales. + int32_t paradigmLimit = suppLength + numParadigms; + for (int32_t i = 0; i < supportedLocalesLength && suppLength < paradigmLimit; ++i) { + if (order[i] == 2) { + suppLength = putIfAbsent(lsrs[i], i, suppLength, errorCode); + } } - supportedLSRsLength = otherIndex - (paradigmLimit - paradigmIndex); - } - - if (def != nullptr && (idef < 0 || def != supportedLocales[idef])) { - ownedDefaultLocale = def->clone(); - if (ownedDefaultLocale == nullptr) { - errorCode = U_MEMORY_ALLOCATION_ERROR; - return; + // Add remaining supported locales. + for (int32_t i = 0; i < supportedLocalesLength; ++i) { + if (order[i] == 3) { + suppLength = putIfAbsent(lsrs[i], i, suppLength, errorCode); + } } - def = ownedDefaultLocale; + supportedLSRsLength = suppLength; + // If supportedLSRsLength < supportedLocalesLength then + // we waste as many array slots as there are duplicate supported LSRs, + // but the amount of wasted space is small as long as there are few duplicates. } + defaultLocale = def; - defaultLocaleIndex = idef; if (builder.demotion_ == ULOCMATCH_DEMOTION_REGION) { demotionPerDesiredLocale = localeDistance.getDefaultDemotionPerDesiredLocale(); @@ -485,14 +466,14 @@ LocaleMatcher::LocaleMatcher(LocaleMatcher &&src) U_NOEXCEPT : thresholdDistance(src.thresholdDistance), demotionPerDesiredLocale(src.demotionPerDesiredLocale), favorSubtag(src.favorSubtag), + direction(src.direction), supportedLocales(src.supportedLocales), lsrs(src.lsrs), supportedLocalesLength(src.supportedLocalesLength), supportedLsrToIndex(src.supportedLsrToIndex), supportedLSRs(src.supportedLSRs), supportedIndexes(src.supportedIndexes), supportedLSRsLength(src.supportedLSRsLength), - ownedDefaultLocale(src.ownedDefaultLocale), defaultLocale(src.defaultLocale), - defaultLocaleIndex(src.defaultLocaleIndex) { + ownedDefaultLocale(src.ownedDefaultLocale), defaultLocale(src.defaultLocale) { src.supportedLocales = nullptr; src.lsrs = nullptr; src.supportedLocalesLength = 0; @@ -502,7 +483,6 @@ LocaleMatcher::LocaleMatcher(LocaleMatcher &&src) U_NOEXCEPT : src.supportedLSRsLength = 0; src.ownedDefaultLocale = nullptr; src.defaultLocale = nullptr; - src.defaultLocaleIndex = -1; } LocaleMatcher::~LocaleMatcher() { @@ -523,6 +503,7 @@ LocaleMatcher &LocaleMatcher::operator=(LocaleMatcher &&src) U_NOEXCEPT { thresholdDistance = src.thresholdDistance; demotionPerDesiredLocale = src.demotionPerDesiredLocale; favorSubtag = src.favorSubtag; + direction = src.direction; supportedLocales = src.supportedLocales; lsrs = src.lsrs; supportedLocalesLength = src.supportedLocalesLength; @@ -532,7 +513,6 @@ LocaleMatcher &LocaleMatcher::operator=(LocaleMatcher &&src) U_NOEXCEPT { supportedLSRsLength = src.supportedLSRsLength; ownedDefaultLocale = src.ownedDefaultLocale; defaultLocale = src.defaultLocale; - defaultLocaleIndex = src.defaultLocaleIndex; src.supportedLocales = nullptr; src.lsrs = nullptr; @@ -543,7 +523,6 @@ LocaleMatcher &LocaleMatcher::operator=(LocaleMatcher &&src) U_NOEXCEPT { src.supportedLSRsLength = 0; src.ownedDefaultLocale = nullptr; src.defaultLocale = nullptr; - src.defaultLocaleIndex = -1; return *this; } @@ -630,13 +609,13 @@ const Locale *LocaleMatcher::getBestMatchForListString( LocaleMatcher::Result LocaleMatcher::getBestMatchResult( const Locale &desiredLocale, UErrorCode &errorCode) const { if (U_FAILURE(errorCode)) { - return Result(nullptr, defaultLocale, -1, defaultLocaleIndex, FALSE); + return Result(nullptr, defaultLocale, -1, -1, FALSE); } int32_t suppIndex = getBestSuppIndex( getMaximalLsrOrUnd(likelySubtags, desiredLocale, errorCode), nullptr, errorCode); if (U_FAILURE(errorCode) || suppIndex < 0) { - return Result(nullptr, defaultLocale, -1, defaultLocaleIndex, FALSE); + return Result(nullptr, defaultLocale, -1, -1, FALSE); } else { return Result(&desiredLocale, supportedLocales[suppIndex], 0, suppIndex, FALSE); } @@ -645,12 +624,12 @@ LocaleMatcher::Result LocaleMatcher::getBestMatchResult( LocaleMatcher::Result LocaleMatcher::getBestMatchResult( Locale::Iterator &desiredLocales, UErrorCode &errorCode) const { if (U_FAILURE(errorCode) || !desiredLocales.hasNext()) { - return Result(nullptr, defaultLocale, -1, defaultLocaleIndex, FALSE); + return Result(nullptr, defaultLocale, -1, -1, FALSE); } LocaleLsrIterator lsrIter(likelySubtags, desiredLocales, ULOCMATCH_TEMPORARY_LOCALES); int32_t suppIndex = getBestSuppIndex(lsrIter.next(errorCode), &lsrIter, errorCode); if (U_FAILURE(errorCode) || suppIndex < 0) { - return Result(nullptr, defaultLocale, -1, defaultLocaleIndex, FALSE); + return Result(nullptr, defaultLocale, -1, -1, FALSE); } else { return Result(lsrIter.orphanRemembered(), supportedLocales[suppIndex], lsrIter.getBestDesiredIndex(), suppIndex, TRUE); @@ -662,7 +641,7 @@ int32_t LocaleMatcher::getBestSuppIndex(LSR desiredLSR, LocaleLsrIterator *remai if (U_FAILURE(errorCode)) { return -1; } int32_t desiredIndex = 0; int32_t bestSupportedLsrIndex = -1; - for (int32_t bestDistance = thresholdDistance;;) { + for (int32_t bestShiftedDistance = LocaleDistance::shiftDistance(thresholdDistance);;) { // Quick check for exact maximized LSR. // Returns suppIndex+1 where 0 means not found. if (supportedLsrToIndex != nullptr) { @@ -677,16 +656,17 @@ int32_t LocaleMatcher::getBestSuppIndex(LSR desiredLSR, LocaleLsrIterator *remai } } int32_t bestIndexAndDistance = localeDistance.getBestIndexAndDistance( - desiredLSR, supportedLSRs, supportedLSRsLength, bestDistance, favorSubtag); + desiredLSR, supportedLSRs, supportedLSRsLength, + bestShiftedDistance, favorSubtag, direction); if (bestIndexAndDistance >= 0) { - bestDistance = bestIndexAndDistance & 0xff; + bestShiftedDistance = LocaleDistance::getShiftedDistance(bestIndexAndDistance); if (remainingIter != nullptr) { remainingIter->rememberCurrent(desiredIndex, errorCode); if (U_FAILURE(errorCode)) { return -1; } } - bestSupportedLsrIndex = bestIndexAndDistance >= 0 ? bestIndexAndDistance >> 8 : -1; + bestSupportedLsrIndex = LocaleDistance::getIndex(bestIndexAndDistance); } - if ((bestDistance -= demotionPerDesiredLocale) <= 0) { + if ((bestShiftedDistance -= LocaleDistance::shiftDistance(demotionPerDesiredLocale)) <= 0) { break; } if (remainingIter == nullptr || !remainingIter->hasNext()) { @@ -708,13 +688,107 @@ double LocaleMatcher::internalMatch(const Locale &desired, const Locale &support LSR suppLSR = getMaximalLsrOrUnd(likelySubtags, supported, errorCode); if (U_FAILURE(errorCode)) { return 0; } const LSR *pSuppLSR = &suppLSR; - int32_t distance = localeDistance.getBestIndexAndDistance( + int32_t indexAndDistance = localeDistance.getBestIndexAndDistance( getMaximalLsrOrUnd(likelySubtags, desired, errorCode), &pSuppLSR, 1, - thresholdDistance, favorSubtag) & 0xff; - return (100 - distance) / 100.0; + LocaleDistance::shiftDistance(thresholdDistance), favorSubtag, direction); + double distance = LocaleDistance::getDistanceDouble(indexAndDistance); + return (100.0 - distance) / 100.0; } U_NAMESPACE_END +// uloc_acceptLanguage() --------------------------------------------------- *** + +U_NAMESPACE_USE + +namespace { + +class LocaleFromTag { +public: + LocaleFromTag() : locale(Locale::getRoot()) {} + const Locale &operator()(const char *tag) { return locale = Locale(tag); } + +private: + // Store the locale in the converter, rather than return a reference to a temporary, + // or a value which could go out of scope with the caller's reference to it. + Locale locale; +}; + +int32_t acceptLanguage(UEnumeration &supportedLocales, Locale::Iterator &desiredLocales, + char *dest, int32_t capacity, UAcceptResult *acceptResult, + UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { return 0; } + LocaleMatcher::Builder builder; + const char *locString; + while ((locString = uenum_next(&supportedLocales, nullptr, &errorCode)) != nullptr) { + Locale loc(locString); + if (loc.isBogus()) { + errorCode = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + builder.addSupportedLocale(loc); + } + LocaleMatcher matcher = builder.build(errorCode); + LocaleMatcher::Result result = matcher.getBestMatchResult(desiredLocales, errorCode); + if (U_FAILURE(errorCode)) { return 0; } + if (result.getDesiredIndex() >= 0) { + if (acceptResult != nullptr) { + *acceptResult = *result.getDesiredLocale() == *result.getSupportedLocale() ? + ULOC_ACCEPT_VALID : ULOC_ACCEPT_FALLBACK; + } + const char *bestStr = result.getSupportedLocale()->getName(); + int32_t bestLength = (int32_t)uprv_strlen(bestStr); + if (bestLength <= capacity) { + uprv_memcpy(dest, bestStr, bestLength); + } + return u_terminateChars(dest, capacity, bestLength, &errorCode); + } else { + if (acceptResult != nullptr) { + *acceptResult = ULOC_ACCEPT_FAILED; + } + return u_terminateChars(dest, capacity, 0, &errorCode); + } +} + +} // namespace + +U_CAPI int32_t U_EXPORT2 +uloc_acceptLanguage(char *result, int32_t resultAvailable, + UAcceptResult *outResult, + const char **acceptList, int32_t acceptListCount, + UEnumeration *availableLocales, + UErrorCode *status) { + if (U_FAILURE(*status)) { return 0; } + if ((result == nullptr ? resultAvailable != 0 : resultAvailable < 0) || + (acceptList == nullptr ? acceptListCount != 0 : acceptListCount < 0) || + availableLocales == nullptr) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + LocaleFromTag converter; + Locale::ConvertingIterator desiredLocales( + acceptList, acceptList + acceptListCount, converter); + return acceptLanguage(*availableLocales, desiredLocales, + result, resultAvailable, outResult, *status); +} + +U_CAPI int32_t U_EXPORT2 +uloc_acceptLanguageFromHTTP(char *result, int32_t resultAvailable, + UAcceptResult *outResult, + const char *httpAcceptLanguage, + UEnumeration *availableLocales, + UErrorCode *status) { + if (U_FAILURE(*status)) { return 0; } + if ((result == nullptr ? resultAvailable != 0 : resultAvailable < 0) || + httpAcceptLanguage == nullptr || availableLocales == nullptr) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + LocalePriorityList list(httpAcceptLanguage, *status); + LocalePriorityList::Iterator desiredLocales = list.iterator(); + return acceptLanguage(*availableLocales, desiredLocales, + result, resultAvailable, outResult, *status); +} + #endif // __LOCMATCHER_H__ diff --git a/deps/icu-small/source/common/localeprioritylist.cpp b/deps/icu-small/source/common/localeprioritylist.cpp index 06442fb46a83ad..cee408269c9b39 100644 --- a/deps/icu-small/source/common/localeprioritylist.cpp +++ b/deps/icu-small/source/common/localeprioritylist.cpp @@ -133,7 +133,7 @@ LocalePriorityList::LocalePriorityList(StringPiece s, UErrorCode &errorCode) { if (U_FAILURE(errorCode)) { return; } Locale locale = Locale(tag.data()); if (locale.isBogus()) { - errorCode = U_MEMORY_ALLOCATION_ERROR; + errorCode = U_ILLEGAL_ARGUMENT_ERROR; return; } int32_t weight = WEIGHT_ONE; diff --git a/deps/icu-small/source/common/locdistance.cpp b/deps/icu-small/source/common/locdistance.cpp index 800d0eacf2b605..18e4d91bce921b 100644 --- a/deps/icu-small/source/common/locdistance.cpp +++ b/deps/icu-small/source/common/locdistance.cpp @@ -69,7 +69,7 @@ void U_CALLCONV LocaleDistance::initLocaleDistance(UErrorCode &errorCode) { errorCode = U_MISSING_RESOURCE_ERROR; return; } - gLocaleDistance = new LocaleDistance(data); + gLocaleDistance = new LocaleDistance(data, likely); if (gLocaleDistance == nullptr) { errorCode = U_MEMORY_ALLOCATION_ERROR; return; @@ -83,7 +83,8 @@ const LocaleDistance *LocaleDistance::getSingleton(UErrorCode &errorCode) { return gLocaleDistance; } -LocaleDistance::LocaleDistance(const LocaleDistanceData &data) : +LocaleDistance::LocaleDistance(const LocaleDistanceData &data, const XLikelySubtags &likely) : + likelySubtags(likely), trie(data.distanceTrieBytes), regionToPartitionsIndex(data.regionToPartitions), partitionArrays(data.partitions), paradigmLSRs(data.paradigms), paradigmLSRsLength(data.paradigmsLength), @@ -97,17 +98,19 @@ LocaleDistance::LocaleDistance(const LocaleDistanceData &data) : // a mere region difference for one desired locale // is as good as a perfect match for the next following desired locale. // As of CLDR 36, we have . - LSR en("en", "Latn", "US"); - LSR enGB("en", "Latn", "GB"); + LSR en("en", "Latn", "US", LSR::EXPLICIT_LSR); + LSR enGB("en", "Latn", "GB", LSR::EXPLICIT_LSR); const LSR *p_enGB = &enGB; - defaultDemotionPerDesiredLocale = getBestIndexAndDistance(en, &p_enGB, 1, - 50, ULOCMATCH_FAVOR_LANGUAGE) & 0xff; + int32_t indexAndDistance = getBestIndexAndDistance(en, &p_enGB, 1, + shiftDistance(50), ULOCMATCH_FAVOR_LANGUAGE, ULOCMATCH_DIRECTION_WITH_ONE_WAY); + defaultDemotionPerDesiredLocale = getDistanceFloor(indexAndDistance); } int32_t LocaleDistance::getBestIndexAndDistance( const LSR &desired, const LSR **supportedLSRs, int32_t supportedLSRsLength, - int32_t threshold, ULocMatchFavorSubtag favorSubtag) const { + int32_t shiftedThreshold, + ULocMatchFavorSubtag favorSubtag, ULocMatchDirection direction) const { BytesTrie iter(trie); // Look up the desired language only once for all supported LSRs. // Its "distance" is either a match point value of 0, or a non-match negative value. @@ -116,6 +119,8 @@ int32_t LocaleDistance::getBestIndexAndDistance( uint64_t desLangState = desLangDistance >= 0 && supportedLSRsLength > 1 ? iter.getState64() : 0; // Index of the supported LSR with the lowest distance. int32_t bestIndex = -1; + // Cached lookup info from XLikelySubtags.compareLikely(). + int32_t bestLikelyInfo = -1; for (int32_t slIndex = 0; slIndex < supportedLSRsLength; ++slIndex) { const LSR &supported = *supportedLSRs[slIndex]; bool star = false; @@ -145,6 +150,11 @@ int32_t LocaleDistance::getBestIndexAndDistance( star = true; } U_ASSERT(0 <= distance && distance <= 100); + // Round up the shifted threshold (if fraction bits are not 0) + // for comparison with un-shifted distances until we need fraction bits. + // (If we simply shifted non-zero fraction bits away, then we might ignore a language + // when it's really still a micro distance below the threshold.) + int32_t roundedThreshold = (shiftedThreshold + DISTANCE_FRACTION_MASK) >> DISTANCE_SHIFT; // We implement "favor subtag" by reducing the language subtag distance // (unscientifically reducing it to a quarter of the normal value), // so that the script distance is relatively more important. @@ -153,7 +163,9 @@ int32_t LocaleDistance::getBestIndexAndDistance( if (favorSubtag == ULOCMATCH_FAVOR_SCRIPT) { distance >>= 2; } - if (distance >= threshold) { + // Let distance == roundedThreshold pass until the tie-breaker logic + // at the end of the loop. + if (distance > roundedThreshold) { continue; } @@ -171,7 +183,7 @@ int32_t LocaleDistance::getBestIndexAndDistance( scriptDistance &= ~DISTANCE_IS_FINAL; } distance += scriptDistance; - if (distance >= threshold) { + if (distance > roundedThreshold) { continue; } @@ -180,8 +192,8 @@ int32_t LocaleDistance::getBestIndexAndDistance( } else if (star || (flags & DISTANCE_IS_FINAL) != 0) { distance += defaultRegionDistance; } else { - int32_t remainingThreshold = threshold - distance; - if (minRegionDistance >= remainingThreshold) { + int32_t remainingThreshold = roundedThreshold - distance; + if (minRegionDistance > remainingThreshold) { continue; } @@ -196,15 +208,51 @@ int32_t LocaleDistance::getBestIndexAndDistance( partitionsForRegion(supported), remainingThreshold); } - if (distance < threshold) { - if (distance == 0) { - return slIndex << 8; + int32_t shiftedDistance = shiftDistance(distance); + if (shiftedDistance == 0) { + // Distinguish between equivalent but originally unequal locales via an + // additional micro distance. + shiftedDistance |= (desired.flags ^ supported.flags); + if (shiftedDistance < shiftedThreshold) { + if (direction != ULOCMATCH_DIRECTION_ONLY_TWO_WAY || + // Is there also a match when we swap desired/supported? + isMatch(supported, desired, shiftedThreshold, favorSubtag)) { + if (shiftedDistance == 0) { + return slIndex << INDEX_SHIFT; + } + bestIndex = slIndex; + shiftedThreshold = shiftedDistance; + bestLikelyInfo = -1; + } + } + } else { + if (shiftedDistance < shiftedThreshold) { + if (direction != ULOCMATCH_DIRECTION_ONLY_TWO_WAY || + // Is there also a match when we swap desired/supported? + isMatch(supported, desired, shiftedThreshold, favorSubtag)) { + bestIndex = slIndex; + shiftedThreshold = shiftedDistance; + bestLikelyInfo = -1; + } + } else if (shiftedDistance == shiftedThreshold && bestIndex >= 0) { + if (direction != ULOCMATCH_DIRECTION_ONLY_TWO_WAY || + // Is there also a match when we swap desired/supported? + isMatch(supported, desired, shiftedThreshold, favorSubtag)) { + bestLikelyInfo = likelySubtags.compareLikely( + supported, *supportedLSRs[bestIndex], bestLikelyInfo); + if ((bestLikelyInfo & 1) != 0) { + // This supported locale matches as well as the previous best match, + // and neither matches perfectly, + // but this one is "more likely" (has more-default subtags). + bestIndex = slIndex; + } + } } - bestIndex = slIndex; - threshold = distance; } } - return bestIndex >= 0 ? (bestIndex << 8) | threshold : 0xffffff00 | ABOVE_THRESHOLD; + return bestIndex >= 0 ? + (bestIndex << INDEX_SHIFT) | shiftedThreshold : + INDEX_NEG_1 | shiftDistance(ABOVE_THRESHOLD); } int32_t LocaleDistance::getDesSuppScriptDistance( @@ -273,7 +321,7 @@ int32_t LocaleDistance::getRegionPartitionsDistance( d = getFallbackRegionDistance(iter, startState); star = true; } - if (d >= threshold) { + if (d > threshold) { return d; } else if (regionDistance < d) { regionDistance = d; @@ -286,7 +334,7 @@ int32_t LocaleDistance::getRegionPartitionsDistance( } } else if (!star) { int32_t d = getFallbackRegionDistance(iter, startState); - if (d >= threshold) { + if (d > threshold) { return d; } else if (regionDistance < d) { regionDistance = d; @@ -352,11 +400,14 @@ int32_t LocaleDistance::trieNext(BytesTrie &iter, const char *s, bool wantValue) } UBool LocaleDistance::isParadigmLSR(const LSR &lsr) const { - // Linear search for a very short list (length 6 as of 2019). - // If there are many paradigm LSRs we should use a hash set. + // Linear search for a very short list (length 6 as of 2019), + // because we look for equivalence not equality, and + // because it's easy. + // If there are many paradigm LSRs we should use a hash set + // with custom comparator and hasher. U_ASSERT(paradigmLSRsLength <= 15); for (int32_t i = 0; i < paradigmLSRsLength; ++i) { - if (lsr == paradigmLSRs[i]) { return true; } + if (lsr.isEquivalentTo(paradigmLSRs[i])) { return true; } } return false; } diff --git a/deps/icu-small/source/common/locdistance.h b/deps/icu-small/source/common/locdistance.h index 7439f51c56bf8c..ad8415138333dc 100644 --- a/deps/icu-small/source/common/locdistance.h +++ b/deps/icu-small/source/common/locdistance.h @@ -26,19 +26,37 @@ class LocaleDistance final : public UMemory { public: static const LocaleDistance *getSingleton(UErrorCode &errorCode); + static int32_t shiftDistance(int32_t distance) { + return distance << DISTANCE_SHIFT; + } + + static int32_t getShiftedDistance(int32_t indexAndDistance) { + return indexAndDistance & DISTANCE_MASK; + } + + static double getDistanceDouble(int32_t indexAndDistance) { + double shiftedDistance = getShiftedDistance(indexAndDistance); + return shiftedDistance / (1 << DISTANCE_SHIFT); + } + + static int32_t getIndex(int32_t indexAndDistance) { + // assert indexAndDistance >= 0; + return indexAndDistance >> INDEX_SHIFT; + } + /** * Finds the supported LSR with the smallest distance from the desired one. * Equivalent LSR subtags must be normalized into a canonical form. * - *

Returns the index of the lowest-distance supported LSR in bits 31..8 + *

Returns the index of the lowest-distance supported LSR in the high bits * (negative if none has a distance below the threshold), - * and its distance (0..ABOVE_THRESHOLD) in bits 7..0. + * and its distance (0..ABOVE_THRESHOLD) in the low bits. */ int32_t getBestIndexAndDistance(const LSR &desired, const LSR **supportedLSRs, int32_t supportedLSRsLength, - int32_t threshold, ULocMatchFavorSubtag favorSubtag) const; - - int32_t getParadigmLSRsLength() const { return paradigmLSRsLength; } + int32_t shiftedThreshold, + ULocMatchFavorSubtag favorSubtag, + ULocMatchDirection direction) const; UBool isParadigmLSR(const LSR &lsr) const; @@ -51,12 +69,34 @@ class LocaleDistance final : public UMemory { } private: - LocaleDistance(const LocaleDistanceData &data); + // The distance is shifted left to gain some fraction bits. + static constexpr int32_t DISTANCE_SHIFT = 3; + static constexpr int32_t DISTANCE_FRACTION_MASK = 7; + // 7 bits for 0..100 + static constexpr int32_t DISTANCE_INT_SHIFT = 7; + static constexpr int32_t INDEX_SHIFT = DISTANCE_INT_SHIFT + DISTANCE_SHIFT; + static constexpr int32_t DISTANCE_MASK = 0x3ff; + // tic constexpr int32_t MAX_INDEX = 0x1fffff; // avoids sign bit + static constexpr int32_t INDEX_NEG_1 = 0xfffffc00; + + static int32_t getDistanceFloor(int32_t indexAndDistance) { + return (indexAndDistance & DISTANCE_MASK) >> DISTANCE_SHIFT; + } + + LocaleDistance(const LocaleDistanceData &data, const XLikelySubtags &likely); LocaleDistance(const LocaleDistance &other) = delete; LocaleDistance &operator=(const LocaleDistance &other) = delete; static void initLocaleDistance(UErrorCode &errorCode); + UBool isMatch(const LSR &desired, const LSR &supported, + int32_t shiftedThreshold, ULocMatchFavorSubtag favorSubtag) const { + const LSR *pSupp = &supported; + return getBestIndexAndDistance( + desired, &pSupp, 1, + shiftedThreshold, favorSubtag, ULOCMATCH_DIRECTION_WITH_ONE_WAY) >= 0; + } + static int32_t getDesSuppScriptDistance(BytesTrie &iter, uint64_t startState, const char *desired, const char *supported); @@ -79,6 +119,8 @@ class LocaleDistance final : public UMemory { return defaultRegionDistance; } + const XLikelySubtags &likelySubtags; + // The trie maps each dlang+slang+dscript+sscript+dregion+sregion // (encoded in ASCII with bit 7 set on the last character of each subtag) to a distance. // There is also a trie value for each subsequence of whole subtags. diff --git a/deps/icu-small/source/common/locid.cpp b/deps/icu-small/source/common/locid.cpp index c6c976394def4d..753a452120ee62 100644 --- a/deps/icu-small/source/common/locid.cpp +++ b/deps/icu-small/source/common/locid.cpp @@ -38,6 +38,7 @@ #include "unicode/strenum.h" #include "unicode/stringpiece.h" #include "unicode/uloc.h" +#include "unicode/ures.h" #include "bytesinkutil.h" #include "charstr.h" @@ -104,7 +105,6 @@ typedef enum ELocalePos { U_CFUNC int32_t locale_getKeywords(const char *localeID, char prev, char *keywords, int32_t keywordCapacity, - char *values, int32_t valuesCapacity, int32_t *valLen, UBool valuesToo, UErrorCode *status); @@ -184,17 +184,16 @@ Locale *locale_set_default_internal(const char *id, UErrorCode& status) { canonicalize = TRUE; // always canonicalize host ID } - char localeNameBuf[512]; - - if (canonicalize) { - uloc_canonicalize(id, localeNameBuf, sizeof(localeNameBuf)-1, &status); - } else { - uloc_getName(id, localeNameBuf, sizeof(localeNameBuf)-1, &status); + CharString localeNameBuf; + { + CharStringByteSink sink(&localeNameBuf); + if (canonicalize) { + ulocimp_canonicalize(id, sink, &status); + } else { + ulocimp_getName(id, sink, &status); + } } - localeNameBuf[sizeof(localeNameBuf)-1] = 0; // Force null termination in event of - // a long name filling the buffer. - // (long names are truncated.) - // + if (U_FAILURE(status)) { return gDefaultLocale; } @@ -208,14 +207,14 @@ Locale *locale_set_default_internal(const char *id, UErrorCode& status) { ucln_common_registerCleanup(UCLN_COMMON_LOCALE, locale_cleanup); } - Locale *newDefault = (Locale *)uhash_get(gDefaultLocalesHashT, localeNameBuf); + Locale *newDefault = (Locale *)uhash_get(gDefaultLocalesHashT, localeNameBuf.data()); if (newDefault == NULL) { newDefault = new Locale(Locale::eBOGUS); if (newDefault == NULL) { status = U_MEMORY_ALLOCATION_ERROR; return gDefaultLocale; } - newDefault->init(localeNameBuf, FALSE); + newDefault->init(localeNameBuf.data(), FALSE); uhash_put(gDefaultLocalesHashT, (char*) newDefault->getName(), newDefault, &status); if (U_FAILURE(status)) { return gDefaultLocale; @@ -509,6 +508,36 @@ Locale::operator==( const Locale& other) const #define ISASCIIALPHA(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z')) +namespace { + +CharString& AppendLSCVE(CharString& out, const char* language, const char* script, + const char* country, const char* variants, const char* extension, + UErrorCode& status) { + out.append(language, status); + if (script && script[0] != '\0') { + out.append('_', status); + out.append(script, status); + } + if (country && country[0] != '\0') { + out.append('_', status); + out.append(country, status); + } + if (variants && variants[0] != '\0') { + if ((script == nullptr || script[0] == '\0') && + (country == nullptr || country[0] == '\0')) { + out.append('_', status); + } + out.append('_', status); + out.append(variants, status); + } + if (extension && extension[0] != '\0') { + out.append(extension, status); + } + return out; +} + +} // namespace + /*This function initializes a Locale from a C locale ID*/ Locale& Locale::init(const char* localeID, UBool canonicalize) { @@ -632,6 +661,195 @@ Locale& Locale::init(const char* localeID, UBool canonicalize) break; } + if (canonicalize) { + UErrorCode status = U_ZERO_ERROR; + // TODO: Try to use ResourceDataValue and ures_getValueWithFallback() etc. + LocalUResourceBundlePointer metadata(ures_openDirect(NULL, "metadata", &status)); + LocalUResourceBundlePointer metadataAlias(ures_getByKey(metadata.getAlias(), "alias", NULL, &status)); + // Look up the metadata:alias:language:$key:replacement entries + // key could be one of the following: + // language + // language_Script_REGION + // language_REGION + // language_variant + do { + // The resource structure looks like + // metadata { + // alias { + // language { + // art_lojban { + // replacement{"jbo"} + // } + // ... + // ks_Arab_IN { + // replacement{"ks_IN"} + // } + // ... + // no { + // replacement{"nb"} + // } + // .... + // zh_CN { + // replacement{"zh_Hans_CN"} + // } + // } + // ... + // } + // } + LocalUResourceBundlePointer languageAlias(ures_getByKey(metadataAlias.getAlias(), "language", NULL, &status)); + if (U_FAILURE(status)) + break; + CharString temp; + // Handle cases of key pattern "language _ variant" + // ex: Map "art_lojban" to "jbo" + const char* variants = getVariant(); + if (variants != nullptr && variants[0] != '\0') { + const char* begin = variants; + const char* end = begin; + // We may have multiple variants, need to look at each of + // them. + do { + status = U_ZERO_ERROR; + end = uprv_strchr(begin, '_'); + int32_t len = (end == nullptr) ? int32_t(uprv_strlen(begin)) : int32_t(end - begin); + temp.clear().append(getLanguage(), status).append("_", status).append(begin, len, status); + LocalUResourceBundlePointer languageVariantAlias( + ures_getByKey(languageAlias.getAlias(), + temp.data(), + NULL, &status)); + temp.clear().appendInvariantChars( + UnicodeString(ures_getStringByKey(languageVariantAlias.getAlias(), "replacement", nullptr, &status)), status); + if (U_SUCCESS(status)) { + CharString newVar; + if (begin != variants) { + newVar.append(variants, static_cast(begin - variants - 1), status); + } + if (end != nullptr) { + if (begin != variants) { + newVar.append("_", status); + } + newVar.append(end + 1, status); + } + Locale l(temp.data()); + init(AppendLSCVE(temp.clear(), + l.getLanguage(), + (getScript() != nullptr && getScript()[0] != '\0') ? getScript() : l.getScript(), + (getCountry() != nullptr && getCountry()[0] != '\0') ? getCountry() : l.getCountry(), + newVar.data(), + uprv_strchr(fullName, '@'), status).data(), false); + break; + } + begin = end + 1; + } while (end != nullptr); + } // End of handle language _ variant + // Handle cases of key pattern "language _ Script _ REGION" + // ex: Map "ks_Arab_IN" to "ks_IN" + if (getScript() != nullptr && getScript()[0] != '\0' && + getCountry() != nullptr && getCountry()[0] != '\0') { + status = U_ZERO_ERROR; + LocalUResourceBundlePointer replacedAlias( + ures_getByKey(languageAlias.getAlias(), + AppendLSCVE(temp.clear(), getLanguage(), getScript(), getCountry(), + nullptr, nullptr, status).data(), NULL, &status)); + temp.clear().appendInvariantChars( + UnicodeString(ures_getStringByKey(replacedAlias.getAlias(), "replacement", nullptr, &status)), status); + if (U_SUCCESS(status)) { + Locale l(temp.data()); + init(AppendLSCVE(temp.clear(), + l.getLanguage(), + l.getScript(), + l.getCountry(), + getVariant(), + uprv_strchr(fullName, '@'), status).data(), false); + } + } // End of handle language _ Script _ REGION + // Handle cases of key pattern "language _ REGION" + // ex: Map "zh_CN" to "zh_Hans_CN" + if (getCountry() != nullptr && getCountry()[0] != '\0') { + status = U_ZERO_ERROR; + LocalUResourceBundlePointer replacedAlias( + ures_getByKey(languageAlias.getAlias(), + AppendLSCVE(temp.clear(), getLanguage(), nullptr, getCountry(), + nullptr, nullptr, status).data(), NULL, &status)); + temp.clear().appendInvariantChars( + UnicodeString(ures_getStringByKey(replacedAlias.getAlias(), "replacement", nullptr, &status)), status); + if (U_SUCCESS(status)) { + Locale l(temp.data()); + init(AppendLSCVE(temp.clear(), + l.getLanguage(), + (getScript() != nullptr && getScript()[0] != '\0') ? getScript() : l.getScript(), + l.getCountry(), + getVariant(), + uprv_strchr(fullName, '@'), status).data(), false); + } + } // End of handle "language _ REGION" + // Handle cases of key pattern "language" + // ex: Map "no" to "nb" + { + status = U_ZERO_ERROR; + LocalUResourceBundlePointer replaceLanguageAlias(ures_getByKey(languageAlias.getAlias(), getLanguage(), NULL, &status)); + temp.clear().appendInvariantChars( + UnicodeString(ures_getStringByKey(replaceLanguageAlias.getAlias(), "replacement", nullptr, &status)), status); + if (U_SUCCESS(status)) { + Locale l(temp.data()); + init(AppendLSCVE(temp.clear(), + l.getLanguage(), + (getScript() != nullptr && getScript()[0] != '\0') ? getScript() : l.getScript(), + (getCountry() != nullptr && getCountry()[0] != '\0') ? getCountry() : l.getCountry(), + getVariant(), + uprv_strchr(fullName, '@'), status).data(), false); + } + } // End of handle "language" + + // Look up the metadata:alias:territory:$key:replacement entries + // key is region code. + if (getCountry() != nullptr) { + status = U_ZERO_ERROR; + // The resource structure looks like + // metadata { + // alias { + // ... + // territory: { + // 172 { + // replacement{"RU AM AZ BY GE KG KZ MD TJ TM UA UZ"} + // } + // ... + // 554 { + // replacement{"NZ"} + // } + // } + // } + // } + LocalUResourceBundlePointer territoryAlias(ures_getByKey(metadataAlias.getAlias(), "territory", NULL, &status)); + LocalUResourceBundlePointer countryAlias(ures_getByKey(territoryAlias.getAlias(), getCountry(), NULL, &status)); + UnicodeString replacements( + ures_getStringByKey(countryAlias.getAlias(), "replacement", nullptr, &status)); + if (U_SUCCESS(status)) { + CharString replacedCountry; + int32_t delPos = replacements.indexOf(' '); + if (delPos == -1) { + replacedCountry.appendInvariantChars(replacements, status); + } else { + Locale l(AppendLSCVE(temp.clear(), getLanguage(), nullptr, getScript(), + nullptr, nullptr, status).data()); + l.addLikelySubtags(status); + if (replacements.indexOf(UnicodeString(l.getCountry())) != -1) { + replacedCountry.append(l.getCountry(), status); + } else { + replacedCountry.appendInvariantChars(replacements.getBuffer(), delPos, status); + } + } + init(AppendLSCVE(temp.clear(), + getLanguage(), + getScript(), + replacedCountry.data(), + getVariant(), + uprv_strchr(fullName, '@'), status).data(), false); + } + } // End of handle REGION + } while (0); + } // if (canonicalize) { + // successful end of init() return *this; } while(0); /*loop doesn't iterate*/ @@ -778,6 +996,25 @@ Locale::minimizeSubtags(UErrorCode& status) { } } +void +Locale::canonicalize(UErrorCode& status) { + if (U_FAILURE(status)) { + return; + } + if (isBogus()) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + CharString uncanonicalized(fullName, status); + if (U_FAILURE(status)) { + return; + } + init(uncanonicalized.data(), /*canonicalize=*/TRUE); + if (isBogus()) { + status = U_ILLEGAL_ARGUMENT_ERROR; + } +} + Locale U_EXPORT2 Locale::forLanguageTag(StringPiece tag, UErrorCode& status) { @@ -1189,7 +1426,7 @@ Locale::createKeywords(UErrorCode &status) const const char* assignment = uprv_strchr(fullName, '='); if(variantStart) { if(assignment > variantStart) { - int32_t keyLen = locale_getKeywords(variantStart+1, '@', keywords, keywordCapacity, NULL, 0, NULL, FALSE, &status); + int32_t keyLen = locale_getKeywords(variantStart+1, '@', keywords, keywordCapacity, FALSE, &status); if(U_SUCCESS(status) && keyLen) { result = new KeywordEnumeration(keywords, keyLen, 0, status); if (!result) { @@ -1218,7 +1455,7 @@ Locale::createUnicodeKeywords(UErrorCode &status) const const char* assignment = uprv_strchr(fullName, '='); if(variantStart) { if(assignment > variantStart) { - int32_t keyLen = locale_getKeywords(variantStart+1, '@', keywords, keywordCapacity, NULL, 0, NULL, FALSE, &status); + int32_t keyLen = locale_getKeywords(variantStart+1, '@', keywords, keywordCapacity, FALSE, &status); if(U_SUCCESS(status) && keyLen) { result = new UnicodeKeywordEnumeration(keywords, keyLen, 0, status); if (!result) { diff --git a/deps/icu-small/source/common/loclikelysubtags.cpp b/deps/icu-small/source/common/loclikelysubtags.cpp index d7f5e124c2c790..1fbf1a1463299f 100644 --- a/deps/icu-small/source/common/loclikelysubtags.cpp +++ b/deps/icu-small/source/common/loclikelysubtags.cpp @@ -250,7 +250,8 @@ struct XLikelySubtagsData { for (int32_t i = 0, j = 0; i < lsrSubtagsLength; i += 3, ++j) { lsrs[j] = LSR(strings.get(lsrSubtagIndexes[i]), strings.get(lsrSubtagIndexes[i + 1]), - strings.get(lsrSubtagIndexes[i + 2])); + strings.get(lsrSubtagIndexes[i + 2]), + LSR::IMPLICIT_LSR); } if (partitionsLength > 0) { @@ -275,7 +276,8 @@ struct XLikelySubtagsData { for (int32_t i = 0, j = 0; i < paradigmSubtagsLength; i += 3, ++j) { paradigms[j] = LSR(strings.get(paradigmSubtagIndexes[i]), strings.get(paradigmSubtagIndexes[i + 1]), - strings.get(paradigmSubtagIndexes[i + 2])); + strings.get(paradigmSubtagIndexes[i + 2]), + LSR::DONT_CARE_FLAGS); } distanceData.paradigms = paradigms; } @@ -383,7 +385,7 @@ LSR XLikelySubtags::makeMaximizedLsrFrom(const Locale &locale, UErrorCode &error const char *name = locale.getName(); if (uprv_isAtSign(name[0]) && name[1] == 'x' && name[2] == '=') { // name.startsWith("@x=") // Private use language tag x-subtag-subtag... - return LSR(name, "", ""); + return LSR(name, "", "", LSR::EXPLICIT_LSR); } return makeMaximizedLsr(locale.getLanguage(), locale.getScript(), locale.getCountry(), locale.getVariant(), errorCode); @@ -407,26 +409,31 @@ LSR XLikelySubtags::makeMaximizedLsr(const char *language, const char *script, c if (region[0] == 'X' && (c1 = region[1]) != 0 && region[2] == 0) { switch (c1) { case 'A': - return LSR(PSEUDO_ACCENTS_PREFIX, language, script, region, errorCode); + return LSR(PSEUDO_ACCENTS_PREFIX, language, script, region, + LSR::EXPLICIT_LSR, errorCode); case 'B': - return LSR(PSEUDO_BIDI_PREFIX, language, script, region, errorCode); + return LSR(PSEUDO_BIDI_PREFIX, language, script, region, + LSR::EXPLICIT_LSR, errorCode); case 'C': - return LSR(PSEUDO_CRACKED_PREFIX, language, script, region, errorCode); + return LSR(PSEUDO_CRACKED_PREFIX, language, script, region, + LSR::EXPLICIT_LSR, errorCode); default: // normal locale break; } } if (variant[0] == 'P' && variant[1] == 'S') { + int32_t lsrFlags = *region == 0 ? + LSR::EXPLICIT_LANGUAGE | LSR::EXPLICIT_SCRIPT : LSR::EXPLICIT_LSR; if (uprv_strcmp(variant, "PSACCENT") == 0) { return LSR(PSEUDO_ACCENTS_PREFIX, language, script, - *region == 0 ? "XA" : region, errorCode); + *region == 0 ? "XA" : region, lsrFlags, errorCode); } else if (uprv_strcmp(variant, "PSBIDI") == 0) { return LSR(PSEUDO_BIDI_PREFIX, language, script, - *region == 0 ? "XB" : region, errorCode); + *region == 0 ? "XB" : region, lsrFlags, errorCode); } else if (uprv_strcmp(variant, "PSCRACK") == 0) { return LSR(PSEUDO_CRACKED_PREFIX, language, script, - *region == 0 ? "XC" : region, errorCode); + *region == 0 ? "XC" : region, lsrFlags, errorCode); } // else normal locale } @@ -448,7 +455,7 @@ LSR XLikelySubtags::maximize(const char *language, const char *script, const cha region = ""; } if (*script != 0 && *region != 0 && *language != 0) { - return LSR(language, script, region); // already maximized + return LSR(language, script, region, LSR::EXPLICIT_LSR); // already maximized } uint32_t retainOldMask = 0; @@ -535,7 +542,7 @@ LSR XLikelySubtags::maximize(const char *language, const char *script, const cha if (retainOldMask == 0) { // Quickly return a copy of the lookup-result LSR // without new allocation of the subtags. - return LSR(result.language, result.script, result.region); + return LSR(result.language, result.script, result.region, result.flags); } if ((retainOldMask & 4) == 0) { language = result.language; @@ -546,7 +553,108 @@ LSR XLikelySubtags::maximize(const char *language, const char *script, const cha if ((retainOldMask & 1) == 0) { region = result.region; } - return LSR(language, script, region); + // retainOldMask flags = LSR explicit-subtag flags + return LSR(language, script, region, retainOldMask); +} + +int32_t XLikelySubtags::compareLikely(const LSR &lsr, const LSR &other, int32_t likelyInfo) const { + // If likelyInfo >= 0: + // likelyInfo bit 1 is set if the previous comparison with lsr + // was for equal language and script. + // Otherwise the scripts differed. + if (uprv_strcmp(lsr.language, other.language) != 0) { + return 0xfffffffc; // negative, lsr not better than other + } + if (uprv_strcmp(lsr.script, other.script) != 0) { + int32_t index; + if (likelyInfo >= 0 && (likelyInfo & 2) == 0) { + index = likelyInfo >> 2; + } else { + index = getLikelyIndex(lsr.language, ""); + likelyInfo = index << 2; + } + const LSR &likely = lsrs[index]; + if (uprv_strcmp(lsr.script, likely.script) == 0) { + return likelyInfo | 1; + } else { + return likelyInfo & ~1; + } + } + if (uprv_strcmp(lsr.region, other.region) != 0) { + int32_t index; + if (likelyInfo >= 0 && (likelyInfo & 2) != 0) { + index = likelyInfo >> 2; + } else { + index = getLikelyIndex(lsr.language, lsr.region); + likelyInfo = (index << 2) | 2; + } + const LSR &likely = lsrs[index]; + if (uprv_strcmp(lsr.region, likely.region) == 0) { + return likelyInfo | 1; + } else { + return likelyInfo & ~1; + } + } + return likelyInfo & ~1; // lsr not better than other +} + +// Subset of maximize(). +int32_t XLikelySubtags::getLikelyIndex(const char *language, const char *script) const { + if (uprv_strcmp(language, "und") == 0) { + language = ""; + } + if (uprv_strcmp(script, "Zzzz") == 0) { + script = ""; + } + + BytesTrie iter(trie); + uint64_t state; + int32_t value; + // Small optimization: Array lookup for first language letter. + int32_t c0; + if (0 <= (c0 = uprv_lowerOrdinal(language[0])) && c0 <= 25 && + language[1] != 0 && // language.length() >= 2 + (state = trieFirstLetterStates[c0]) != 0) { + value = trieNext(iter.resetToState64(state), language, 1); + } else { + value = trieNext(iter, language, 0); + } + if (value >= 0) { + state = iter.getState64(); + } else { + iter.resetToState64(trieUndState); // "und" ("*") + state = 0; + } + + if (value > 0) { + // Intermediate or final value from just language. + if (value == SKIP_SCRIPT) { + value = 0; + } + } else { + value = trieNext(iter, script, 0); + if (value >= 0) { + state = iter.getState64(); + } else { + if (state == 0) { + iter.resetToState64(trieUndZzzzState); // "und-Zzzz" ("**") + } else { + iter.resetToState64(state); + value = trieNext(iter, "", 0); + U_ASSERT(value >= 0); + state = iter.getState64(); + } + } + } + + if (value > 0) { + // Final value from just language or language+script. + } else { + value = trieNext(iter, "", 0); + U_ASSERT(value > 0); + } + U_ASSERT(value < lsrsLength); + return value; } int32_t XLikelySubtags::trieNext(BytesTrie &iter, const char *s, int32_t i) { @@ -615,9 +723,9 @@ LSR XLikelySubtags::minimizeSubtags(const char *languageIn, const char *scriptIn boolean favorRegionOk = false; if (result.script.equals(value00.script)) { //script is default if (result.region.equals(value00.region)) { - return new LSR(result.language, "", ""); + return new LSR(result.language, "", "", LSR.DONT_CARE_FLAGS); } else if (fieldToFavor == ULocale.Minimize.FAVOR_REGION) { - return new LSR(result.language, "", result.region); + return new LSR(result.language, "", result.region, LSR.DONT_CARE_FLAGS); } else { favorRegionOk = true; } @@ -627,9 +735,9 @@ LSR XLikelySubtags::minimizeSubtags(const char *languageIn, const char *scriptIn // Maybe do later, but for now use the straightforward code. LSR result2 = maximize(languageIn, scriptIn, ""); if (result2.equals(result)) { - return new LSR(result.language, result.script, ""); + return new LSR(result.language, result.script, "", LSR.DONT_CARE_FLAGS); } else if (favorRegionOk) { - return new LSR(result.language, "", result.region); + return new LSR(result.language, "", result.region, LSR.DONT_CARE_FLAGS); } return result; } diff --git a/deps/icu-small/source/common/loclikelysubtags.h b/deps/icu-small/source/common/loclikelysubtags.h index 8c8a08ac5e314e..90ddfffaca672d 100644 --- a/deps/icu-small/source/common/loclikelysubtags.h +++ b/deps/icu-small/source/common/loclikelysubtags.h @@ -85,6 +85,18 @@ class XLikelySubtags final : public UMemory { // VisibleForTesting LSR makeMaximizedLsrFrom(const Locale &locale, UErrorCode &errorCode) const; + /** + * Tests whether lsr is "more likely" than other. + * For example, fr-Latn-FR is more likely than fr-Latn-CH because + * FR is the default region for fr-Latn. + * + * The likelyInfo caches lookup information between calls. + * The return value is an updated likelyInfo value, + * with bit 0 set if lsr is "more likely". + * The initial value of likelyInfo must be negative. + */ + int32_t compareLikely(const LSR &lsr, const LSR &other, int32_t likelyInfo) const; + // TODO(ICU-20777): Switch Locale/uloc_ likely-subtags API from the old code // in loclikely.cpp to this new code, including activating this // minimizeSubtags() function. The LocaleMatcher does not minimize. @@ -111,6 +123,8 @@ class XLikelySubtags final : public UMemory { */ LSR maximize(const char *language, const char *script, const char *region) const; + int32_t getLikelyIndex(const char *language, const char *script) const; + static int32_t trieNext(BytesTrie &iter, const char *s, int32_t i); UResourceBundle *langInfoBundle; diff --git a/deps/icu-small/source/common/lsr.cpp b/deps/icu-small/source/common/lsr.cpp index 0c28eeda1bc7b6..d4308ad0275428 100644 --- a/deps/icu-small/source/common/lsr.cpp +++ b/deps/icu-small/source/common/lsr.cpp @@ -14,9 +14,10 @@ U_NAMESPACE_BEGIN -LSR::LSR(char prefix, const char *lang, const char *scr, const char *r, UErrorCode &errorCode) : +LSR::LSR(char prefix, const char *lang, const char *scr, const char *r, int32_t f, + UErrorCode &errorCode) : language(nullptr), script(nullptr), region(r), - regionIndex(indexForRegion(region)) { + regionIndex(indexForRegion(region)), flags(f) { if (U_SUCCESS(errorCode)) { CharString langScript; langScript.append(prefix, errorCode).append(lang, errorCode).append('\0', errorCode); @@ -32,7 +33,8 @@ LSR::LSR(char prefix, const char *lang, const char *scr, const char *r, UErrorCo LSR::LSR(LSR &&other) U_NOEXCEPT : language(other.language), script(other.script), region(other.region), owned(other.owned), - regionIndex(other.regionIndex), hashCode(other.hashCode) { + regionIndex(other.regionIndex), flags(other.flags), + hashCode(other.hashCode) { if (owned != nullptr) { other.language = other.script = ""; other.owned = nullptr; @@ -50,6 +52,7 @@ LSR &LSR::operator=(LSR &&other) U_NOEXCEPT { script = other.script; region = other.region; regionIndex = other.regionIndex; + flags = other.flags; owned = other.owned; hashCode = other.hashCode; if (owned != nullptr) { @@ -60,7 +63,7 @@ LSR &LSR::operator=(LSR &&other) U_NOEXCEPT { return *this; } -UBool LSR::operator==(const LSR &other) const { +UBool LSR::isEquivalentTo(const LSR &other) const { return uprv_strcmp(language, other.language) == 0 && uprv_strcmp(script, other.script) == 0 && @@ -69,6 +72,16 @@ UBool LSR::operator==(const LSR &other) const { (regionIndex > 0 || uprv_strcmp(region, other.region) == 0); } +UBool LSR::operator==(const LSR &other) const { + return + uprv_strcmp(language, other.language) == 0 && + uprv_strcmp(script, other.script) == 0 && + regionIndex == other.regionIndex && + // Compare regions if both are ill-formed (and their indexes are 0). + (regionIndex > 0 || uprv_strcmp(region, other.region) == 0) && + flags == other.flags; +} + int32_t LSR::indexForRegion(const char *region) { int32_t c = region[0]; int32_t a = c - '0'; @@ -90,10 +103,10 @@ int32_t LSR::indexForRegion(const char *region) { LSR &LSR::setHashCode() { if (hashCode == 0) { - hashCode = - (ustr_hashCharsN(language, static_cast(uprv_strlen(language))) * 37 + - ustr_hashCharsN(script, static_cast(uprv_strlen(script)))) * 37 + - regionIndex; + uint32_t h = ustr_hashCharsN(language, static_cast(uprv_strlen(language))); + h = h * 37 + ustr_hashCharsN(script, static_cast(uprv_strlen(script))); + h = h * 37 + regionIndex; + hashCode = h * 37 + flags; } return *this; } diff --git a/deps/icu-small/source/common/lsr.h b/deps/icu-small/source/common/lsr.h index db6cf938f47d02..d535e5b0376cd3 100644 --- a/deps/icu-small/source/common/lsr.h +++ b/deps/icu-small/source/common/lsr.h @@ -16,26 +16,35 @@ U_NAMESPACE_BEGIN struct LSR final : public UMemory { static constexpr int32_t REGION_INDEX_LIMIT = 1001 + 26 * 26; + static constexpr int32_t EXPLICIT_LSR = 7; + static constexpr int32_t EXPLICIT_LANGUAGE = 4; + static constexpr int32_t EXPLICIT_SCRIPT = 2; + static constexpr int32_t EXPLICIT_REGION = 1; + static constexpr int32_t IMPLICIT_LSR = 0; + static constexpr int32_t DONT_CARE_FLAGS = 0; + const char *language; const char *script; const char *region; char *owned = nullptr; /** Index for region, 0 if ill-formed. @see indexForRegion */ int32_t regionIndex = 0; + int32_t flags = 0; /** Only set for LSRs that will be used in a hash table. */ int32_t hashCode = 0; LSR() : language("und"), script(""), region("") {} /** Constructor which aliases all subtag pointers. */ - LSR(const char *lang, const char *scr, const char *r) : + LSR(const char *lang, const char *scr, const char *r, int32_t f) : language(lang), script(scr), region(r), - regionIndex(indexForRegion(region)) {} + regionIndex(indexForRegion(region)), flags(f) {} /** * Constructor which prepends the prefix to the language and script, * copies those into owned memory, and aliases the region. */ - LSR(char prefix, const char *lang, const char *scr, const char *r, UErrorCode &errorCode); + LSR(char prefix, const char *lang, const char *scr, const char *r, int32_t f, + UErrorCode &errorCode); LSR(LSR &&other) U_NOEXCEPT; LSR(const LSR &other) = delete; inline ~LSR() { @@ -55,6 +64,7 @@ struct LSR final : public UMemory { */ static int32_t indexForRegion(const char *region); + UBool isEquivalentTo(const LSR &other) const; UBool operator==(const LSR &other) const; inline UBool operator!=(const LSR &other) const { diff --git a/deps/icu-small/source/common/putil.cpp b/deps/icu-small/source/common/putil.cpp index 207350f8f26120..51c2473c982d5d 100644 --- a/deps/icu-small/source/common/putil.cpp +++ b/deps/icu-small/source/common/putil.cpp @@ -1459,6 +1459,11 @@ static void U_CALLCONV TimeZoneDataDirInitFn(UErrorCode &status) { const char *dir = ""; +#if defined(ICU_TIMEZONE_FILES_DIR_PREFIX_ENV_VAR) + char timezonefilesdir_path_buffer[PATH_MAX]; + const char *prefix = getenv(ICU_TIMEZONE_FILES_DIR_PREFIX_ENV_VAR); +#endif + #if U_PLATFORM_HAS_WINUWP_API == 1 // The UWP version does not support the environment variable setting. @@ -1485,6 +1490,13 @@ static void U_CALLCONV TimeZoneDataDirInitFn(UErrorCode &status) { dir = ""; } +#if defined(ICU_TIMEZONE_FILES_DIR_PREFIX_ENV_VAR) + if (prefix != NULL) { + snprintf(timezonefilesdir_path_buffer, PATH_MAX, "%s%s", prefix, dir); + dir = timezonefilesdir_path_buffer; + } +#endif + setTimeZoneFilesDir(dir, status); } diff --git a/deps/icu-small/source/common/rbbi.cpp b/deps/icu-small/source/common/rbbi.cpp index 01dae48de44c1d..43ba58ba9e6577 100644 --- a/deps/icu-small/source/common/rbbi.cpp +++ b/deps/icu-small/source/common/rbbi.cpp @@ -883,9 +883,15 @@ int32_t RuleBasedBreakIterator::handleNext() { return lookaheadResult; } } + + // If we are at the position of the '/' in a look-ahead (hard break) rule; + // record the current position, to be returned later, if the full rule matches. + // TODO: Move this check before the previous check of fAccepting. + // This would enable hard-break rules with no following context. + // But there are line break test failures when trying this. Investigate. + // Issue ICU-20837 int16_t rule = row->fLookAhead; if (rule != 0) { - // At the position of a '/' in a look-ahead match. Record it. int32_t pos = (int32_t)UTEXT_GETNATIVEINDEX(&fText); lookAheadMatches.setPosition(rule, pos); } @@ -1111,7 +1117,7 @@ static icu::UInitOnce gRBBIInitOnce = U_INITONCE_INITIALIZER; * Release all static memory held by breakiterator. */ U_CDECL_BEGIN -static UBool U_CALLCONV rbbi_cleanup(void) { +UBool U_CALLCONV rbbi_cleanup(void) { delete gLanguageBreakFactories; gLanguageBreakFactories = nullptr; delete gEmptyString; diff --git a/deps/icu-small/source/common/rbbidata.h b/deps/icu-small/source/common/rbbidata.h index 3e573039d0f491..96e4649533f068 100644 --- a/deps/icu-small/source/common/rbbidata.h +++ b/deps/icu-small/source/common/rbbidata.h @@ -192,6 +192,8 @@ class RBBIDataWrapper : public UMemory { U_NAMESPACE_END +U_CFUNC UBool rbbi_cleanup(void); + #endif /* C++ */ #endif diff --git a/deps/icu-small/source/common/rbbirb.cpp b/deps/icu-small/source/common/rbbirb.cpp index 5f5661af94776d..4df96532643d06 100644 --- a/deps/icu-small/source/common/rbbirb.cpp +++ b/deps/icu-small/source/common/rbbirb.cpp @@ -161,6 +161,19 @@ RBBIDataHeader *RBBIRuleBuilder::flattenData() { + reverseTableSize + statusTableSize + trieSize + rulesSize; +#ifdef RBBI_DEBUG + if (fDebugEnv && uprv_strstr(fDebugEnv, "size")) { + RBBIDebugPrintf("Header Size: %8d\n", headerSize); + RBBIDebugPrintf("Forward Table Size: %8d\n", forwardTableSize); + RBBIDebugPrintf("Reverse Table Size: %8d\n", reverseTableSize); + RBBIDebugPrintf("Trie Size: %8d\n", trieSize); + RBBIDebugPrintf("Status Table Size: %8d\n", statusTableSize); + RBBIDebugPrintf("Rules Size: %8d\n", rulesSize); + RBBIDebugPrintf("-----------------------------\n"); + RBBIDebugPrintf("Total Size: %8d\n", totalSize); + } +#endif + RBBIDataHeader *data = (RBBIDataHeader *)uprv_malloc(totalSize); if (data == NULL) { *fStatus = U_MEMORY_ALLOCATION_ERROR; diff --git a/deps/icu-small/source/common/rbbiscan.cpp b/deps/icu-small/source/common/rbbiscan.cpp index 170c212e13fd1f..da8246ba6f1e47 100644 --- a/deps/icu-small/source/common/rbbiscan.cpp +++ b/deps/icu-small/source/common/rbbiscan.cpp @@ -1274,6 +1274,10 @@ void RBBIRuleScanner::scanSet() { } +int32_t RBBIRuleScanner::numRules() { + return fRuleNum; +} + U_NAMESPACE_END #endif /* #if !UCONFIG_NO_BREAK_ITERATION */ diff --git a/deps/icu-small/source/common/rbbiscan.h b/deps/icu-small/source/common/rbbiscan.h index cac60fb18a11b8..559617e78b439f 100644 --- a/deps/icu-small/source/common/rbbiscan.h +++ b/deps/icu-small/source/common/rbbiscan.h @@ -73,6 +73,8 @@ class RBBIRuleScanner : public UMemory { // reverse rules, // and a list of UnicodeSets encountered. + int32_t numRules(); // Return the number of rules that have been seen. + /** * Return a rules string without unnecessary * characters. diff --git a/deps/icu-small/source/common/rbbitblb.cpp b/deps/icu-small/source/common/rbbitblb.cpp index e6ae2dc654a88c..3b1edc6a15c700 100644 --- a/deps/icu-small/source/common/rbbitblb.cpp +++ b/deps/icu-small/source/common/rbbitblb.cpp @@ -18,6 +18,7 @@ #include "unicode/unistr.h" #include "rbbitblb.h" #include "rbbirb.h" +#include "rbbiscan.h" #include "rbbisetb.h" #include "rbbidata.h" #include "cstring.h" @@ -52,6 +53,7 @@ RBBITableBuilder::~RBBITableBuilder() { } delete fDStates; delete fSafeTable; + delete fLookAheadRuleMap; } @@ -121,7 +123,7 @@ void RBBITableBuilder::buildForwardTable() { } cn->fLeftChild = fTree; fTree->fParent = cn; - cn->fRightChild = new RBBINode(RBBINode::endMark); + RBBINode *endMarkerNode = cn->fRightChild = new RBBINode(RBBINode::endMark); // Delete and exit if memory allocation failed. if (cn->fRightChild == NULL) { *fStatus = U_MEMORY_ALLOCATION_ERROR; @@ -164,7 +166,7 @@ void RBBITableBuilder::buildForwardTable() { // For "chained" rules, modify the followPos sets // if (fRB->fChainRules) { - calcChainedFollowPos(fTree); + calcChainedFollowPos(fTree, endMarkerNode); } // @@ -178,6 +180,7 @@ void RBBITableBuilder::buildForwardTable() { // Build the DFA state transition tables. // buildStateTable(); + mapLookAheadRules(); flagAcceptingStates(); flagLookAheadStates(); flagTaggedStates(); @@ -401,19 +404,13 @@ void RBBITableBuilder::addRuleRootNodes(UVector *dest, RBBINode *node) { // to implement rule chaining. NOT described by Aho // //----------------------------------------------------------------------------- -void RBBITableBuilder::calcChainedFollowPos(RBBINode *tree) { +void RBBITableBuilder::calcChainedFollowPos(RBBINode *tree, RBBINode *endMarkNode) { - UVector endMarkerNodes(*fStatus); UVector leafNodes(*fStatus); - int32_t i; - if (U_FAILURE(*fStatus)) { return; } - // get a list of all endmarker nodes. - tree->findNodes(&endMarkerNodes, RBBINode::endMark, *fStatus); - // get a list all leaf nodes tree->findNodes(&leafNodes, RBBINode::leafChar, *fStatus); if (U_FAILURE(*fStatus)) { @@ -442,28 +439,26 @@ void RBBITableBuilder::calcChainedFollowPos(RBBINode *tree) { int32_t startNodeIx; for (endNodeIx=0; endNodeIxfFollowPos->contains(endMarkerNodes.elementAt(i))) { - endNode = tNode; - break; - } - } - if (endNode == NULL) { - // node wasn't an end node. Try again with the next. + // These include the endMarkNode in their followPos sets. + // + // Note: do not consider other end marker nodes, those that are added to + // look-ahead rules. These can't chain; a match immediately stops + // further matching. This leaves exactly one end marker node, the one + // at the end of the complete tree. + + if (!endNode->fFollowPos->contains(endMarkNode)) { continue; } // We've got a node that can end a match. - // Line Break Specific hack: If this node's val correspond to the $CM char class, - // don't chain from it. - // TODO: Add rule syntax for this behavior, get specifics out of here and - // into the rule file. + // !!LBCMNoChain implementation: If this node's val correspond to + // the Line Break $CM char class, don't chain from it. + // TODO: Remove this. !!LBCMNoChain is deprecated, and is not used + // by any of the standard ICU rules. if (fRB->fLBCMNoChain) { UChar32 c = this->fRB->fSetBuilder->getFirstChar(endNode->fVal); if (c != -1) { @@ -475,7 +470,6 @@ void RBBITableBuilder::calcChainedFollowPos(RBBINode *tree) { } } - // Now iterate over the nodes that can start a match, looking for ones // with the same char class as our ending node. RBBINode *startNode; @@ -705,6 +699,77 @@ void RBBITableBuilder::buildStateTable() { } +/** + * mapLookAheadRules + * + */ +void RBBITableBuilder::mapLookAheadRules() { + fLookAheadRuleMap = new UVector32(fRB->fScanner->numRules() + 1, *fStatus); + if (fLookAheadRuleMap == nullptr) { + *fStatus = U_MEMORY_ALLOCATION_ERROR; + } + if (U_FAILURE(*fStatus)) { + return; + } + fLookAheadRuleMap->setSize(fRB->fScanner->numRules() + 1); + int32_t laSlotsInUse = 0; + + for (int32_t n=0; nsize(); n++) { + RBBIStateDescriptor *sd = (RBBIStateDescriptor *)fDStates->elementAt(n); + int32_t laSlotForState = 0; + + // Establish the look-ahead slot for this state, if the state covers + // any look-ahead nodes - corresponding to the '/' in look-ahead rules. + + // If any of the look-ahead nodes already have a slot assigned, use it, + // otherwise assign a new one. + + bool sawLookAheadNode = false; + for (int32_t ipos=0; iposfPositions->size(); ++ipos) { + RBBINode *node = static_cast(sd->fPositions->elementAt(ipos)); + if (node->fType != RBBINode::NodeType::lookAhead) { + continue; + } + sawLookAheadNode = true; + int32_t ruleNum = node->fVal; // Set when rule was originally parsed. + U_ASSERT(ruleNum < fLookAheadRuleMap->size()); + U_ASSERT(ruleNum > 0); + int32_t laSlot = fLookAheadRuleMap->elementAti(ruleNum); + if (laSlot != 0) { + if (laSlotForState == 0) { + laSlotForState = laSlot; + } else { + // TODO: figure out if this can fail, change to setting an error code if so. + U_ASSERT(laSlot == laSlotForState); + } + } + } + if (!sawLookAheadNode) { + continue; + } + + if (laSlotForState == 0) { + laSlotForState = ++laSlotsInUse; + } + + // For each look ahead node covered by this state, + // set the mapping from the node's rule number to the look ahead slot. + // There can be multiple nodes/rule numbers going to the same la slot. + + for (int32_t ipos=0; iposfPositions->size(); ++ipos) { + RBBINode *node = static_cast(sd->fPositions->elementAt(ipos)); + if (node->fType != RBBINode::NodeType::lookAhead) { + continue; + } + int32_t ruleNum = node->fVal; // Set when rule was originally parsed. + int32_t existingVal = fLookAheadRuleMap->elementAti(ruleNum); + (void)existingVal; + U_ASSERT(existingVal == 0 || existingVal == laSlotForState); + fLookAheadRuleMap->setElementAt(laSlotForState, ruleNum); + } + } + +} //----------------------------------------------------------------------------- // @@ -744,28 +809,19 @@ void RBBITableBuilder::flagAcceptingStates() { if (sd->fAccepting==0) { // State hasn't been marked as accepting yet. Do it now. - sd->fAccepting = endMarker->fVal; + sd->fAccepting = fLookAheadRuleMap->elementAti(endMarker->fVal); if (sd->fAccepting == 0) { sd->fAccepting = -1; } } if (sd->fAccepting==-1 && endMarker->fVal != 0) { // Both lookahead and non-lookahead accepting for this state. - // Favor the look-ahead. Expedient for line break. - // TODO: need a more elegant resolution for conflicting rules. - sd->fAccepting = endMarker->fVal; + // Favor the look-ahead, because a look-ahead match needs to + // immediately stop the run-time engine. First match, not longest. + sd->fAccepting = fLookAheadRuleMap->elementAti(endMarker->fVal); } // implicit else: // if sd->fAccepting already had a value other than 0 or -1, leave it be. - - // If the end marker node is from a look-ahead rule, set - // the fLookAhead field for this state also. - if (endMarker->fLookAheadEnd) { - // TODO: don't change value if already set? - // TODO: allow for more than one active look-ahead rule in engine. - // Make value here an index to a side array in engine? - sd->fLookAhead = sd->fAccepting; - } } } } @@ -792,11 +848,20 @@ void RBBITableBuilder::flagLookAheadStates() { } for (i=0; ifType == RBBINode::NodeType::lookAhead); for (n=0; nsize(); n++) { RBBIStateDescriptor *sd = (RBBIStateDescriptor *)fDStates->elementAt(n); - if (sd->fPositions->indexOf(lookAheadNode) >= 0) { - sd->fLookAhead = lookAheadNode->fVal; + int32_t positionsIdx = sd->fPositions->indexOf(lookAheadNode); + if (positionsIdx >= 0) { + U_ASSERT(lookAheadNode == sd->fPositions->elementAt(positionsIdx)); + int32_t lookaheadSlot = fLookAheadRuleMap->elementAti(lookAheadNode->fVal); + U_ASSERT(sd->fLookAhead == 0 || sd->fLookAhead == lookaheadSlot); + // if (sd->fLookAhead != 0 && sd->fLookAhead != lookaheadSlot) { + // printf("%s:%d Bingo. sd->fLookAhead:%d lookaheadSlot:%d\n", + // __FILE__, __LINE__, sd->fLookAhead, lookaheadSlot); + // } + sd->fLookAhead = lookaheadSlot; } } } @@ -1204,16 +1269,6 @@ void RBBITableBuilder::removeState(IntPair duplStates) { } sd->fDtran->setElementAt(newVal, col); } - if (sd->fAccepting == duplState) { - sd->fAccepting = keepState; - } else if (sd->fAccepting > duplState) { - sd->fAccepting--; - } - if (sd->fLookAhead == duplState) { - sd->fLookAhead = keepState; - } else if (sd->fLookAhead > duplState) { - sd->fLookAhead--; - } } } diff --git a/deps/icu-small/source/common/rbbitblb.h b/deps/icu-small/source/common/rbbitblb.h index bc6077bb4da3dc..c2b574fe1b8f93 100644 --- a/deps/icu-small/source/common/rbbitblb.h +++ b/deps/icu-small/source/common/rbbitblb.h @@ -91,9 +91,10 @@ class RBBITableBuilder : public UMemory { void calcFirstPos(RBBINode *n); void calcLastPos(RBBINode *n); void calcFollowPos(RBBINode *n); - void calcChainedFollowPos(RBBINode *n); + void calcChainedFollowPos(RBBINode *n, RBBINode *endMarkNode); void bofFixup(); void buildStateTable(); + void mapLookAheadRules(); void flagAcceptingStates(); void flagLookAheadStates(); void flagTaggedStates(); @@ -175,6 +176,9 @@ class RBBITableBuilder : public UMemory { /** Synthesized safe table, UVector of UnicodeString, one string per table row. */ UVector *fSafeTable; + /** Map from rule number (fVal in look ahead nodes) to sequential lookahead index. */ + UVector32 *fLookAheadRuleMap = nullptr; + RBBITableBuilder(const RBBITableBuilder &other); // forbid copying of this class RBBITableBuilder &operator=(const RBBITableBuilder &other); // forbid copying of this class diff --git a/deps/icu-small/source/common/stringpiece.cpp b/deps/icu-small/source/common/stringpiece.cpp index d4f7f310bafc7d..99089e08ef90f1 100644 --- a/deps/icu-small/source/common/stringpiece.cpp +++ b/deps/icu-small/source/common/stringpiece.cpp @@ -51,6 +51,47 @@ void StringPiece::set(const char* str) { length_ = 0; } +int32_t StringPiece::find(StringPiece needle, int32_t offset) { + if (length() == 0 && needle.length() == 0) { + return 0; + } + // TODO: Improve to be better than O(N^2)? + for (int32_t i = offset; i < length(); i++) { + int32_t j = 0; + for (; j < needle.length(); i++, j++) { + if (data()[i] != needle.data()[j]) { + i -= j; + goto outer_end; + } + } + return i - j; + outer_end: void(); + } + return -1; +} + +int32_t StringPiece::compare(StringPiece other) { + int32_t i = 0; + for (; i < length(); i++) { + if (i == other.length()) { + // this is longer + return 1; + } + char a = data()[i]; + char b = other.data()[i]; + if (a < b) { + return -1; + } else if (a > b) { + return 1; + } + } + if (i < other.length()) { + // other is longer + return -1; + } + return 0; +} + U_EXPORT UBool U_EXPORT2 operator==(const StringPiece& x, const StringPiece& y) { int32_t len = x.size(); diff --git a/deps/icu-small/source/common/uarrsort.cpp b/deps/icu-small/source/common/uarrsort.cpp index 60905821649db9..c17dbb2e2b16a5 100644 --- a/deps/icu-small/source/common/uarrsort.cpp +++ b/deps/icu-small/source/common/uarrsort.cpp @@ -18,6 +18,8 @@ * Internal function for sorting arrays. */ +#include + #include "unicode/utypes.h" #include "cmemory.h" #include "uarrsort.h" @@ -35,7 +37,7 @@ enum { }; static constexpr int32_t sizeInMaxAlignTs(int32_t sizeInBytes) { - return (sizeInBytes + sizeof(max_align_t) - 1) / sizeof(max_align_t); + return (sizeInBytes + sizeof(std::max_align_t) - 1) / sizeof(std::max_align_t); } /* UComparator convenience implementations ---------------------------------- */ @@ -139,7 +141,7 @@ static void insertionSort(char *array, int32_t length, int32_t itemSize, UComparator *cmp, const void *context, UErrorCode *pErrorCode) { - icu::MaybeStackArray v; + icu::MaybeStackArray v; if (sizeInMaxAlignTs(itemSize) > v.getCapacity() && v.resize(sizeInMaxAlignTs(itemSize)) == nullptr) { *pErrorCode = U_MEMORY_ALLOCATION_ERROR; @@ -233,7 +235,7 @@ static void quickSort(char *array, int32_t length, int32_t itemSize, UComparator *cmp, const void *context, UErrorCode *pErrorCode) { /* allocate two intermediate item variables (x and w) */ - icu::MaybeStackArray xw; + icu::MaybeStackArray xw; if(sizeInMaxAlignTs(itemSize)*2 > xw.getCapacity() && xw.resize(sizeInMaxAlignTs(itemSize) * 2) == nullptr) { *pErrorCode=U_MEMORY_ALLOCATION_ERROR; diff --git a/deps/icu-small/source/common/uassert.h b/deps/icu-small/source/common/uassert.h index f0f7a92574b4d4..15cd55c873487c 100644 --- a/deps/icu-small/source/common/uassert.h +++ b/deps/icu-small/source/common/uassert.h @@ -31,6 +31,8 @@ #if U_DEBUG # include # define U_ASSERT(exp) assert(exp) +#elif U_CPLUSPLUS_VERSION +# define U_ASSERT(exp) void() #else # define U_ASSERT(exp) #endif diff --git a/deps/icu-small/source/common/ucasemap.cpp b/deps/icu-small/source/common/ucasemap.cpp index cc998c993d73dc..ed72bda828fc1c 100644 --- a/deps/icu-small/source/common/ucasemap.cpp +++ b/deps/icu-small/source/common/ucasemap.cpp @@ -687,13 +687,13 @@ void toUpper(uint32_t options, if (change) { ByteSinkUtil::appendTwoBytes(upper, sink); if ((data & HAS_EITHER_DIALYTIKA) != 0) { - sink.Append(reinterpret_cast(u8"\u0308"), 2); // restore or add a dialytika + sink.AppendU8(u8"\u0308", 2); // restore or add a dialytika } if (addTonos) { - sink.Append(reinterpret_cast(u8"\u0301"), 2); + sink.AppendU8(u8"\u0301", 2); } while (numYpogegrammeni > 0) { - sink.Append(reinterpret_cast(u8"\u0399"), 2); + sink.AppendU8(u8"\u0399", 2); --numYpogegrammeni; } } diff --git a/deps/icu-small/source/common/ucnv2022.cpp b/deps/icu-small/source/common/ucnv2022.cpp index 6cd9a3d12e40fc..89db9e81ddea06 100644 --- a/deps/icu-small/source/common/ucnv2022.cpp +++ b/deps/icu-small/source/common/ucnv2022.cpp @@ -478,7 +478,7 @@ setInitialStateFromUnicodeKR(UConverter* converter,UConverterDataISO2022 *myConv static void U_CALLCONV _ISO2022Open(UConverter *cnv, UConverterLoadArgs *pArgs, UErrorCode *errorCode){ - char myLocale[6]={' ',' ',' ',' ',' ',' '}; + char myLocale[7]={' ',' ',' ',' ',' ',' ', '\0'}; cnv->extraInfo = uprv_malloc (sizeof (UConverterDataISO2022)); if(cnv->extraInfo != NULL) { @@ -493,7 +493,7 @@ _ISO2022Open(UConverter *cnv, UConverterLoadArgs *pArgs, UErrorCode *errorCode){ myConverterData->currentType = ASCII1; cnv->fromUnicodeStatus =FALSE; if(pArgs->locale){ - uprv_strncpy(myLocale, pArgs->locale, sizeof(myLocale)); + uprv_strncpy(myLocale, pArgs->locale, sizeof(myLocale)-1); } version = pArgs->options & UCNV_OPTIONS_VERSION_MASK; myConverterData->version = version; diff --git a/deps/icu-small/source/common/ucurr.cpp b/deps/icu-small/source/common/ucurr.cpp index d42c2f10b1d4c6..391b08083b899a 100644 --- a/deps/icu-small/source/common/ucurr.cpp +++ b/deps/icu-small/source/common/ucurr.cpp @@ -866,7 +866,7 @@ getCurrencyNameCount(const char* loc, int32_t* total_currency_name_count, int32_ *total_currency_name_count = 0; *total_currency_symbol_count = 0; const UChar* s = NULL; - char locale[ULOC_FULLNAME_CAPACITY]; + char locale[ULOC_FULLNAME_CAPACITY] = ""; uprv_strcpy(locale, loc); const icu::Hashtable *currencySymbolsEquiv = getCurrSymbolsEquiv(); for (;;) { @@ -941,7 +941,7 @@ collectCurrencyNames(const char* locale, // Look up the Currencies resource for the given locale. UErrorCode ec2 = U_ZERO_ERROR; - char loc[ULOC_FULLNAME_CAPACITY]; + char loc[ULOC_FULLNAME_CAPACITY] = ""; uloc_getName(locale, loc, sizeof(loc), &ec2); if (U_FAILURE(ec2) || ec2 == U_STRING_NOT_TERMINATED_WARNING) { ec = U_ILLEGAL_ARGUMENT_ERROR; diff --git a/deps/icu-small/source/common/uloc.cpp b/deps/icu-small/source/common/uloc.cpp index ea81c0ce87fe13..0e235d7958ceb1 100644 --- a/deps/icu-small/source/common/uloc.cpp +++ b/deps/icu-small/source/common/uloc.cpp @@ -30,10 +30,14 @@ l = lang, C = ctry, M = charmap, V = variant */ +#include "unicode/bytestream.h" +#include "unicode/errorcode.h" +#include "unicode/stringpiece.h" #include "unicode/utypes.h" #include "unicode/ustring.h" #include "unicode/uloc.h" +#include "bytesinkutil.h" #include "putilimp.h" #include "ustr_imp.h" #include "ulocimp.h" @@ -46,6 +50,7 @@ #include "uassert.h" #include "charstr.h" +#include #include /* for sprintf */ U_NAMESPACE_USE @@ -59,7 +64,6 @@ U_CFUNC int32_t locale_getKeywords(const char *localeID, char prev, char *keywords, int32_t keywordCapacity, - char *values, int32_t valuesCapacity, int32_t *valLen, UBool valuesToo, UErrorCode *status); @@ -157,7 +161,7 @@ static const char * const LANGUAGES[] = { "nnh", "no", "nog", "non", "nov", "nqo", "nr", "nso", "nus", "nv", "nwc", "ny", "nym", "nyn", "nyo", "nzi", "oc", "oj", "om", "or", "os", "osa", "ota", - "pa", "pag", "pal", "pam", "pap", "pau", "pcd", "pdc", + "pa", "pag", "pal", "pam", "pap", "pau", "pcd", "pcm", "pdc", "pdt", "peo", "pfl", "phn", "pi", "pl", "pms", "pnt", "pon", "prg", "pro", "ps", "pt", "qu", "quc", "qug", @@ -274,7 +278,7 @@ static const char * const LANGUAGES_3[] = { "nnh", "nor", "nog", "non", "nov", "nqo", "nbl", "nso", "nus", "nav", "nwc", "nya", "nym", "nyn", "nyo", "nzi", "oci", "oji", "orm", "ori", "oss", "osa", "ota", - "pan", "pag", "pal", "pam", "pap", "pau", "pcd", "pdc", + "pan", "pag", "pal", "pam", "pap", "pau", "pcd", "pcm", "pdc", "pdt", "peo", "pfl", "phn", "pli", "pol", "pms", "pnt", "pon", "prg", "pro", "pus", "por", "que", "quc", "qug", @@ -466,15 +470,16 @@ typedef struct CanonicalizationMap { * different semantic kinds of transformations. */ static const CanonicalizationMap CANONICALIZE_MAP[] = { - { "art_LOJBAN", "jbo" }, /* registered name */ + { "art__LOJBAN", "jbo" }, /* registered name */ { "hy__AREVELA", "hy" }, /* Registered IANA variant */ { "hy__AREVMDA", "hyw" }, /* Registered IANA variant */ + { "zh__GUOYU", "zh" }, /* registered name */ + { "zh__HAKKA", "hak" }, /* registered name */ + { "zh__XIANG", "hsn" }, /* registered name */ + // subtags with 3 chars won't be treated as variants. { "zh_GAN", "gan" }, /* registered name */ - { "zh_GUOYU", "zh" }, /* registered name */ - { "zh_HAKKA", "hak" }, /* registered name */ { "zh_MIN_NAN", "nan" }, /* registered name */ { "zh_WUU", "wuu" }, /* registered name */ - { "zh_XIANG", "hsn" }, /* registered name */ { "zh_YUE", "yue" }, /* registered name */ }; @@ -596,11 +601,10 @@ compareKeywordStructs(const void * /*context*/, const void *left, const void *ri return uprv_strcmp(leftString, rightString); } -static int32_t +static void _getKeywords(const char *localeID, char prev, - char *keywords, int32_t keywordCapacity, - char *values, int32_t valuesCapacity, int32_t *valLen, + ByteSink& sink, UBool valuesToo, UErrorCode *status) { @@ -612,8 +616,6 @@ _getKeywords(const char *localeID, const char* equalSign = NULL; const char* semicolon = NULL; int32_t i = 0, j, n; - int32_t keywordsLen = 0; - int32_t valuesLen = 0; if(prev == '@') { /* start of keyword definition */ /* we will grab pairs, trim spaces, lowercase keywords, sort and return */ @@ -628,7 +630,7 @@ _getKeywords(const char *localeID, } if(numKeywords == maxKeywords) { *status = U_INTERNAL_PROGRAM_ERROR; - return 0; + return; } equalSign = uprv_strchr(pos, '='); semicolon = uprv_strchr(pos, ';'); @@ -636,13 +638,13 @@ _getKeywords(const char *localeID, /* ';' before '=' [foo@currency;collation=pinyin] is illegal */ if(!equalSign || (semicolon && semicolon= ULOC_KEYWORD_BUFFER_LEN) { /* keyword name too long for internal buffer */ *status = U_INTERNAL_PROGRAM_ERROR; - return 0; + return; } for(i = 0, n = 0; i < equalSign - pos; ++i) { if (pos[i] != ' ') { @@ -653,7 +655,7 @@ _getKeywords(const char *localeID, /* zero-length keyword is an error. */ if (n == 0) { *status = U_INVALID_FORMAT_ERROR; - return 0; + return; } keywordList[numKeywords].keyword[n] = 0; @@ -668,7 +670,7 @@ _getKeywords(const char *localeID, /* Premature end or zero-length value */ if (!*equalSign || equalSign == semicolon) { *status = U_INVALID_FORMAT_ERROR; - return 0; + return; } keywordList[numKeywords].valueStart = equalSign; @@ -706,45 +708,17 @@ _getKeywords(const char *localeID, /* Now construct the keyword part */ for(i = 0; i < numKeywords; i++) { - if(keywordsLen + keywordList[i].keywordLen + 1< keywordCapacity) { - uprv_strcpy(keywords+keywordsLen, keywordList[i].keyword); - if(valuesToo) { - keywords[keywordsLen + keywordList[i].keywordLen] = '='; - } else { - keywords[keywordsLen + keywordList[i].keywordLen] = 0; - } - } - keywordsLen += keywordList[i].keywordLen + 1; + sink.Append(keywordList[i].keyword, keywordList[i].keywordLen); if(valuesToo) { - if(keywordsLen + keywordList[i].valueLen <= keywordCapacity) { - uprv_strncpy(keywords+keywordsLen, keywordList[i].valueStart, keywordList[i].valueLen); - } - keywordsLen += keywordList[i].valueLen; - + sink.Append("=", 1); + sink.Append(keywordList[i].valueStart, keywordList[i].valueLen); if(i < numKeywords - 1) { - if(keywordsLen < keywordCapacity) { - keywords[keywordsLen] = ';'; - } - keywordsLen++; - } - } - if(values) { - if(valuesLen + keywordList[i].valueLen + 1< valuesCapacity) { - uprv_strcpy(values+valuesLen, keywordList[i].valueStart); - values[valuesLen + keywordList[i].valueLen] = 0; + sink.Append(";", 1); } - valuesLen += keywordList[i].valueLen + 1; - } - } - if(values) { - values[valuesLen] = 0; - if(valLen) { - *valLen = valuesLen; + } else { + sink.Append("\0", 1); } } - return u_terminateChars(keywords, keywordCapacity, keywordsLen, status); - } else { - return 0; } } @@ -752,12 +726,28 @@ U_CFUNC int32_t locale_getKeywords(const char *localeID, char prev, char *keywords, int32_t keywordCapacity, - char *values, int32_t valuesCapacity, int32_t *valLen, UBool valuesToo, UErrorCode *status) { - return _getKeywords(localeID, prev, keywords, keywordCapacity, - values, valuesCapacity, valLen, valuesToo, - status); + if (U_FAILURE(*status)) { + return 0; + } + + CheckedArrayByteSink sink(keywords, keywordCapacity); + _getKeywords(localeID, prev, sink, valuesToo, status); + + int32_t reslen = sink.NumberOfBytesAppended(); + + if (U_FAILURE(*status)) { + return reslen; + } + + if (sink.Overflowed()) { + *status = U_BUFFER_OVERFLOW_ERROR; + } else { + u_terminateChars(keywords, keywordCapacity, reslen, status); + } + + return reslen; } U_CAPI int32_t U_EXPORT2 @@ -1134,26 +1124,6 @@ static int16_t _findIndex(const char* const* list, const char* key) return -1; } -/* count the length of src while copying it to dest; return strlen(src) */ -static inline int32_t -_copyCount(char *dest, int32_t destCapacity, const char *src) { - const char *anchor; - char c; - - anchor=src; - for(;;) { - if((c=*src)==0) { - return (int32_t)(src-anchor); - } - if(destCapacity<=0) { - return (int32_t)((src-anchor)+uprv_strlen(src)); - } - ++src; - *dest++=c; - --destCapacity; - } -} - U_CFUNC const char* uloc_getCurrentCountryID(const char* oldID){ int32_t offset = _findIndex(DEPRECATED_COUNTRIES, oldID); @@ -1178,13 +1148,11 @@ uloc_getCurrentLanguageID(const char* oldID){ * * TODO try to use this in Locale */ -U_CFUNC int32_t +static CharString ulocimp_getLanguage(const char *localeID, - char *language, int32_t languageCapacity, - const char **pEnd) { - int32_t i=0; - int32_t offset; - char lang[4]={ 0, 0, 0, 0 }; /* temporary buffer to hold language code for searching */ + const char **pEnd, + UErrorCode &status) { + CharString result; if (uprv_stricmp(localeID, "root") == 0) { localeID += 4; @@ -1198,48 +1166,52 @@ ulocimp_getLanguage(const char *localeID, /* if it starts with i- or x- then copy that prefix */ if(_isIDPrefix(localeID)) { - if(i=0); - lang[i]=(char)uprv_tolower(*localeID); - } - i++; + result.append((char)uprv_tolower(*localeID), status); localeID++; } - if(i==3) { + if(result.length()==3) { /* convert 3 character code to 2 character code if possible *CWB*/ - offset=_findIndex(LANGUAGES_3, lang); + int32_t offset = _findIndex(LANGUAGES_3, result.data()); if(offset>=0) { - i=_copyCount(language, languageCapacity, LANGUAGES[offset]); + result.clear(); + result.append(LANGUAGES[offset], status); } } if(pEnd!=NULL) { *pEnd=localeID; } - return i; + + return result; } U_CFUNC int32_t +ulocimp_getLanguage(const char *localeID, + char *language, int32_t languageCapacity, + const char **pEnd) { + ErrorCode status; + CharString result = ulocimp_getLanguage(localeID, pEnd, status); + if (status.isFailure()) { + return 0; + } + int32_t reslen = result.length(); + uprv_memcpy(language, result.data(), std::min(reslen, languageCapacity)); + return reslen; +} + +static CharString ulocimp_getScript(const char *localeID, - char *script, int32_t scriptCapacity, - const char **pEnd) -{ + const char **pEnd, + UErrorCode &status) { + CharString result; int32_t idLen = 0; if (pEnd != NULL) { @@ -1258,132 +1230,137 @@ ulocimp_getScript(const char *localeID, if (pEnd != NULL) { *pEnd = localeID+idLen; } - if(idLen > scriptCapacity) { - idLen = scriptCapacity; - } if (idLen >= 1) { - script[0]=(char)uprv_toupper(*(localeID++)); + result.append((char)uprv_toupper(*(localeID++)), status); } for (i = 1; i < idLen; i++) { - script[i]=(char)uprv_tolower(*(localeID++)); + result.append((char)uprv_tolower(*(localeID++)), status); } } - else { - idLen = 0; - } - return idLen; + + return result; } U_CFUNC int32_t +ulocimp_getScript(const char *localeID, + char *script, int32_t scriptCapacity, + const char **pEnd) { + ErrorCode status; + CharString result = ulocimp_getScript(localeID, pEnd, status); + if (status.isFailure()) { + return 0; + } + int32_t reslen = result.length(); + uprv_memcpy(script, result.data(), std::min(reslen, scriptCapacity)); + return reslen; +} + +static CharString ulocimp_getCountry(const char *localeID, - char *country, int32_t countryCapacity, - const char **pEnd) -{ + const char **pEnd, + UErrorCode &status) { + CharString result; int32_t idLen=0; - char cnty[ULOC_COUNTRY_CAPACITY]={ 0, 0, 0, 0 }; - int32_t offset; /* copy the country as far as possible and count its length */ while(!_isTerminator(localeID[idLen]) && !_isIDSeparator(localeID[idLen])) { - if(idLen<(ULOC_COUNTRY_CAPACITY-1)) { /*CWB*/ - cnty[idLen]=(char)uprv_toupper(localeID[idLen]); - } + result.append((char)uprv_toupper(localeID[idLen]), status); idLen++; } /* the country should be either length 2 or 3 */ if (idLen == 2 || idLen == 3) { - UBool gotCountry = FALSE; /* convert 3 character code to 2 character code if possible *CWB*/ if(idLen==3) { - offset=_findIndex(COUNTRIES_3, cnty); + int32_t offset = _findIndex(COUNTRIES_3, result.data()); if(offset>=0) { - idLen=_copyCount(country, countryCapacity, COUNTRIES[offset]); - gotCountry = TRUE; - } - } - if (!gotCountry) { - int32_t i = 0; - for (i = 0; i < idLen; i++) { - if (i < countryCapacity) { - country[i]=(char)uprv_toupper(localeID[i]); - } + result.clear(); + result.append(COUNTRIES[offset], status); } } localeID+=idLen; } else { - idLen = 0; + result.clear(); } if(pEnd!=NULL) { *pEnd=localeID; } - return idLen; + return result; +} + +U_CFUNC int32_t +ulocimp_getCountry(const char *localeID, + char *country, int32_t countryCapacity, + const char **pEnd) { + ErrorCode status; + CharString result = ulocimp_getCountry(localeID, pEnd, status); + if (status.isFailure()) { + return 0; + } + int32_t reslen = result.length(); + uprv_memcpy(country, result.data(), std::min(reslen, countryCapacity)); + return reslen; } /** * @param needSeparator if true, then add leading '_' if any variants * are added to 'variant' */ -static int32_t +static void _getVariantEx(const char *localeID, char prev, - char *variant, int32_t variantCapacity, + ByteSink& sink, UBool needSeparator) { - int32_t i=0; + UBool hasVariant = FALSE; /* get one or more variant tags and separate them with '_' */ if(_isIDSeparator(prev)) { /* get a variant string after a '-' or '_' */ while(!_isTerminator(*localeID)) { if (needSeparator) { - if (i 0) { /* Found optional script */ tmpLocaleID = scriptID; ++fieldCount; - len+=scriptSize; if (_isIDSeparator(*tmpLocaleID)) { /* If there is something else, then we add the _ */ - if(len 0) { + + CharString country = ulocimp_getCountry(tmpLocaleID+1, &cntryID, *err); + tag.append(country, *err); + if (!country.isEmpty()) { /* Found optional country */ tmpLocaleID = cntryID; - len+=cntrySize; } if(_isIDSeparator(*tmpLocaleID)) { /* If there is something else, then we add the _ if we found country before. */ - if (cntrySize >= 0 && ! _isIDSeparator(*(tmpLocaleID+1)) ) { + if (!_isIDSeparator(*(tmpLocaleID+1))) { ++fieldCount; - if(len 0) { - variant = len 0)) { do { - if(len 0)); + + int32_t posixVariantSize = -tag.length(); + { + CharStringByteSink s(&tag); + _getVariantEx(tmpLocaleID+1, '@', s, (UBool)(variantSize > 0)); + } + posixVariantSize += tag.length(); if (posixVariantSize > 0) { - if (variant == NULL) { - variant = name+len; - } - len += posixVariantSize; variantSize += posixVariantSize; } } /* Look up the ID in the canonicalization map */ for (j=0; j keywordAssign)) { - if(len resultCapacity) ? resultCapacity : len); - } - - return u_terminateChars(result, resultCapacity, len, err); } /* ### ID parsing API **************************************************/ @@ -1949,7 +1883,34 @@ uloc_getName(const char* localeID, int32_t nameCapacity, UErrorCode* err) { - return _canonicalize(localeID, name, nameCapacity, 0, err); + if (U_FAILURE(*err)) { + return 0; + } + + CheckedArrayByteSink sink(name, nameCapacity); + ulocimp_getName(localeID, sink, err); + + int32_t reslen = sink.NumberOfBytesAppended(); + + if (U_FAILURE(*err)) { + return reslen; + } + + if (sink.Overflowed()) { + *err = U_BUFFER_OVERFLOW_ERROR; + } else { + u_terminateChars(name, nameCapacity, reslen, err); + } + + return reslen; +} + +U_STABLE void U_EXPORT2 +ulocimp_getName(const char* localeID, + ByteSink& sink, + UErrorCode* err) +{ + _canonicalize(localeID, sink, 0, err); } U_CAPI int32_t U_EXPORT2 @@ -1958,7 +1919,34 @@ uloc_getBaseName(const char* localeID, int32_t nameCapacity, UErrorCode* err) { - return _canonicalize(localeID, name, nameCapacity, _ULOC_STRIP_KEYWORDS, err); + if (U_FAILURE(*err)) { + return 0; + } + + CheckedArrayByteSink sink(name, nameCapacity); + ulocimp_getBaseName(localeID, sink, err); + + int32_t reslen = sink.NumberOfBytesAppended(); + + if (U_FAILURE(*err)) { + return reslen; + } + + if (sink.Overflowed()) { + *err = U_BUFFER_OVERFLOW_ERROR; + } else { + u_terminateChars(name, nameCapacity, reslen, err); + } + + return reslen; +} + +U_STABLE void U_EXPORT2 +ulocimp_getBaseName(const char* localeID, + ByteSink& sink, + UErrorCode* err) +{ + _canonicalize(localeID, sink, _ULOC_STRIP_KEYWORDS, err); } U_CAPI int32_t U_EXPORT2 @@ -1967,7 +1955,34 @@ uloc_canonicalize(const char* localeID, int32_t nameCapacity, UErrorCode* err) { - return _canonicalize(localeID, name, nameCapacity, _ULOC_CANONICALIZE, err); + if (U_FAILURE(*err)) { + return 0; + } + + CheckedArrayByteSink sink(name, nameCapacity); + ulocimp_canonicalize(localeID, sink, err); + + int32_t reslen = sink.NumberOfBytesAppended(); + + if (U_FAILURE(*err)) { + return reslen; + } + + if (sink.Overflowed()) { + *err = U_BUFFER_OVERFLOW_ERROR; + } else { + u_terminateChars(name, nameCapacity, reslen, err); + } + + return reslen; +} + +U_STABLE void U_EXPORT2 +ulocimp_canonicalize(const char* localeID, + ByteSink& sink, + UErrorCode* err) +{ + _canonicalize(localeID, sink, _ULOC_CANONICALIZE, err); } U_CAPI const char* U_EXPORT2 @@ -2126,301 +2141,6 @@ uloc_getISOCountries() return COUNTRIES; } - -/* this function to be moved into cstring.c later */ -static char gDecimal = 0; - -static /* U_CAPI */ -double -/* U_EXPORT2 */ -_uloc_strtod(const char *start, char **end) { - char *decimal; - char *myEnd; - char buf[30]; - double rv; - if (!gDecimal) { - char rep[5]; - /* For machines that decide to change the decimal on you, - and try to be too smart with localization. - This normally should be just a '.'. */ - sprintf(rep, "%+1.1f", 1.0); - gDecimal = rep[2]; - } - - if(gDecimal == '.') { - return uprv_strtod(start, end); /* fall through to OS */ - } else { - uprv_strncpy(buf, start, 29); - buf[29]=0; - decimal = uprv_strchr(buf, '.'); - if(decimal) { - *decimal = gDecimal; - } else { - return uprv_strtod(start, end); /* no decimal point */ - } - rv = uprv_strtod(buf, &myEnd); - if(end) { - *end = (char*)(start+(myEnd-buf)); /* cast away const (to follow uprv_strtod API.) */ - } - return rv; - } -} - -typedef struct { - float q; - int32_t dummy; /* to avoid uninitialized memory copy from qsort */ - char locale[ULOC_FULLNAME_CAPACITY+1]; -} _acceptLangItem; - -static int32_t U_CALLCONV -uloc_acceptLanguageCompare(const void * /*context*/, const void *a, const void *b) -{ - const _acceptLangItem *aa = (const _acceptLangItem*)a; - const _acceptLangItem *bb = (const _acceptLangItem*)b; - - int32_t rc = 0; - if(bb->q < aa->q) { - rc = -1; /* A > B */ - } else if(bb->q > aa->q) { - rc = 1; /* A < B */ - } else { - rc = 0; /* A = B */ - } - - if(rc==0) { - rc = uprv_stricmp(aa->locale, bb->locale); - } - -#if defined(ULOC_DEBUG) - /* fprintf(stderr, "a:[%s:%g], b:[%s:%g] -> %d\n", - aa->locale, aa->q, - bb->locale, bb->q, - rc);*/ -#endif - - return rc; -} - -/* -mt-mt, ja;q=0.76, en-us;q=0.95, en;q=0.92, en-gb;q=0.89, fr;q=0.87, iu-ca;q=0.84, iu;q=0.82, ja-jp;q=0.79, mt;q=0.97, de-de;q=0.74, de;q=0.71, es;q=0.68, it-it;q=0.66, it;q=0.63, vi-vn;q=0.61, vi;q=0.58, nl-nl;q=0.55, nl;q=0.53 -*/ - -U_CAPI int32_t U_EXPORT2 -uloc_acceptLanguageFromHTTP(char *result, int32_t resultAvailable, UAcceptResult *outResult, - const char *httpAcceptLanguage, - UEnumeration* availableLocales, - UErrorCode *status) -{ - MaybeStackArray<_acceptLangItem, 4> items; // Struct for collecting items. - char tmp[ULOC_FULLNAME_CAPACITY +1]; - int32_t n = 0; - const char *itemEnd; - const char *paramEnd; - const char *s; - const char *t; - int32_t res; - int32_t i; - int32_t l = (int32_t)uprv_strlen(httpAcceptLanguage); - - if(U_FAILURE(*status)) { - return -1; - } - - for(s=httpAcceptLanguage;s&&*s;) { - while(isspace(*s)) /* eat space at the beginning */ - s++; - itemEnd=uprv_strchr(s,','); - paramEnd=uprv_strchr(s,';'); - if(!itemEnd) { - itemEnd = httpAcceptLanguage+l; /* end of string */ - } - if(paramEnd && paramEnds)&&isspace(*t);t--) - ; - int32_t slen = static_cast(((t+1)-s)); - if(slen > ULOC_FULLNAME_CAPACITY) { - *status = U_BUFFER_OVERFLOW_ERROR; - return -1; // too big - } - uprv_strncpy(items[n].locale, s, slen); - items[n].locale[slen]=0; // terminate - int32_t clen = uloc_canonicalize(items[n].locale, tmp, UPRV_LENGTHOF(tmp)-1, status); - if(U_FAILURE(*status)) return -1; - if((clen!=slen) || (uprv_strncmp(items[n].locale, tmp, slen))) { - // canonicalization had an effect- copy back - uprv_strncpy(items[n].locale, tmp, clen); - items[n].locale[clen] = 0; // terminate - } -#if defined(ULOC_DEBUG) - /*fprintf(stderr,"%d: s <%s> q <%g>\n", n, j[n].locale, j[n].q);*/ -#endif - n++; - s = itemEnd; - while(*s==',') { /* eat duplicate commas */ - s++; - } - if(n>=items.getCapacity()) { // If we need more items - if(NULL == items.resize(items.getCapacity()*2, items.getCapacity())) { - *status = U_MEMORY_ALLOCATION_ERROR; - return -1; - } -#if defined(ULOC_DEBUG) - fprintf(stderr,"malloced at size %d\n", items.getCapacity()); -#endif - } - } - uprv_sortArray(items.getAlias(), n, sizeof(items[0]), uloc_acceptLanguageCompare, NULL, TRUE, status); - if (U_FAILURE(*status)) { - return -1; - } - LocalMemory strs(NULL); - if (strs.allocateInsteadAndReset(n) == NULL) { - *status = U_MEMORY_ALLOCATION_ERROR; - return -1; - } - for(i=0;i q <%g>\n", i, j[i].locale, j[i].q);*/ -#endif - strs[i]=items[i].locale; - } - res = uloc_acceptLanguage(result, resultAvailable, outResult, - strs.getAlias(), n, availableLocales, status); - return res; -} - - -U_CAPI int32_t U_EXPORT2 -uloc_acceptLanguage(char *result, int32_t resultAvailable, - UAcceptResult *outResult, const char **acceptList, - int32_t acceptListCount, - UEnumeration* availableLocales, - UErrorCode *status) -{ - int32_t i,j; - int32_t len; - int32_t maxLen=0; - char tmp[ULOC_FULLNAME_CAPACITY+1]; - const char *l; - char **fallbackList; - if(U_FAILURE(*status)) { - return -1; - } - fallbackList = static_cast(uprv_malloc((size_t)(sizeof(fallbackList[0])*acceptListCount))); - if(fallbackList==NULL) { - *status = U_MEMORY_ALLOCATION_ERROR; - return -1; - } - for(i=0;i0) { - uprv_strncpy(result, l, uprv_min(len, resultAvailable)); - } - for(j=0;jmaxLen) { - maxLen = len; - } - } - uenum_reset(availableLocales, status); - /* save off parent info */ - if(uloc_getParent(acceptList[i], tmp, UPRV_LENGTHOF(tmp), status)!=0) { - fallbackList[i] = uprv_strdup(tmp); - } else { - fallbackList[i]=0; - } - } - - for(maxLen--;maxLen>0;maxLen--) { - for(i=0;i0) { - uprv_strncpy(result, l, uprv_min(len, resultAvailable)); - } - for(j=0;jnext) { + for (VariantListEntry* var2 = var1->next; var2 != NULL; var2 = var2->next) { + // Swap var1->variant and var2->variant. + if (uprv_compareInvCharsAsAscii(var1->variant, var2->variant) > 0) { + const char* temp = var1->variant; + var1->variant = var2->variant; + var2->variant = temp; + } + } + } +} + static void _appendVariantsToLanguageTag(const char* localeID, icu::ByteSink& sink, UBool strict, UBool *hadPosix, UErrorCode* status) { char buf[ULOC_FULLNAME_CAPACITY]; @@ -1199,6 +1212,9 @@ _appendVariantsToLanguageTag(const char* localeID, icu::ByteSink& sink, UBool st if (varFirst != NULL) { int32_t varLen; + /* per UTS35, we should sort the variants */ + _sortVariants(varFirst); + /* write out validated/normalized variants to the target */ var = varFirst; while (var != NULL) { @@ -1492,8 +1508,11 @@ _appendKeywordsToLanguageTag(const char* localeID, icu::ByteSink& sink, UBool st } else { sink.Append("-", 1); sink.Append(ext->key, static_cast(uprv_strlen(ext->key))); - sink.Append("-", 1); - sink.Append(ext->value, static_cast(uprv_strlen(ext->value))); + if (uprv_strcmp(ext->value, "true") != 0 && + uprv_strcmp(ext->value, "yes") != 0) { + sink.Append("-", 1); + sink.Append(ext->value, static_cast(uprv_strlen(ext->value))); + } } } } @@ -1662,7 +1681,7 @@ _appendLDMLExtensionAsKeywords(const char* ldmlext, ExtensionListEntry** appendT const char *pKey = NULL; /* LDML key */ const char *pType = NULL; /* LDML type */ - char bcpKeyBuf[9]; /* BCP key length is always 2 for now */ + char bcpKeyBuf[3]; /* BCP key length is always 2 for now */ U_ASSERT(pBcpKey != NULL); @@ -1671,6 +1690,7 @@ _appendLDMLExtensionAsKeywords(const char* ldmlext, ExtensionListEntry** appendT *status = U_ILLEGAL_ARGUMENT_ERROR; return; } + U_ASSERT(bcpKeyLen <= 2); uprv_strncpy(bcpKeyBuf, pBcpKey, bcpKeyLen); bcpKeyBuf[bcpKeyLen] = 0; @@ -2822,6 +2842,7 @@ ulocimp_forLanguageTag(const char* langtag, } /* variants */ + _sortVariants(lt.getAlias()->variants); n = ultag_getVariantsSize(lt.getAlias()); if (n > 0) { if (noRegion) { diff --git a/deps/icu-small/source/common/ulocimp.h b/deps/icu-small/source/common/ulocimp.h index dac82872e6ed40..98b95dddfe75bc 100644 --- a/deps/icu-small/source/common/ulocimp.h +++ b/deps/icu-small/source/common/ulocimp.h @@ -62,6 +62,21 @@ ulocimp_getCountry(const char *localeID, char *country, int32_t countryCapacity, const char **pEnd); +U_STABLE void U_EXPORT2 +ulocimp_getName(const char* localeID, + icu::ByteSink& sink, + UErrorCode* err); + +U_STABLE void U_EXPORT2 +ulocimp_getBaseName(const char* localeID, + icu::ByteSink& sink, + UErrorCode* err); + +U_STABLE void U_EXPORT2 +ulocimp_canonicalize(const char* localeID, + icu::ByteSink& sink, + UErrorCode* err); + /** * Writes a well-formed language tag for this locale ID. * diff --git a/deps/icu-small/source/common/umutex.h b/deps/icu-small/source/common/umutex.h old mode 100755 new mode 100644 diff --git a/deps/icu-small/source/common/unames.cpp b/deps/icu-small/source/common/unames.cpp index a28b6ee6036b96..c55e2d662acff5 100644 --- a/deps/icu-small/source/common/unames.cpp +++ b/deps/icu-small/source/common/unames.cpp @@ -1519,7 +1519,8 @@ U_CAPI UChar32 U_EXPORT2 u_charFromName(UCharNameChoice nameChoice, const char *name, UErrorCode *pErrorCode) { - char upper[120], lower[120]; + char upper[120] = {0}; + char lower[120] = {0}; FindName findName; AlgorithmicRange *algRange; uint32_t *p; diff --git a/deps/icu-small/source/common/unicode/bytestream.h b/deps/icu-small/source/common/unicode/bytestream.h index 2c71c248e3dfa0..33505a34299818 100644 --- a/deps/icu-small/source/common/unicode/bytestream.h +++ b/deps/icu-small/source/common/unicode/bytestream.h @@ -71,6 +71,40 @@ class U_COMMON_API ByteSink : public UMemory { */ virtual void Append(const char* bytes, int32_t n) = 0; +#ifndef U_HIDE_DRAFT_API + /** + * Appends n bytes to this. Same as Append(). + * Call AppendU8() with u8"string literals" which are const char * in C++11 + * but const char8_t * in C++20. + * If the compiler does support char8_t as a distinct type, + * then an AppendU8() overload for that is defined and will be chosen. + * + * @param bytes the pointer to the bytes + * @param n the number of bytes; must be non-negative + * @draft ICU 67 + */ + inline void AppendU8(const char* bytes, int32_t n) { + Append(bytes, n); + } + +#if defined(__cpp_char8_t) || defined(U_IN_DOXYGEN) + /** + * Appends n bytes to this. Same as Append() but for a const char8_t * pointer. + * Call AppendU8() with u8"string literals" which are const char * in C++11 + * but const char8_t * in C++20. + * If the compiler does support char8_t as a distinct type, + * then this AppendU8() overload for that is defined and will be chosen. + * + * @param bytes the pointer to the bytes + * @param n the number of bytes; must be non-negative + * @draft ICU 67 + */ + inline void AppendU8(const char8_t* bytes, int32_t n) { + Append(reinterpret_cast(bytes), n); + } +#endif +#endif // U_HIDE_DRAFT_API + /** * Returns a writable buffer for appending and writes the buffer's capacity to * *result_capacity. Guarantees *result_capacity>=min_capacity. diff --git a/deps/icu-small/source/common/unicode/localebuilder.h b/deps/icu-small/source/common/unicode/localebuilder.h index 19e10f1c070924..c5836fe27021b3 100644 --- a/deps/icu-small/source/common/unicode/localebuilder.h +++ b/deps/icu-small/source/common/unicode/localebuilder.h @@ -12,7 +12,6 @@ #include "unicode/stringpiece.h" #include "unicode/uobject.h" -#ifndef U_HIDE_DRAFT_API /** * \file * \brief C++ API: Builder API for Locale @@ -57,7 +56,7 @@ class CharString; * UErrorCode, then track the error of the validation of the input parameter * into the internal UErrorCode. * - * @draft ICU 64 + * @stable ICU 64 */ class U_COMMON_API LocaleBuilder : public UObject { public: @@ -66,13 +65,13 @@ class U_COMMON_API LocaleBuilder : public UObject { * fields, extensions, and private use information is the * empty string. * - * @draft ICU 64 + * @stable ICU 64 */ LocaleBuilder(); /** * Destructor - * @draft ICU 64 + * @stable ICU 64 */ virtual ~LocaleBuilder(); @@ -86,7 +85,7 @@ class U_COMMON_API LocaleBuilder : public UObject { * @param locale the locale * @return This builder. * - * @draft ICU 64 + * @stable ICU 64 */ LocaleBuilder& setLocale(const Locale& locale); @@ -104,7 +103,7 @@ class U_COMMON_API LocaleBuilder : public UObject { * @param tag the language tag, defined as * [unicode_locale_id](http://www.unicode.org/reports/tr35/tr35.html#unicode_locale_id). * @return This builder. - * @draft ICU 64 + * @stable ICU 64 */ LocaleBuilder& setLanguageTag(StringPiece tag); @@ -119,7 +118,7 @@ class U_COMMON_API LocaleBuilder : public UObject { * * @param language the language * @return This builder. - * @draft ICU 64 + * @stable ICU 64 */ LocaleBuilder& setLanguage(StringPiece language); @@ -135,7 +134,7 @@ class U_COMMON_API LocaleBuilder : public UObject { * * @param script the script * @return This builder. - * @draft ICU 64 + * @stable ICU 64 */ LocaleBuilder& setScript(StringPiece script); @@ -154,7 +153,7 @@ class U_COMMON_API LocaleBuilder : public UObject { * * @param region the region * @return This builder. - * @draft ICU 64 + * @stable ICU 64 */ LocaleBuilder& setRegion(StringPiece region); @@ -175,7 +174,7 @@ class U_COMMON_API LocaleBuilder : public UObject { * * @param variant the variant * @return This builder. - * @draft ICU 64 + * @stable ICU 64 */ LocaleBuilder& setVariant(StringPiece variant); @@ -196,7 +195,7 @@ class U_COMMON_API LocaleBuilder : public UObject { * @param key the extension key * @param value the extension value * @return This builder. - * @draft ICU 64 + * @stable ICU 64 */ LocaleBuilder& setExtension(char key, StringPiece value); @@ -216,7 +215,7 @@ class U_COMMON_API LocaleBuilder : public UObject { * @param key the Unicode locale key * @param type the Unicode locale type * @return This builder. - * @draft ICU 64 + * @stable ICU 64 */ LocaleBuilder& setUnicodeLocaleKeyword( StringPiece key, StringPiece type); @@ -229,7 +228,7 @@ class U_COMMON_API LocaleBuilder : public UObject { * * @param attribute the attribute * @return This builder. - * @draft ICU 64 + * @stable ICU 64 */ LocaleBuilder& addUnicodeLocaleAttribute(StringPiece attribute); @@ -242,7 +241,7 @@ class U_COMMON_API LocaleBuilder : public UObject { * * @param attribute the attribute * @return This builder. - * @draft ICU 64 + * @stable ICU 64 */ LocaleBuilder& removeUnicodeLocaleAttribute(StringPiece attribute); @@ -251,7 +250,7 @@ class U_COMMON_API LocaleBuilder : public UObject { *

This method clears the internal UErrorCode. * * @return this builder - * @draft ICU 64 + * @stable ICU 64 */ LocaleBuilder& clear(); @@ -260,7 +259,7 @@ class U_COMMON_API LocaleBuilder : public UObject { * Language, script, region and variant are unchanged. * * @return this builder - * @draft ICU 64 + * @stable ICU 64 */ LocaleBuilder& clearExtensions(); @@ -275,7 +274,7 @@ class U_COMMON_API LocaleBuilder : public UObject { * the same builder to build more locales. * * @return a new Locale - * @draft ICU 64 + * @stable ICU 64 */ Locale build(UErrorCode& status); @@ -308,8 +307,6 @@ class U_COMMON_API LocaleBuilder : public UObject { U_NAMESPACE_END -#endif // U_HIDE_DRAFT_API - #endif /* U_SHOW_CPLUSPLUS_API */ #endif // __LOCALEBUILDER_H__ diff --git a/deps/icu-small/source/common/unicode/localematcher.h b/deps/icu-small/source/common/unicode/localematcher.h index 701123f750b222..2e1a7a349f3983 100644 --- a/deps/icu-small/source/common/unicode/localematcher.h +++ b/deps/icu-small/source/common/unicode/localematcher.h @@ -20,12 +20,12 @@ * \brief C++ API: Locale matcher: User's desired locales vs. application's supported locales. */ -#ifndef U_HIDE_DRAFT_API +#ifndef U_FORCE_HIDE_DRAFT_API /** * Builder option for whether the language subtag or the script subtag is most important. * - * @see Builder#setFavorSubtag(FavorSubtag) + * @see Builder#setFavorSubtag(ULocMatchFavorSubtag) * @draft ICU 65 */ enum ULocMatchFavorSubtag { @@ -51,7 +51,7 @@ typedef enum ULocMatchFavorSubtag ULocMatchFavorSubtag; * Builder option for whether all desired locales are treated equally or * earlier ones are preferred. * - * @see Builder#setDemotionPerDesiredLocale(Demotion) + * @see Builder#setDemotionPerDesiredLocale(ULocMatchDemotion) * @draft ICU 65 */ enum ULocMatchDemotion { @@ -93,6 +93,42 @@ enum ULocMatchDemotion { typedef enum ULocMatchDemotion ULocMatchDemotion; #endif +/** + * Builder option for whether to include or ignore one-way (fallback) match data. + * The LocaleMatcher uses CLDR languageMatch data which includes fallback (oneway=true) entries. + * Sometimes it is desirable to ignore those. + * + *

For example, consider a web application with the UI in a given language, + * with a link to another, related web app. + * The link should include the UI language, and the target server may also use + * the client’s Accept-Language header data. + * The target server has its own list of supported languages. + * One may want to favor UI language consistency, that is, + * if there is a decent match for the original UI language, we want to use it, + * but not if it is merely a fallback. + * + * @see Builder#setDirection(ULocMatchDirection) + * @draft ICU 67 + */ +enum ULocMatchDirection { + /** + * Locale matching includes one-way matches such as Breton→French. (default) + * + * @draft ICU 67 + */ + ULOCMATCH_DIRECTION_WITH_ONE_WAY, + /** + * Locale matching limited to two-way matches including e.g. Danish↔Norwegian + * but ignoring one-way matches. + * + * @draft ICU 67 + */ + ULOCMATCH_DIRECTION_ONLY_TWO_WAY +}; +#ifndef U_IN_DOXYGEN +typedef enum ULocMatchDirection ULocMatchDirection; +#endif + struct UHashtable; U_NAMESPACE_BEGIN @@ -182,6 +218,7 @@ class U_COMMON_API LocaleMatcher : public UMemory { */ Result &operator=(Result &&src) U_NOEXCEPT; +#ifndef U_HIDE_DRAFT_API /** * Returns the best-matching desired locale. * nullptr if the list of desired locales is empty or if none matched well enough. @@ -236,6 +273,7 @@ class U_COMMON_API LocaleMatcher : public UMemory { * @draft ICU 65 */ Locale makeResolvedLocale(UErrorCode &errorCode) const; +#endif // U_HIDE_DRAFT_API private: Result(const Locale *desired, const Locale *supported, @@ -298,6 +336,7 @@ class U_COMMON_API LocaleMatcher : public UMemory { */ Builder &operator=(Builder &&src) U_NOEXCEPT; +#ifndef U_HIDE_DRAFT_API /** * Parses an Accept-Language string * (RFC 2616 Section 14.4), @@ -412,6 +451,21 @@ class U_COMMON_API LocaleMatcher : public UMemory { */ Builder &setDemotionPerDesiredLocale(ULocMatchDemotion demotion); + /** + * Option for whether to include or ignore one-way (fallback) match data. + * By default, they are included. + * + * @param direction the match direction to set. + * @return this Builder object + * @draft ICU 67 + */ + Builder &setDirection(ULocMatchDirection direction) { + if (U_SUCCESS(errorCode_)) { + direction_ = direction; + } + return *this; + } + /** * Sets the UErrorCode if an error occurred while setting parameters. * Preserves older error codes in the outErrorCode. @@ -435,6 +489,7 @@ class U_COMMON_API LocaleMatcher : public UMemory { * @draft ICU 65 */ LocaleMatcher build(UErrorCode &errorCode) const; +#endif // U_HIDE_DRAFT_API private: friend class LocaleMatcher; @@ -451,6 +506,7 @@ class U_COMMON_API LocaleMatcher : public UMemory { ULocMatchDemotion demotion_ = ULOCMATCH_DEMOTION_REGION; Locale *defaultLocale_ = nullptr; ULocMatchFavorSubtag favor_ = ULOCMATCH_FAVOR_LANGUAGE; + ULocMatchDirection direction_ = ULOCMATCH_DIRECTION_WITH_ONE_WAY; }; // FYI No public LocaleMatcher constructors in C++; use the Builder. @@ -479,6 +535,7 @@ class U_COMMON_API LocaleMatcher : public UMemory { */ LocaleMatcher &operator=(LocaleMatcher &&src) U_NOEXCEPT; +#ifndef U_HIDE_DRAFT_API /** * Returns the supported locale which best matches the desired locale. * @@ -546,6 +603,7 @@ class U_COMMON_API LocaleMatcher : public UMemory { * @draft ICU 65 */ Result getBestMatchResult(Locale::Iterator &desiredLocales, UErrorCode &errorCode) const; +#endif // U_HIDE_DRAFT_API #ifndef U_HIDE_INTERNAL_API /** @@ -574,6 +632,8 @@ class U_COMMON_API LocaleMatcher : public UMemory { LocaleMatcher(const LocaleMatcher &other) = delete; LocaleMatcher &operator=(const LocaleMatcher &other) = delete; + int32_t putIfAbsent(const LSR &lsr, int32_t i, int32_t suppLength, UErrorCode &errorCode); + int32_t getBestSuppIndex(LSR desiredLSR, LocaleLsrIterator *remainingIter, UErrorCode &errorCode) const; const XLikelySubtags &likelySubtags; @@ -581,6 +641,7 @@ class U_COMMON_API LocaleMatcher : public UMemory { int32_t thresholdDistance; int32_t demotionPerDesiredLocale; ULocMatchFavorSubtag favorSubtag; + ULocMatchDirection direction; // These are in input order. const Locale ** supportedLocales; @@ -595,11 +656,10 @@ class U_COMMON_API LocaleMatcher : public UMemory { int32_t supportedLSRsLength; Locale *ownedDefaultLocale; const Locale *defaultLocale; - int32_t defaultLocaleIndex; }; U_NAMESPACE_END -#endif // U_HIDE_DRAFT_API +#endif // U_FORCE_HIDE_DRAFT_API #endif // U_SHOW_CPLUSPLUS_API #endif // __LOCALEMATCHER_H__ diff --git a/deps/icu-small/source/common/unicode/localpointer.h b/deps/icu-small/source/common/unicode/localpointer.h index e011688b1a54df..61c3020918e578 100644 --- a/deps/icu-small/source/common/unicode/localpointer.h +++ b/deps/icu-small/source/common/unicode/localpointer.h @@ -225,7 +225,6 @@ class LocalPointer : public LocalPointerBase { src.ptr=NULL; } -#ifndef U_HIDE_DRAFT_API /** * Constructs a LocalPointer from a C++11 std::unique_ptr. * The LocalPointer steals the object owned by the std::unique_ptr. @@ -234,11 +233,10 @@ class LocalPointer : public LocalPointerBase { * in a local variable, you must use std::move. * * @param p The std::unique_ptr from which the pointer will be stolen. - * @draft ICU 64 + * @stable ICU 64 */ explicit LocalPointer(std::unique_ptr &&p) : LocalPointerBase(p.release()) {} -#endif /* U_HIDE_DRAFT_API */ /** * Destructor deletes the object it owns. @@ -261,20 +259,18 @@ class LocalPointer : public LocalPointerBase { return *this; } -#ifndef U_HIDE_DRAFT_API /** * Move-assign from an std::unique_ptr to this LocalPointer. * Steals the pointer from the std::unique_ptr. * * @param p The std::unique_ptr from which the pointer will be stolen. * @return *this - * @draft ICU 64 + * @stable ICU 64 */ LocalPointer &operator=(std::unique_ptr &&p) U_NOEXCEPT { adoptInstead(p.release()); return *this; } -#endif /* U_HIDE_DRAFT_API */ /** * Swap pointers. @@ -332,7 +328,6 @@ class LocalPointer : public LocalPointerBase { } } -#ifndef U_HIDE_DRAFT_API /** * Conversion operator to a C++11 std::unique_ptr. * Disowns the object and gives it to the returned std::unique_ptr. @@ -342,12 +337,11 @@ class LocalPointer : public LocalPointerBase { * * @return An std::unique_ptr owning the pointer previously owned by this * icu::LocalPointer. - * @draft ICU 64 + * @stable ICU 64 */ operator std::unique_ptr () && { return std::unique_ptr(LocalPointerBase::orphan()); } -#endif /* U_HIDE_DRAFT_API */ }; /** @@ -406,7 +400,6 @@ class LocalArray : public LocalPointerBase { src.ptr=NULL; } -#ifndef U_HIDE_DRAFT_API /** * Constructs a LocalArray from a C++11 std::unique_ptr of an array type. * The LocalPointer steals the array owned by the std::unique_ptr. @@ -415,11 +408,10 @@ class LocalArray : public LocalPointerBase { * in a local variable, you must use std::move. * * @param p The std::unique_ptr from which the array will be stolen. - * @draft ICU 64 + * @stable ICU 64 */ explicit LocalArray(std::unique_ptr &&p) : LocalPointerBase(p.release()) {} -#endif /* U_HIDE_DRAFT_API */ /** * Destructor deletes the array it owns. @@ -442,20 +434,18 @@ class LocalArray : public LocalPointerBase { return *this; } -#ifndef U_HIDE_DRAFT_API /** * Move-assign from an std::unique_ptr to this LocalPointer. * Steals the array from the std::unique_ptr. * * @param p The std::unique_ptr from which the array will be stolen. * @return *this - * @draft ICU 64 + * @stable ICU 64 */ LocalArray &operator=(std::unique_ptr &&p) U_NOEXCEPT { adoptInstead(p.release()); return *this; } -#endif /* U_HIDE_DRAFT_API */ /** * Swap pointers. @@ -521,7 +511,6 @@ class LocalArray : public LocalPointerBase { */ T &operator[](ptrdiff_t i) const { return LocalPointerBase::ptr[i]; } -#ifndef U_HIDE_DRAFT_API /** * Conversion operator to a C++11 std::unique_ptr. * Disowns the object and gives it to the returned std::unique_ptr. @@ -531,12 +520,11 @@ class LocalArray : public LocalPointerBase { * * @return An std::unique_ptr owning the pointer previously owned by this * icu::LocalPointer. - * @draft ICU 64 + * @stable ICU 64 */ operator std::unique_ptr () && { return std::unique_ptr(LocalPointerBase::orphan()); } -#endif /* U_HIDE_DRAFT_API */ }; /** diff --git a/deps/icu-small/source/common/unicode/locid.h b/deps/icu-small/source/common/unicode/locid.h index 6fb0897fc05d95..ee8697b0a57f3e 100644 --- a/deps/icu-small/source/common/unicode/locid.h +++ b/deps/icu-small/source/common/unicode/locid.h @@ -448,7 +448,7 @@ class U_COMMON_API Locale : public UObject { /** * Creates a locale from the given string after canonicalizing - * the string by calling uloc_canonicalize(). + * the string according to CLDR by calling uloc_canonicalize(). * @param name the locale ID to create from. Must not be NULL. * @return a new locale object corresponding to the given name * @stable ICU 3.0 @@ -567,6 +567,16 @@ class U_COMMON_API Locale : public UObject { */ void minimizeSubtags(UErrorCode& status); +#ifndef U_HIDE_DRAFT_API + /** + * Canonicalize the locale ID of this object according to CLDR. + * @param status the status code + * @draft ICU 67 + * @see createCanonical + */ + void canonicalize(UErrorCode& status); +#endif // U_HIDE_DRAFT_API + /** * Gets the list of keywords for the specified locale. * diff --git a/deps/icu-small/source/common/unicode/platform.h b/deps/icu-small/source/common/unicode/platform.h index 74689d790cf79a..d6f792ba345b7e 100644 --- a/deps/icu-small/source/common/unicode/platform.h +++ b/deps/icu-small/source/common/unicode/platform.h @@ -828,7 +828,7 @@ namespace std { # define U_EXPORT #endif -/* U_CALLCONV is releated to U_EXPORT2 */ +/* U_CALLCONV is related to U_EXPORT2 */ #ifdef U_EXPORT2 /* Use the predefined value. */ #elif defined(_MSC_VER) diff --git a/deps/icu-small/source/common/unicode/stringpiece.h b/deps/icu-small/source/common/unicode/stringpiece.h index 15cebb0f202fe7..19fbe2e22eb032 100644 --- a/deps/icu-small/source/common/unicode/stringpiece.h +++ b/deps/icu-small/source/common/unicode/stringpiece.h @@ -67,19 +67,50 @@ class U_COMMON_API StringPiece : public UMemory { * Default constructor, creates an empty StringPiece. * @stable ICU 4.2 */ - StringPiece() : ptr_(NULL), length_(0) { } + StringPiece() : ptr_(nullptr), length_(0) { } + /** * Constructs from a NUL-terminated const char * pointer. * @param str a NUL-terminated const char * pointer * @stable ICU 4.2 */ StringPiece(const char* str); +#ifndef U_HIDE_DRAFT_API +#if defined(__cpp_char8_t) || defined(U_IN_DOXYGEN) + /** + * Constructs from a NUL-terminated const char8_t * pointer. + * @param str a NUL-terminated const char8_t * pointer + * @draft ICU 67 + */ + StringPiece(const char8_t* str) : StringPiece(reinterpret_cast(str)) {} +#endif + /** + * Constructs an empty StringPiece. + * Needed for type disambiguation from multiple other overloads. + * @param p nullptr + * @draft ICU 67 + */ + StringPiece(std::nullptr_t p) : ptr_(p), length_(0) {} +#endif // U_HIDE_DRAFT_API + /** * Constructs from a std::string. * @stable ICU 4.2 */ StringPiece(const std::string& str) : ptr_(str.data()), length_(static_cast(str.size())) { } +#ifndef U_HIDE_DRAFT_API +#if defined(__cpp_lib_char8_t) || defined(U_IN_DOXYGEN) + /** + * Constructs from a std::u8string. + * @draft ICU 67 + */ + StringPiece(const std::u8string& str) + : ptr_(reinterpret_cast(str.data())), + length_(static_cast(str.size())) { } +#endif +#endif // U_HIDE_DRAFT_API + #ifndef U_HIDE_DRAFT_API /** * Constructs from some other implementation of a string piece class, from any @@ -88,7 +119,7 @@ class U_COMMON_API StringPiece : public UMemory { * \code{.cpp} * * struct OtherStringPieceClass { - * const char* data(); + * const char* data(); // or const char8_t* * size_t size(); * }; * @@ -97,16 +128,25 @@ class U_COMMON_API StringPiece : public UMemory { * The other string piece class will typically be std::string_view from C++17 * or absl::string_view from Abseil. * + * Starting with C++20, data() may also return a const char8_t* pointer, + * as from std::u8string_view. + * * @param str the other string piece * @draft ICU 65 */ template ::value && + (std::is_same::value +#if defined(__cpp_char8_t) + || std::is_same::value +#endif + ) && std::is_same::value>::type> StringPiece(T str) - : ptr_(str.data()), length_(static_cast(str.size())) {} + : ptr_(reinterpret_cast(str.data())), + length_(static_cast(str.size())) {} #endif // U_HIDE_DRAFT_API + /** * Constructs from a const char * pointer and a specified length. * @param offset a const char * pointer (need not be terminated) @@ -114,6 +154,19 @@ class U_COMMON_API StringPiece : public UMemory { * @stable ICU 4.2 */ StringPiece(const char* offset, int32_t len) : ptr_(offset), length_(len) { } +#ifndef U_HIDE_DRAFT_API +#if defined(__cpp_char8_t) || defined(U_IN_DOXYGEN) + /** + * Constructs from a const char8_t * pointer and a specified length. + * @param str a const char8_t * pointer (need not be terminated) + * @param len the length of the string; must be non-negative + * @draft ICU 67 + */ + StringPiece(const char8_t* str, int32_t len) : + StringPiece(reinterpret_cast(str), len) {} +#endif +#endif // U_HIDE_DRAFT_API + /** * Substring of another StringPiece. * @param x the other StringPiece @@ -132,7 +185,7 @@ class U_COMMON_API StringPiece : public UMemory { StringPiece(const StringPiece& x, int32_t pos, int32_t len); /** - * Returns the string pointer. May be NULL if it is empty. + * Returns the string pointer. May be nullptr if it is empty. * * data() may return a pointer to a buffer with embedded NULs, and the * returned buffer may or may not be null terminated. Therefore it is @@ -165,7 +218,7 @@ class U_COMMON_API StringPiece : public UMemory { * Sets to an empty string. * @stable ICU 4.2 */ - void clear() { ptr_ = NULL; length_ = 0; } + void clear() { ptr_ = nullptr; length_ = 0; } /** * Reset the stringpiece to refer to new data. @@ -182,6 +235,29 @@ class U_COMMON_API StringPiece : public UMemory { */ void set(const char* str); +#ifndef U_HIDE_DRAFT_API +#if defined(__cpp_char8_t) || defined(U_IN_DOXYGEN) + /** + * Resets the stringpiece to refer to new data. + * @param xdata pointer the new string data. Need not be NUL-terminated. + * @param len the length of the new data + * @draft ICU 67 + */ + inline void set(const char8_t* xdata, int32_t len) { + set(reinterpret_cast(xdata), len); + } + + /** + * Resets the stringpiece to refer to new data. + * @param str a pointer to a NUL-terminated string. + * @draft ICU 67 + */ + inline void set(const char8_t* str) { + set(reinterpret_cast(str)); + } +#endif +#endif // U_HIDE_DRAFT_API + /** * Removes the first n string units. * @param n prefix length, must be non-negative and <=length() @@ -212,6 +288,26 @@ class U_COMMON_API StringPiece : public UMemory { } } +#ifndef U_HIDE_DRAFT_API + /** + * Searches the StringPiece for the given search string (needle); + * @param needle The string for which to search. + * @param offset Where to start searching within this string (haystack). + * @return The offset of needle in haystack, or -1 if not found. + * @draft ICU 67 + */ + int32_t find(StringPiece needle, int32_t offset); + + /** + * Compares this StringPiece with the other StringPiece, with semantics + * similar to std::string::compare(). + * @param other The string to compare to. + * @return below zero if this < other; above zero if this > other; 0 if this == other. + * @draft ICU 67 + */ + int32_t compare(StringPiece other); +#endif // U_HIDE_DRAFT_API + /** * Maximum integer, used as a default value for substring methods. * @stable ICU 4.2 diff --git a/deps/icu-small/source/common/unicode/uloc.h b/deps/icu-small/source/common/unicode/uloc.h index 882f79bedca62c..a10ab526cec141 100644 --- a/deps/icu-small/source/common/unicode/uloc.h +++ b/deps/icu-small/source/common/unicode/uloc.h @@ -1034,29 +1034,45 @@ uloc_getLineOrientation(const char* localeId, UErrorCode *status); /** - * enums for the 'outResult' parameter return value + * Output values which uloc_acceptLanguage() writes to the 'outResult' parameter. + * * @see uloc_acceptLanguageFromHTTP * @see uloc_acceptLanguage * @stable ICU 3.2 */ typedef enum { - ULOC_ACCEPT_FAILED = 0, /* No exact match was found. */ - ULOC_ACCEPT_VALID = 1, /* An exact match was found. */ - ULOC_ACCEPT_FALLBACK = 2 /* A fallback was found, for example, - Accept list contained 'ja_JP' - which matched available locale 'ja'. */ + /** + * No exact match was found. + * @stable ICU 3.2 + */ + ULOC_ACCEPT_FAILED = 0, + /** + * An exact match was found. + * @stable ICU 3.2 + */ + ULOC_ACCEPT_VALID = 1, + /** + * A fallback was found. For example, the Accept-Language list includes 'ja_JP' + * and is matched with available locale 'ja'. + * @stable ICU 3.2 + */ + ULOC_ACCEPT_FALLBACK = 2 /* */ } UAcceptResult; - /** * Based on a HTTP header from a web browser and a list of available locales, * determine an acceptable locale for the user. + * + * This is a thin wrapper over C++ class LocaleMatcher. + * * @param result - buffer to accept the result locale * @param resultAvailable the size of the result buffer. * @param outResult - An out parameter that contains the fallback status * @param httpAcceptLanguage - "Accept-Language:" header as per HTTP. * @param availableLocales - list of available locales to match - * @param status Error status, may be BUFFER_OVERFLOW_ERROR + * @param status ICU error code. Its input value must pass the U_SUCCESS() test, + * or else the function returns immediately. Check for U_FAILURE() + * on output or use with function chaining. (See User Guide for details.) * @return length needed for the locale. * @stable ICU 3.2 */ @@ -1070,13 +1086,18 @@ uloc_acceptLanguageFromHTTP(char *result, int32_t resultAvailable, /** * Based on a list of available locales, * determine an acceptable locale for the user. + * + * This is a thin wrapper over C++ class LocaleMatcher. + * * @param result - buffer to accept the result locale * @param resultAvailable the size of the result buffer. * @param outResult - An out parameter that contains the fallback status * @param acceptList - list of acceptable languages * @param acceptListCount - count of acceptList items * @param availableLocales - list of available locales to match - * @param status Error status, may be BUFFER_OVERFLOW_ERROR + * @param status ICU error code. Its input value must pass the U_SUCCESS() test, + * or else the function returns immediately. Check for U_FAILURE() + * on output or use with function chaining. (See User Guide for details.) * @return length needed for the locale. * @stable ICU 3.2 */ diff --git a/deps/icu-small/source/common/unicode/umachine.h b/deps/icu-small/source/common/unicode/umachine.h index 5cb95e58f37295..ff5deb8d01786a 100644 --- a/deps/icu-small/source/common/unicode/umachine.h +++ b/deps/icu-small/source/common/unicode/umachine.h @@ -372,7 +372,7 @@ typedef int8_t UBool; typedef char16_t UChar; #elif defined(UCHAR_TYPE) typedef UCHAR_TYPE UChar; -#elif defined(__cplusplus) +#elif (U_CPLUSPLUS_VERSION >= 11) typedef char16_t UChar; #else typedef uint16_t UChar; diff --git a/deps/icu-small/source/common/unicode/umutablecptrie.h b/deps/icu-small/source/common/unicode/umutablecptrie.h index 13e71ef25e8c87..f2af36477d5300 100644 --- a/deps/icu-small/source/common/unicode/umutablecptrie.h +++ b/deps/icu-small/source/common/unicode/umutablecptrie.h @@ -83,25 +83,6 @@ umutablecptrie_clone(const UMutableCPTrie *other, UErrorCode *pErrorCode); U_CAPI void U_EXPORT2 umutablecptrie_close(UMutableCPTrie *trie); -#if U_SHOW_CPLUSPLUS_API - -U_NAMESPACE_BEGIN - -/** - * \class LocalUMutableCPTriePointer - * "Smart pointer" class, closes a UMutableCPTrie via umutablecptrie_close(). - * For most methods see the LocalPointerBase base class. - * - * @see LocalPointerBase - * @see LocalPointer - * @stable ICU 63 - */ -U_DEFINE_LOCAL_OPEN_POINTER(LocalUMutableCPTriePointer, UMutableCPTrie, umutablecptrie_close); - -U_NAMESPACE_END - -#endif - /** * Creates a mutable trie with the same contents as the UCPMap. * You must umutablecptrie_close() the mutable trie once you are done using it. @@ -235,4 +216,23 @@ umutablecptrie_buildImmutable(UMutableCPTrie *trie, UCPTrieType type, UCPTrieVal U_CDECL_END +#if U_SHOW_CPLUSPLUS_API + +U_NAMESPACE_BEGIN + +/** + * \class LocalUMutableCPTriePointer + * "Smart pointer" class, closes a UMutableCPTrie via umutablecptrie_close(). + * For most methods see the LocalPointerBase base class. + * + * @see LocalPointerBase + * @see LocalPointer + * @stable ICU 63 + */ +U_DEFINE_LOCAL_OPEN_POINTER(LocalUMutableCPTriePointer, UMutableCPTrie, umutablecptrie_close); + +U_NAMESPACE_END + +#endif + #endif diff --git a/deps/icu-small/source/common/unicode/urename.h b/deps/icu-small/source/common/unicode/urename.h index 5b793bbfd48d1e..30f4b7af39adc5 100644 --- a/deps/icu-small/source/common/unicode/urename.h +++ b/deps/icu-small/source/common/unicode/urename.h @@ -135,6 +135,7 @@ #define locale_get_default U_ICU_ENTRY_POINT_RENAME(locale_get_default) #define locale_set_default U_ICU_ENTRY_POINT_RENAME(locale_set_default) #define numSysCleanup U_ICU_ENTRY_POINT_RENAME(numSysCleanup) +#define rbbi_cleanup U_ICU_ENTRY_POINT_RENAME(rbbi_cleanup) #define pl_addFontRun U_ICU_ENTRY_POINT_RENAME(pl_addFontRun) #define pl_addLocaleRun U_ICU_ENTRY_POINT_RENAME(pl_addLocaleRun) #define pl_addValueRun U_ICU_ENTRY_POINT_RENAME(pl_addValueRun) @@ -203,6 +204,7 @@ #define res_read U_ICU_ENTRY_POINT_RENAME(res_read) #define res_unload U_ICU_ENTRY_POINT_RENAME(res_unload) #define u_UCharsToChars U_ICU_ENTRY_POINT_RENAME(u_UCharsToChars) +#define u_asciiToUpper U_ICU_ENTRY_POINT_RENAME(u_asciiToUpper) #define u_austrcpy U_ICU_ENTRY_POINT_RENAME(u_austrcpy) #define u_austrncpy U_ICU_ENTRY_POINT_RENAME(u_austrncpy) #define u_caseInsensitivePrefixMatch U_ICU_ENTRY_POINT_RENAME(u_caseInsensitivePrefixMatch) @@ -896,6 +898,7 @@ #define udatpg_getBestPatternWithOptions U_ICU_ENTRY_POINT_RENAME(udatpg_getBestPatternWithOptions) #define udatpg_getDateTimeFormat U_ICU_ENTRY_POINT_RENAME(udatpg_getDateTimeFormat) #define udatpg_getDecimal U_ICU_ENTRY_POINT_RENAME(udatpg_getDecimal) +#define udatpg_getDefaultHourCycle U_ICU_ENTRY_POINT_RENAME(udatpg_getDefaultHourCycle) #define udatpg_getFieldDisplayName U_ICU_ENTRY_POINT_RENAME(udatpg_getFieldDisplayName) #define udatpg_getPatternForSkeleton U_ICU_ENTRY_POINT_RENAME(udatpg_getPatternForSkeleton) #define udatpg_getSkeleton U_ICU_ENTRY_POINT_RENAME(udatpg_getSkeleton) @@ -913,6 +916,7 @@ #define udtitvfmt_close U_ICU_ENTRY_POINT_RENAME(udtitvfmt_close) #define udtitvfmt_closeResult U_ICU_ENTRY_POINT_RENAME(udtitvfmt_closeResult) #define udtitvfmt_format U_ICU_ENTRY_POINT_RENAME(udtitvfmt_format) +#define udtitvfmt_formatCalendarToResult U_ICU_ENTRY_POINT_RENAME(udtitvfmt_formatCalendarToResult) #define udtitvfmt_formatToResult U_ICU_ENTRY_POINT_RENAME(udtitvfmt_formatToResult) #define udtitvfmt_open U_ICU_ENTRY_POINT_RENAME(udtitvfmt_open) #define udtitvfmt_openResult U_ICU_ENTRY_POINT_RENAME(udtitvfmt_openResult) @@ -1053,6 +1057,7 @@ #define ulistfmt_format U_ICU_ENTRY_POINT_RENAME(ulistfmt_format) #define ulistfmt_formatStringsToResult U_ICU_ENTRY_POINT_RENAME(ulistfmt_formatStringsToResult) #define ulistfmt_open U_ICU_ENTRY_POINT_RENAME(ulistfmt_open) +#define ulistfmt_openForType U_ICU_ENTRY_POINT_RENAME(ulistfmt_openForType) #define ulistfmt_openResult U_ICU_ENTRY_POINT_RENAME(ulistfmt_openResult) #define ulistfmt_resultAsValue U_ICU_ENTRY_POINT_RENAME(ulistfmt_resultAsValue) #define uloc_acceptLanguage U_ICU_ENTRY_POINT_RENAME(uloc_acceptLanguage) @@ -1114,9 +1119,12 @@ #define ulocdata_open U_ICU_ENTRY_POINT_RENAME(ulocdata_open) #define ulocdata_setNoSubstitute U_ICU_ENTRY_POINT_RENAME(ulocdata_setNoSubstitute) #define ulocimp_addLikelySubtags U_ICU_ENTRY_POINT_RENAME(ulocimp_addLikelySubtags) +#define ulocimp_canonicalize U_ICU_ENTRY_POINT_RENAME(ulocimp_canonicalize) #define ulocimp_forLanguageTag U_ICU_ENTRY_POINT_RENAME(ulocimp_forLanguageTag) +#define ulocimp_getBaseName U_ICU_ENTRY_POINT_RENAME(ulocimp_getBaseName) #define ulocimp_getCountry U_ICU_ENTRY_POINT_RENAME(ulocimp_getCountry) #define ulocimp_getLanguage U_ICU_ENTRY_POINT_RENAME(ulocimp_getLanguage) +#define ulocimp_getName U_ICU_ENTRY_POINT_RENAME(ulocimp_getName) #define ulocimp_getRegionForSupplementalData U_ICU_ENTRY_POINT_RENAME(ulocimp_getRegionForSupplementalData) #define ulocimp_getScript U_ICU_ENTRY_POINT_RENAME(ulocimp_getScript) #define ulocimp_minimizeSubtags U_ICU_ENTRY_POINT_RENAME(ulocimp_minimizeSubtags) @@ -1295,7 +1303,6 @@ #define uprv_convertToPosix U_ICU_ENTRY_POINT_RENAME(uprv_convertToPosix) #define uprv_copyAscii U_ICU_ENTRY_POINT_RENAME(uprv_copyAscii) #define uprv_copyEbcdic U_ICU_ENTRY_POINT_RENAME(uprv_copyEbcdic) -#define uprv_currencyLeads U_ICU_ENTRY_POINT_RENAME(uprv_currencyLeads) #define uprv_decContextClearStatus U_ICU_ENTRY_POINT_RENAME(uprv_decContextClearStatus) #define uprv_decContextDefault U_ICU_ENTRY_POINT_RENAME(uprv_decContextDefault) #define uprv_decContextGetRounding U_ICU_ENTRY_POINT_RENAME(uprv_decContextGetRounding) diff --git a/deps/icu-small/source/common/unicode/utext.h b/deps/icu-small/source/common/unicode/utext.h index 6f1e3409d8fdeb..d36c1c035e70f1 100644 --- a/deps/icu-small/source/common/unicode/utext.h +++ b/deps/icu-small/source/common/unicode/utext.h @@ -183,25 +183,6 @@ typedef struct UText UText; /**< C typedef for struct UText. @stable ICU 3.6 */ U_STABLE UText * U_EXPORT2 utext_close(UText *ut); -#if U_SHOW_CPLUSPLUS_API - -U_NAMESPACE_BEGIN - -/** - * \class LocalUTextPointer - * "Smart pointer" class, closes a UText via utext_close(). - * For most methods see the LocalPointerBase base class. - * - * @see LocalPointerBase - * @see LocalPointer - * @stable ICU 4.4 - */ -U_DEFINE_LOCAL_OPEN_POINTER(LocalUTextPointer, UText, utext_close); - -U_NAMESPACE_END - -#endif - /** * Open a read-only UText implementation for UTF-8 strings. * @@ -1599,5 +1580,24 @@ enum { U_CDECL_END +#if U_SHOW_CPLUSPLUS_API + +U_NAMESPACE_BEGIN + +/** + * \class LocalUTextPointer + * "Smart pointer" class, closes a UText via utext_close(). + * For most methods see the LocalPointerBase base class. + * + * @see LocalPointerBase + * @see LocalPointer + * @stable ICU 4.4 + */ +U_DEFINE_LOCAL_OPEN_POINTER(LocalUTextPointer, UText, utext_close); + +U_NAMESPACE_END + +#endif + #endif diff --git a/deps/icu-small/source/common/unicode/utrace.h b/deps/icu-small/source/common/unicode/utrace.h index 0af050756fc38a..c7d51ff44f5bf7 100644 --- a/deps/icu-small/source/common/unicode/utrace.h +++ b/deps/icu-small/source/common/unicode/utrace.h @@ -177,6 +177,71 @@ typedef enum UTraceFunctionNumber { UTRACE_RES_DATA_LIMIT, #endif // U_HIDE_INTERNAL_API +#ifndef U_HIDE_DRAFT_API + /** + * The lowest break iterator location. + * @draft ICU 67 + */ + UTRACE_UBRK_START=0x4000, + + /** + * Indicates that a character instance of break iterator was created. + * + * @draft ICU 67 + */ + UTRACE_UBRK_CREATE_CHARACTER = UTRACE_UBRK_START, + + /** + * Indicates that a word instance of break iterator was created. + * + * @draft ICU 67 + */ + UTRACE_UBRK_CREATE_WORD, + + /** + * Indicates that a line instance of break iterator was created. + * + * Provides one C-style string to UTraceData: the lb value ("", + * "loose", "strict", or "normal"). + * + * @draft ICU 67 + */ + UTRACE_UBRK_CREATE_LINE, + + /** + * Indicates that a sentence instance of break iterator was created. + * + * @draft ICU 67 + */ + UTRACE_UBRK_CREATE_SENTENCE, + + /** + * Indicates that a title instance of break iterator was created. + * + * @draft ICU 67 + */ + UTRACE_UBRK_CREATE_TITLE, + + /** + * Indicates that an internal dictionary break engine was created. + * + * Provides one C-style string to UTraceData: the script code of what + * the break engine cover ("Hani", "Khmr", "Laoo", "Mymr", or "Thai"). + * + * @draft ICU 67 + */ + UTRACE_UBRK_CREATE_BREAK_ENGINE, + +#endif // U_HIDE_DRAFT_API + +#ifndef U_HIDE_INTERNAL_API + /** + * One more than the highest normal break iterator trace location. + * @internal The numeric value may change over time, see ICU ticket #12420. + */ + UTRACE_UBRK_LIMIT, +#endif // U_HIDE_INTERNAL_API + } UTraceFunctionNumber; /** diff --git a/deps/icu-small/source/common/unicode/uvernum.h b/deps/icu-small/source/common/unicode/uvernum.h index f5d6497842c5f7..c66776d10b5826 100644 --- a/deps/icu-small/source/common/unicode/uvernum.h +++ b/deps/icu-small/source/common/unicode/uvernum.h @@ -60,7 +60,7 @@ * This value will change in the subsequent releases of ICU * @stable ICU 2.4 */ -#define U_ICU_VERSION_MAJOR_NUM 66 +#define U_ICU_VERSION_MAJOR_NUM 67 /** The current ICU minor version as an integer. * This value will change in the subsequent releases of ICU @@ -86,7 +86,7 @@ * This value will change in the subsequent releases of ICU * @stable ICU 2.6 */ -#define U_ICU_VERSION_SUFFIX _66 +#define U_ICU_VERSION_SUFFIX _67 /** * \def U_DEF2_ICU_ENTRY_POINT_RENAME @@ -139,7 +139,7 @@ * This value will change in the subsequent releases of ICU * @stable ICU 2.4 */ -#define U_ICU_VERSION "66.1" +#define U_ICU_VERSION "67.1" /** * The current ICU library major version number as a string, for library name suffixes. @@ -152,13 +152,13 @@ * * @stable ICU 2.6 */ -#define U_ICU_VERSION_SHORT "66" +#define U_ICU_VERSION_SHORT "67" #ifndef U_HIDE_INTERNAL_API /** Data version in ICU4C. * @internal ICU 4.4 Internal Use Only **/ -#define U_ICU_DATA_VERSION "66.1" +#define U_ICU_DATA_VERSION "67.1" #endif /* U_HIDE_INTERNAL_API */ /*=========================================================================== diff --git a/deps/icu-small/source/common/unistr.cpp b/deps/icu-small/source/common/unistr.cpp index eeb0c3a679a5e9..1c59de972d95ed 100644 --- a/deps/icu-small/source/common/unistr.cpp +++ b/deps/icu-small/source/common/unistr.cpp @@ -1563,7 +1563,11 @@ UnicodeString::doAppend(const UChar *srcChars, int32_t srcStart, int32_t srcLeng } int32_t oldLength = length(); - int32_t newLength = oldLength + srcLength; + int32_t newLength; + if (uprv_add32_overflow(oldLength, srcLength, &newLength)) { + setToBogus(); + return *this; + } // Check for append onto ourself const UChar* oldArray = getArrayStart(); diff --git a/deps/icu-small/source/common/uposixdefs.h b/deps/icu-small/source/common/uposixdefs.h index 45ca1233ac731a..23c3f6d466700c 100644 --- a/deps/icu-small/source/common/uposixdefs.h +++ b/deps/icu-small/source/common/uposixdefs.h @@ -68,4 +68,10 @@ # define _STDC_C99 #endif +#if !defined _POSIX_C_SOURCE && \ + defined(__APPLE__) && defined(__MACH__) && !defined(__clang__) +// Needed to prevent EOWNERDEAD issues with GCC on Mac +#define _POSIX_C_SOURCE 200809L +#endif + #endif /* __UPOSIXDEFS_H__ */ diff --git a/deps/icu-small/source/common/uresbund.cpp b/deps/icu-small/source/common/uresbund.cpp index 3a9b4340bb4a38..f4efb8ccab5a0b 100644 --- a/deps/icu-small/source/common/uresbund.cpp +++ b/deps/icu-small/source/common/uresbund.cpp @@ -2611,8 +2611,8 @@ ures_getFunctionalEquivalent(char *result, int32_t resultCapacity, char defVal[1024] = ""; /* default value for given locale */ char defLoc[1024] = ""; /* default value for given locale */ char base[1024] = ""; /* base locale */ - char found[1024]; - char parent[1024]; + char found[1024] = ""; + char parent[1024] = ""; char full[1024] = ""; UResourceBundle bund1, bund2; UResourceBundle *res = NULL; diff --git a/deps/icu-small/source/common/uscript.cpp b/deps/icu-small/source/common/uscript.cpp index 98528c158b4387..f8bd7e7fdd1ae2 100644 --- a/deps/icu-small/source/common/uscript.cpp +++ b/deps/icu-small/source/common/uscript.cpp @@ -58,8 +58,8 @@ static int32_t getCodesFromLocale(const char *locale, UScriptCode *scripts, int32_t capacity, UErrorCode *err) { UErrorCode internalErrorCode = U_ZERO_ERROR; - char lang[8]; - char script[8]; + char lang[8] = {0}; + char script[8] = {0}; int32_t scriptLength; if(U_FAILURE(*err)) { return 0; } // Multi-script languages, equivalent to the LocaleScript data diff --git a/deps/icu-small/source/common/ustr_imp.h b/deps/icu-small/source/common/ustr_imp.h index 943824fa197645..85d8e6d8ee6970 100644 --- a/deps/icu-small/source/common/ustr_imp.h +++ b/deps/icu-small/source/common/ustr_imp.h @@ -37,15 +37,27 @@ uprv_strCompare(const UChar *s1, int32_t length1, const UChar *s2, int32_t length2, UBool strncmpStyle, UBool codePointOrder); -U_CAPI int32_t U_EXPORT2 +U_INTERNAL int32_t U_EXPORT2 ustr_hashUCharsN(const UChar *str, int32_t length); -U_CAPI int32_t U_EXPORT2 +U_INTERNAL int32_t U_EXPORT2 ustr_hashCharsN(const char *str, int32_t length); -U_CAPI int32_t U_EXPORT2 +U_INTERNAL int32_t U_EXPORT2 ustr_hashICharsN(const char *str, int32_t length); +/** + * Convert an ASCII-range lowercase character to uppercase. + * + * @param c A UChar. + * @return If UChar is a lowercase ASCII character, returns the uppercase version. + * Otherwise, returns the input character. + */ +U_INTERNAL UChar U_EXPORT2 +u_asciiToUpper(UChar c); + +// TODO: Add u_asciiToLower if/when there is a need for it. + /** * NUL-terminate a UChar * string if possible. * If length < destCapacity then NUL-terminate. @@ -58,28 +70,28 @@ ustr_hashICharsN(const char *str, int32_t length); * @param pErrorCode ICU error code. * @return length */ -U_CAPI int32_t U_EXPORT2 +U_INTERNAL int32_t U_EXPORT2 u_terminateUChars(UChar *dest, int32_t destCapacity, int32_t length, UErrorCode *pErrorCode); /** * NUL-terminate a char * string if possible. * Same as u_terminateUChars() but for a different string type. */ -U_CAPI int32_t U_EXPORT2 +U_INTERNAL int32_t U_EXPORT2 u_terminateChars(char *dest, int32_t destCapacity, int32_t length, UErrorCode *pErrorCode); /** * NUL-terminate a UChar32 * string if possible. * Same as u_terminateUChars() but for a different string type. */ -U_CAPI int32_t U_EXPORT2 +U_INTERNAL int32_t U_EXPORT2 u_terminateUChar32s(UChar32 *dest, int32_t destCapacity, int32_t length, UErrorCode *pErrorCode); /** * NUL-terminate a wchar_t * string if possible. * Same as u_terminateUChars() but for a different string type. */ -U_CAPI int32_t U_EXPORT2 +U_INTERNAL int32_t U_EXPORT2 u_terminateWChars(wchar_t *dest, int32_t destCapacity, int32_t length, UErrorCode *pErrorCode); /** diff --git a/deps/icu-small/source/common/ustring.cpp b/deps/icu-small/source/common/ustring.cpp index 6886c145d9a216..375f66add44835 100644 --- a/deps/icu-small/source/common/ustring.cpp +++ b/deps/icu-small/source/common/ustring.cpp @@ -1451,6 +1451,14 @@ u_unescape(const char *src, UChar *dest, int32_t destCapacity) { } \ } UPRV_BLOCK_MACRO_END +U_CAPI UChar U_EXPORT2 +u_asciiToUpper(UChar c) { + if (u'a' <= c && c <= u'z') { + c = c + u'A' - u'a'; + } + return c; +} + U_CAPI int32_t U_EXPORT2 u_terminateUChars(UChar *dest, int32_t destCapacity, int32_t length, UErrorCode *pErrorCode) { __TERMINATE_STRING(dest, destCapacity, length, pErrorCode); diff --git a/deps/icu-small/source/common/utext.cpp b/deps/icu-small/source/common/utext.cpp index 324341f1ba65dc..ac828fbefa81bb 100644 --- a/deps/icu-small/source/common/utext.cpp +++ b/deps/icu-small/source/common/utext.cpp @@ -16,6 +16,8 @@ * created by: Markus W. Scherer */ +#include + #include "unicode/utypes.h" #include "unicode/ustring.h" #include "unicode/unistr.h" @@ -566,8 +568,8 @@ enum { // when a provider asks for a UText to be allocated with extra storage. struct ExtendedUText { - UText ut; - max_align_t extension; + UText ut; + std::max_align_t extension; }; static const UText emptyText = UTEXT_INITIALIZER; @@ -582,7 +584,7 @@ utext_setup(UText *ut, int32_t extraSpace, UErrorCode *status) { // We need to heap-allocate storage for the new UText int32_t spaceRequired = sizeof(UText); if (extraSpace > 0) { - spaceRequired = sizeof(ExtendedUText) + extraSpace - sizeof(max_align_t); + spaceRequired = sizeof(ExtendedUText) + extraSpace - sizeof(std::max_align_t); } ut = (UText *)uprv_malloc(spaceRequired); if (ut == NULL) { diff --git a/deps/icu-small/source/data/in/icudt66l.dat.bz2 b/deps/icu-small/source/data/in/icudt67l.dat.bz2 similarity index 55% rename from deps/icu-small/source/data/in/icudt66l.dat.bz2 rename to deps/icu-small/source/data/in/icudt67l.dat.bz2 index a4aef420257d42..7c63c0bd468f85 100644 Binary files a/deps/icu-small/source/data/in/icudt66l.dat.bz2 and b/deps/icu-small/source/data/in/icudt67l.dat.bz2 differ diff --git a/deps/icu-small/source/i18n/calendar.cpp b/deps/icu-small/source/i18n/calendar.cpp index 94625465614547..e8b718f3c4619d 100644 --- a/deps/icu-small/source/i18n/calendar.cpp +++ b/deps/icu-small/source/i18n/calendar.cpp @@ -958,7 +958,7 @@ Calendar::makeInstance(const Locale& aLocale, UErrorCode& success) { #endif c->setWeekData(aLocale, c->getType(), success); // set the correct locale (this was an indirected calendar) - char keyword[ULOC_FULLNAME_CAPACITY]; + char keyword[ULOC_FULLNAME_CAPACITY] = ""; UErrorCode tmpStatus = U_ZERO_ERROR; l.getKeywordValue("calendar", keyword, ULOC_FULLNAME_CAPACITY, tmpStatus); if (U_SUCCESS(tmpStatus) && uprv_strcmp(keyword, "iso8601") == 0) { diff --git a/deps/icu-small/source/i18n/collationtailoring.h b/deps/icu-small/source/i18n/collationtailoring.h index 9a636cf1eb9aa3..e1bc34c7d7683b 100644 --- a/deps/icu-small/source/i18n/collationtailoring.h +++ b/deps/icu-small/source/i18n/collationtailoring.h @@ -92,7 +92,7 @@ struct U_I18N_API CollationTailoring : public SharedObject { CollationTailoring(const CollationTailoring &other); }; -struct CollationCacheEntry : public SharedObject { +struct U_I18N_API CollationCacheEntry : public SharedObject { CollationCacheEntry(const Locale &loc, const CollationTailoring *t) : validLocale(loc), tailoring(t) { if(t != NULL) { diff --git a/deps/icu-small/source/i18n/currunit.cpp b/deps/icu-small/source/i18n/currunit.cpp index 03347604a4c1fc..c1febf7df6d7e6 100644 --- a/deps/icu-small/source/i18n/currunit.cpp +++ b/deps/icu-small/source/i18n/currunit.cpp @@ -16,12 +16,12 @@ #include "unicode/currunit.h" #include "unicode/ustring.h" +#include "unicode/uchar.h" #include "cstring.h" #include "uinvchar.h" #include "charstr.h" - -static constexpr char16_t kDefaultCurrency[] = u"XXX"; -static constexpr char kDefaultCurrency8[] = "XXX"; +#include "ustr_imp.h" +#include "measunit_impl.h" U_NAMESPACE_BEGIN @@ -31,22 +31,25 @@ CurrencyUnit::CurrencyUnit(ConstChar16Ptr _isoCode, UErrorCode& ec) { // non-NUL-terminated string to be passed as an argument, so it is not possible to check length. // However, we allow a NUL-terminated empty string, which should have the same behavior as nullptr. // Consider NUL-terminated strings of length 1 or 2 as invalid. - const char16_t* isoCodeToUse; + bool useDefault = false; if (U_FAILURE(ec) || _isoCode == nullptr || _isoCode[0] == 0) { - isoCodeToUse = kDefaultCurrency; + useDefault = true; } else if (_isoCode[1] == 0 || _isoCode[2] == 0) { - isoCodeToUse = kDefaultCurrency; + useDefault = true; ec = U_ILLEGAL_ARGUMENT_ERROR; } else if (!uprv_isInvariantUString(_isoCode, 3)) { // TODO: Perform a more strict ASCII check like in ICU4J isAlpha3Code? - isoCodeToUse = kDefaultCurrency; + useDefault = true; ec = U_INVARIANT_CONVERSION_ERROR; } else { - isoCodeToUse = _isoCode; + for (int32_t i=0; i<3; i++) { + isoCode[i] = u_asciiToUpper(_isoCode[i]); + } + isoCode[3] = 0; + } + if (useDefault) { + uprv_memcpy(isoCode, kDefaultCurrency, sizeof(UChar) * 4); } - // TODO: Perform uppercasing here like in ICU4J Currency.getInstance()? - uprv_memcpy(isoCode, isoCodeToUse, sizeof(UChar) * 3); - isoCode[3] = 0; char simpleIsoCode[4]; u_UCharsToChars(isoCode, simpleIsoCode, 4); initCurrency(simpleIsoCode); @@ -66,13 +69,13 @@ CurrencyUnit::CurrencyUnit(StringPiece _isoCode, UErrorCode& ec) { ec = U_INVARIANT_CONVERSION_ERROR; } else { // Have to use isoCodeBuffer to ensure the string is NUL-terminated - uprv_strncpy(isoCodeBuffer, _isoCode.data(), 3); + for (int32_t i=0; i<3; i++) { + isoCodeBuffer[i] = uprv_toupper(_isoCode.data()[i]); + } isoCodeBuffer[3] = 0; isoCodeToUse = isoCodeBuffer; } - // TODO: Perform uppercasing here like in ICU4J Currency.getInstance()? - u_charsToUChars(isoCodeToUse, isoCode, 3); - isoCode[3] = 0; + u_charsToUChars(isoCodeToUse, isoCode, 4); initCurrency(isoCodeToUse); } diff --git a/deps/icu-small/source/i18n/dcfmtsym.cpp b/deps/icu-small/source/i18n/dcfmtsym.cpp index 04113785f27308..6f19182e2bfcf7 100644 --- a/deps/icu-small/source/i18n/dcfmtsym.cpp +++ b/deps/icu-small/source/i18n/dcfmtsym.cpp @@ -167,6 +167,7 @@ DecimalFormatSymbols::operator=(const DecimalFormatSymbols& rhs) fIsCustomCurrencySymbol = rhs.fIsCustomCurrencySymbol; fIsCustomIntlCurrencySymbol = rhs.fIsCustomIntlCurrencySymbol; fCodePointZero = rhs.fCodePointZero; + currPattern = rhs.currPattern; } return *this; } @@ -453,58 +454,16 @@ DecimalFormatSymbols::initialize(const Locale& loc, UErrorCode& status, } fCodePointZero = tempCodePointZero; - // Obtain currency data from the currency API. This is strictly - // for backward compatibility; we don't use DecimalFormatSymbols - // for currency data anymore. + // Get the default currency from the currency API. UErrorCode internalStatus = U_ZERO_ERROR; // don't propagate failures out UChar curriso[4]; UnicodeString tempStr; int32_t currisoLength = ucurr_forLocale(locStr, curriso, UPRV_LENGTHOF(curriso), &internalStatus); if (U_SUCCESS(internalStatus) && currisoLength == 3) { - uprv_getStaticCurrencyName(curriso, locStr, tempStr, internalStatus); - if (U_SUCCESS(internalStatus)) { - fSymbols[kIntlCurrencySymbol].setTo(curriso, currisoLength); - fSymbols[kCurrencySymbol] = tempStr; - } - } - /* else use the default values. */ - - //load the currency data - UChar ucc[4]={0}; //Currency Codes are always 3 chars long - int32_t uccLen = 4; - const char* locName = loc.getName(); - UErrorCode localStatus = U_ZERO_ERROR; - uccLen = ucurr_forLocale(locName, ucc, uccLen, &localStatus); - - // TODO: Currency pattern data loading is duplicated in number_formatimpl.cpp - if(U_SUCCESS(localStatus) && uccLen > 0) { - char cc[4]={0}; - u_UCharsToChars(ucc, cc, uccLen); - /* An explicit currency was requested */ - LocalUResourceBundlePointer currencyResource(ures_open(U_ICUDATA_CURR, locStr, &localStatus)); - LocalUResourceBundlePointer currency( - ures_getByKeyWithFallback(currencyResource.getAlias(), "Currencies", NULL, &localStatus)); - ures_getByKeyWithFallback(currency.getAlias(), cc, currency.getAlias(), &localStatus); - if(U_SUCCESS(localStatus) && ures_getSize(currency.getAlias())>2) { // the length is 3 if more data is present - ures_getByIndex(currency.getAlias(), 2, currency.getAlias(), &localStatus); - int32_t currPatternLen = 0; - currPattern = - ures_getStringByIndex(currency.getAlias(), (int32_t)0, &currPatternLen, &localStatus); - UnicodeString decimalSep = - ures_getUnicodeStringByIndex(currency.getAlias(), (int32_t)1, &localStatus); - UnicodeString groupingSep = - ures_getUnicodeStringByIndex(currency.getAlias(), (int32_t)2, &localStatus); - if(U_SUCCESS(localStatus)){ - fSymbols[kMonetaryGroupingSeparatorSymbol] = groupingSep; - fSymbols[kMonetarySeparatorSymbol] = decimalSep; - //pattern.setTo(TRUE, currPattern, currPatternLen); - status = localStatus; - } - } - /* else An explicit currency was requested and is unknown or locale data is malformed. */ - /* ucurr_* API will get the correct value later on. */ + setCurrency(curriso, status); + } else { + setCurrency(nullptr, status); } - // else ignore the error if no currency // Currency Spacing. LocalUResourceBundlePointer currencyResource(ures_open(U_ICUDATA_CURR, locStr, &status)); @@ -553,9 +512,54 @@ DecimalFormatSymbols::initialize() { fIsCustomIntlCurrencySymbol = FALSE; fCodePointZero = 0x30; U_ASSERT(fCodePointZero == fSymbols[kZeroDigitSymbol].char32At(0)); + currPattern = nullptr; } +void DecimalFormatSymbols::setCurrency(const UChar* currency, UErrorCode& status) { + // TODO: If this method is made public: + // - Adopt ICU4J behavior of not allowing currency to be null. + // - Also verify that the length of currency is 3. + if (!currency) { + return; + } + + UnicodeString tempStr; + uprv_getStaticCurrencyName(currency, locale.getName(), tempStr, status); + if (U_SUCCESS(status)) { + fSymbols[kIntlCurrencySymbol].setTo(currency, 3); + fSymbols[kCurrencySymbol] = tempStr; + } + + char cc[4]={0}; + u_UCharsToChars(currency, cc, 3); + + /* An explicit currency was requested */ + // TODO(ICU-13297): Move this data loading logic into a centralized place + UErrorCode localStatus = U_ZERO_ERROR; + LocalUResourceBundlePointer rbTop(ures_open(U_ICUDATA_CURR, locale.getName(), &localStatus)); + LocalUResourceBundlePointer rb( + ures_getByKeyWithFallback(rbTop.getAlias(), "Currencies", NULL, &localStatus)); + ures_getByKeyWithFallback(rb.getAlias(), cc, rb.getAlias(), &localStatus); + if(U_SUCCESS(localStatus) && ures_getSize(rb.getAlias())>2) { // the length is 3 if more data is present + ures_getByIndex(rb.getAlias(), 2, rb.getAlias(), &localStatus); + int32_t currPatternLen = 0; + currPattern = + ures_getStringByIndex(rb.getAlias(), (int32_t)0, &currPatternLen, &localStatus); + UnicodeString decimalSep = + ures_getUnicodeStringByIndex(rb.getAlias(), (int32_t)1, &localStatus); + UnicodeString groupingSep = + ures_getUnicodeStringByIndex(rb.getAlias(), (int32_t)2, &localStatus); + if(U_SUCCESS(localStatus)){ + fSymbols[kMonetaryGroupingSeparatorSymbol] = groupingSep; + fSymbols[kMonetarySeparatorSymbol] = decimalSep; + //pattern.setTo(TRUE, currPattern, currPatternLen); + } + } + /* else An explicit currency was requested and is unknown or locale data is malformed. */ + /* ucurr_* API will get the correct value later on. */ +} + Locale DecimalFormatSymbols::getLocale(ULocDataLocaleType type, UErrorCode& status) const { U_LOCALE_BASED(locBased, *this); diff --git a/deps/icu-small/source/i18n/decimfmt.cpp b/deps/icu-small/source/i18n/decimfmt.cpp index 6a69c9d7a300e6..275fe888a1b498 100644 --- a/deps/icu-small/source/i18n/decimfmt.cpp +++ b/deps/icu-small/source/i18n/decimfmt.cpp @@ -519,7 +519,9 @@ UnicodeString& DecimalFormat::format(double number, UnicodeString& appendTo, Fie return appendTo; } UErrorCode localStatus = U_ZERO_ERROR; - FormattedNumber output = fields->formatter.formatDouble(number, localStatus); + UFormattedNumberData output; + output.quantity.setToDouble(number); + fields->formatter.formatImpl(&output, localStatus); fieldPositionHelper(output, pos, appendTo.length(), localStatus); auto appendable = UnicodeStringAppendable(appendTo); output.appendTo(appendable, localStatus); @@ -540,7 +542,9 @@ UnicodeString& DecimalFormat::format(double number, UnicodeString& appendTo, Fie if (pos.getField() == FieldPosition::DONT_CARE && fastFormatDouble(number, appendTo)) { return appendTo; } - FormattedNumber output = fields->formatter.formatDouble(number, status); + UFormattedNumberData output; + output.quantity.setToDouble(number); + fields->formatter.formatImpl(&output, status); fieldPositionHelper(output, pos, appendTo.length(), status); auto appendable = UnicodeStringAppendable(appendTo); output.appendTo(appendable, status); @@ -562,7 +566,9 @@ DecimalFormat::format(double number, UnicodeString& appendTo, FieldPositionItera if (posIter == nullptr && fastFormatDouble(number, appendTo)) { return appendTo; } - FormattedNumber output = fields->formatter.formatDouble(number, status); + UFormattedNumberData output; + output.quantity.setToDouble(number); + fields->formatter.formatImpl(&output, status); fieldPositionIteratorHelper(output, posIter, appendTo.length(), status); auto appendable = UnicodeStringAppendable(appendTo); output.appendTo(appendable, status); @@ -593,7 +599,9 @@ UnicodeString& DecimalFormat::format(int64_t number, UnicodeString& appendTo, Fi return appendTo; } UErrorCode localStatus = U_ZERO_ERROR; - FormattedNumber output = fields->formatter.formatInt(number, localStatus); + UFormattedNumberData output; + output.quantity.setToLong(number); + fields->formatter.formatImpl(&output, localStatus); fieldPositionHelper(output, pos, appendTo.length(), localStatus); auto appendable = UnicodeStringAppendable(appendTo); output.appendTo(appendable, localStatus); @@ -614,7 +622,9 @@ UnicodeString& DecimalFormat::format(int64_t number, UnicodeString& appendTo, Fi if (pos.getField() == FieldPosition::DONT_CARE && fastFormatInt64(number, appendTo)) { return appendTo; } - FormattedNumber output = fields->formatter.formatInt(number, status); + UFormattedNumberData output; + output.quantity.setToLong(number); + fields->formatter.formatImpl(&output, status); fieldPositionHelper(output, pos, appendTo.length(), status); auto appendable = UnicodeStringAppendable(appendTo); output.appendTo(appendable, status); @@ -636,7 +646,9 @@ DecimalFormat::format(int64_t number, UnicodeString& appendTo, FieldPositionIter if (posIter == nullptr && fastFormatInt64(number, appendTo)) { return appendTo; } - FormattedNumber output = fields->formatter.formatInt(number, status); + UFormattedNumberData output; + output.quantity.setToLong(number); + fields->formatter.formatImpl(&output, status); fieldPositionIteratorHelper(output, posIter, appendTo.length(), status); auto appendable = UnicodeStringAppendable(appendTo); output.appendTo(appendable, status); @@ -655,7 +667,9 @@ DecimalFormat::format(StringPiece number, UnicodeString& appendTo, FieldPosition appendTo.setToBogus(); return appendTo; } - FormattedNumber output = fields->formatter.formatDecimal(number, status); + UFormattedNumberData output; + output.quantity.setToDecNumber(number, status); + fields->formatter.formatImpl(&output, status); fieldPositionIteratorHelper(output, posIter, appendTo.length(), status); auto appendable = UnicodeStringAppendable(appendTo); output.appendTo(appendable, status); @@ -673,7 +687,9 @@ UnicodeString& DecimalFormat::format(const DecimalQuantity& number, UnicodeStrin appendTo.setToBogus(); return appendTo; } - FormattedNumber output = fields->formatter.formatDecimalQuantity(number, status); + UFormattedNumberData output; + output.quantity = number; + fields->formatter.formatImpl(&output, status); fieldPositionIteratorHelper(output, posIter, appendTo.length(), status); auto appendable = UnicodeStringAppendable(appendTo); output.appendTo(appendable, status); @@ -692,7 +708,9 @@ DecimalFormat::format(const DecimalQuantity& number, UnicodeString& appendTo, Fi appendTo.setToBogus(); return appendTo; } - FormattedNumber output = fields->formatter.formatDecimalQuantity(number, status); + UFormattedNumberData output; + output.quantity = number; + fields->formatter.formatImpl(&output, status); fieldPositionHelper(output, pos, appendTo.length(), status); auto appendable = UnicodeStringAppendable(appendTo); output.appendTo(appendable, status); @@ -1502,8 +1520,11 @@ void DecimalFormat::setCurrency(const char16_t* theCurrency, UErrorCode& ec) { } NumberFormat::setCurrency(theCurrency, ec); // to set field for compatibility fields->properties.currency = currencyUnit; - // TODO: Set values in fields->symbols, too? - touchNoError(); + // In Java, the DecimalFormatSymbols is mutable. Why not in C++? + LocalPointer newSymbols(new DecimalFormatSymbols(*fields->symbols), ec); + newSymbols->setCurrency(currencyUnit.getISOCurrency(), ec); + fields->symbols.adoptInsteadAndCheckErrorCode(newSymbols.orphan(), ec); + touch(ec); } void DecimalFormat::setCurrency(const char16_t* theCurrency) { @@ -1700,8 +1721,11 @@ const numparse::impl::NumberParserImpl* DecimalFormat::getCurrencyParser(UErrorC } void -DecimalFormat::fieldPositionHelper(const number::FormattedNumber& formatted, FieldPosition& fieldPosition, - int32_t offset, UErrorCode& status) { +DecimalFormat::fieldPositionHelper( + const UFormattedNumberData& formatted, + FieldPosition& fieldPosition, + int32_t offset, + UErrorCode& status) { if (U_FAILURE(status)) { return; } // always return first occurrence: fieldPosition.setBeginIndex(0); @@ -1714,12 +1738,15 @@ DecimalFormat::fieldPositionHelper(const number::FormattedNumber& formatted, Fie } void -DecimalFormat::fieldPositionIteratorHelper(const number::FormattedNumber& formatted, FieldPositionIterator* fpi, - int32_t offset, UErrorCode& status) { +DecimalFormat::fieldPositionIteratorHelper( + const UFormattedNumberData& formatted, + FieldPositionIterator* fpi, + int32_t offset, + UErrorCode& status) { if (U_SUCCESS(status) && (fpi != nullptr)) { FieldPositionIteratorHandler fpih(fpi, status); fpih.setShift(offset); - formatted.getAllFieldPositionsImpl(fpih, status); + formatted.getAllFieldPositions(fpih, status); } } @@ -1801,7 +1828,7 @@ bool DecimalFormat::fastFormatDouble(double input, UnicodeString& output) const return false; } if (std::isnan(input) - || std::trunc(input) != input + || uprv_trunc(input) != input || input <= INT32_MIN || input > INT32_MAX) { return false; @@ -1834,7 +1861,8 @@ void DecimalFormat::doFastFormatInt32(int32_t input, bool isNegative, UnicodeStr char16_t localBuffer[localCapacity]; char16_t* ptr = localBuffer + localCapacity; int8_t group = 0; - for (int8_t i = 0; i < fields->fastData.maxInt && (input != 0 || i < fields->fastData.minInt); i++) { + int8_t minInt = (fields->fastData.minInt < 1)? 1: fields->fastData.minInt; + for (int8_t i = 0; i < fields->fastData.maxInt && (input != 0 || i < minInt); i++) { if (group++ == 3 && fields->fastData.cpGroupingSeparator != 0) { *(--ptr) = fields->fastData.cpGroupingSeparator; group = 1; diff --git a/deps/icu-small/source/i18n/double-conversion-ieee.h b/deps/icu-small/source/i18n/double-conversion-ieee.h index f4c62a9a9f8d99..31c35867de5610 100644 --- a/deps/icu-small/source/i18n/double-conversion-ieee.h +++ b/deps/icu-small/source/i18n/double-conversion-ieee.h @@ -59,6 +59,7 @@ class Double { static const uint64_t kExponentMask = DOUBLE_CONVERSION_UINT64_2PART_C(0x7FF00000, 00000000); static const uint64_t kSignificandMask = DOUBLE_CONVERSION_UINT64_2PART_C(0x000FFFFF, FFFFFFFF); static const uint64_t kHiddenBit = DOUBLE_CONVERSION_UINT64_2PART_C(0x00100000, 00000000); + static const uint64_t kQuietNanBit = DOUBLE_CONVERSION_UINT64_2PART_C(0x00080000, 00000000); static const int kPhysicalSignificandSize = 52; // Excludes the hidden bit. static const int kSignificandSize = 53; static const int kExponentBias = 0x3FF + kPhysicalSignificandSize; @@ -162,6 +163,15 @@ class Double { ((d64 & kSignificandMask) != 0); } + bool IsQuietNan() const { + return IsNan() && ((AsUint64() & kQuietNanBit) != 0); + } + + bool IsSignalingNan() const { + return IsNan() && ((AsUint64() & kQuietNanBit) == 0); + } + + bool IsInfinite() const { uint64_t d64 = AsUint64(); return ((d64 & kExponentMask) == kExponentMask) && @@ -280,6 +290,7 @@ class Single { static const uint32_t kExponentMask = 0x7F800000; static const uint32_t kSignificandMask = 0x007FFFFF; static const uint32_t kHiddenBit = 0x00800000; + static const uint32_t kQuietNanBit = 0x00400000; static const int kPhysicalSignificandSize = 23; // Excludes the hidden bit. static const int kSignificandSize = 24; @@ -338,6 +349,15 @@ class Single { ((d32 & kSignificandMask) != 0); } + bool IsQuietNan() const { + return IsNan() && ((AsUint32() & kQuietNanBit) != 0); + } + + bool IsSignalingNan() const { + return IsNan() && ((AsUint32() & kQuietNanBit) == 0); + } + + bool IsInfinite() const { uint32_t d32 = AsUint32(); return ((d32 & kExponentMask) == kExponentMask) && diff --git a/deps/icu-small/source/i18n/double-conversion-string-to-double.cpp b/deps/icu-small/source/i18n/double-conversion-string-to-double.cpp index 946b2b26e77aa4..548cad1f302241 100644 --- a/deps/icu-small/source/i18n/double-conversion-string-to-double.cpp +++ b/deps/icu-small/source/i18n/double-conversion-string-to-double.cpp @@ -462,11 +462,6 @@ double StringToDoubleConverter::StringToIeee( } } - // The longest form of simplified number is: "-.1eXXX\0". - const int kBufferSize = kMaxSignificantDigits + 10; - char buffer[kBufferSize]; // NOLINT: size is known at compile time. - int buffer_pos = 0; - // Exponent will be adjusted if insignificant digits of the integer part // or insignificant leading zeros of the fractional part are dropped. int exponent = 0; @@ -501,7 +496,6 @@ double StringToDoubleConverter::StringToIeee( return junk_string_value_; } - DOUBLE_CONVERSION_ASSERT(buffer_pos == 0); *processed_characters_count = static_cast(current - input); return sign ? -Double::Infinity() : Double::Infinity(); } @@ -520,7 +514,6 @@ double StringToDoubleConverter::StringToIeee( return junk_string_value_; } - DOUBLE_CONVERSION_ASSERT(buffer_pos == 0); *processed_characters_count = static_cast(current - input); return sign ? -Double::NaN() : Double::NaN(); } @@ -577,6 +570,12 @@ double StringToDoubleConverter::StringToIeee( bool octal = leading_zero && (flags_ & ALLOW_OCTALS) != 0; + // The longest form of simplified number is: "-.1eXXX\0". + const int kBufferSize = kMaxSignificantDigits + 10; + DOUBLE_CONVERSION_STACK_UNINITIALIZED char + buffer[kBufferSize]; // NOLINT: size is known at compile time. + int buffer_pos = 0; + // Copy significant digits of the integer part (if any) to the buffer. while (*current >= '0' && *current <= '9') { if (significant_digits < kMaxSignificantDigits) { diff --git a/deps/icu-small/source/i18n/double-conversion-strtod.cpp b/deps/icu-small/source/i18n/double-conversion-strtod.cpp index 9cf4854426756c..ee6377782bb82f 100644 --- a/deps/icu-small/source/i18n/double-conversion-strtod.cpp +++ b/deps/icu-small/source/i18n/double-conversion-strtod.cpp @@ -49,10 +49,12 @@ U_NAMESPACE_BEGIN namespace double_conversion { +#if defined(DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS) // 2^53 = 9007199254740992. // Any integer with at most 15 decimal digits will hence fit into a double // (which has a 53bit significand) without loss of precision. static const int kMaxExactDoubleIntegerDecimalDigits = 15; +#endif // #if defined(DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS) // 2^64 = 18446744073709551616 > 10^19 static const int kMaxUint64DecimalDigits = 19; @@ -69,6 +71,7 @@ static const int kMinDecimalPower = -324; static const uint64_t kMaxUint64 = DOUBLE_CONVERSION_UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF); +#if defined(DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS) static const double exact_powers_of_ten[] = { 1.0, // 10^0 10.0, @@ -96,6 +99,7 @@ static const double exact_powers_of_ten[] = { 10000000000000000000000.0 }; static const int kExactPowersOfTenSize = DOUBLE_CONVERSION_ARRAY_SIZE(exact_powers_of_ten); +#endif // #if defined(DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS) // Maximum number of significant digits in the decimal representation. // In fact the value is 772 (see conversions.cc), but to give us some margin diff --git a/deps/icu-small/source/i18n/double-conversion-utils.h b/deps/icu-small/source/i18n/double-conversion-utils.h index 099298460c63d9..8c6a0e16e005fe 100644 --- a/deps/icu-small/source/i18n/double-conversion-utils.h +++ b/deps/icu-small/source/i18n/double-conversion-utils.h @@ -66,14 +66,28 @@ inline void abort_noreturn() { abort(); } #endif #endif +// Not all compilers support __has_attribute and combining a check for both +// ifdef and __has_attribute on the same preprocessor line isn't portable. +#ifdef __has_attribute +# define DOUBLE_CONVERSION_HAS_ATTRIBUTE(x) __has_attribute(x) +#else +# define DOUBLE_CONVERSION_HAS_ATTRIBUTE(x) 0 +#endif + #ifndef DOUBLE_CONVERSION_UNUSED -#ifdef __GNUC__ +#if DOUBLE_CONVERSION_HAS_ATTRIBUTE(unused) #define DOUBLE_CONVERSION_UNUSED __attribute__((unused)) #else #define DOUBLE_CONVERSION_UNUSED #endif #endif +#if DOUBLE_CONVERSION_HAS_ATTRIBUTE(uninitialized) +#define DOUBLE_CONVERSION_STACK_UNINITIALIZED __attribute__((uninitialized)) +#else +#define DOUBLE_CONVERSION_STACK_UNINITIALIZED +#endif + // Double operations detection based on target architecture. // Linux uses a 80bit wide floating point stack on x86. This induces double // rounding, which in turn leads to wrong results. @@ -104,6 +118,7 @@ int main(int argc, char** argv) { defined(__ARMEL__) || defined(__avr32__) || defined(_M_ARM) || defined(_M_ARM64) || \ defined(__hppa__) || defined(__ia64__) || \ defined(__mips__) || \ + defined(__nios2__) || \ defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || \ defined(_POWER) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \ defined(__sparc__) || defined(__sparc) || defined(__s390__) || \ @@ -112,7 +127,8 @@ int main(int argc, char** argv) { defined(__AARCH64EL__) || defined(__aarch64__) || defined(__AARCH64EB__) || \ defined(__riscv) || defined(__e2k__) || \ defined(__or1k__) || defined(__arc__) || \ - defined(__EMSCRIPTEN__) + defined(__microblaze__) || defined(__XTENSA__) || \ + defined(__EMSCRIPTEN__) || defined(__wasm32__) #define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1 #elif defined(__mc68000__) || \ defined(__pnacl__) || defined(__native_client__) diff --git a/deps/icu-small/source/i18n/dtitvfmt.cpp b/deps/icu-small/source/i18n/dtitvfmt.cpp index f47e7708ccc128..b71a571d1c490a 100644 --- a/deps/icu-small/source/i18n/dtitvfmt.cpp +++ b/deps/icu-small/source/i18n/dtitvfmt.cpp @@ -108,6 +108,10 @@ DateIntervalFormat::createInstance(const UnicodeString& skeleton, #endif DateIntervalInfo* dtitvinf = new DateIntervalInfo(locale, status); + if (dtitvinf == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return nullptr; + } return create(locale, dtitvinf, &skeleton, status); } @@ -132,27 +136,27 @@ DateIntervalFormat::createInstance(const UnicodeString& skeleton, DateIntervalFormat::DateIntervalFormat() -: fInfo(NULL), - fDateFormat(NULL), - fFromCalendar(NULL), - fToCalendar(NULL), +: fInfo(nullptr), + fDateFormat(nullptr), + fFromCalendar(nullptr), + fToCalendar(nullptr), fLocale(Locale::getRoot()), - fDatePattern(NULL), - fTimePattern(NULL), - fDateTimeFormat(NULL) + fDatePattern(nullptr), + fTimePattern(nullptr), + fDateTimeFormat(nullptr) {} DateIntervalFormat::DateIntervalFormat(const DateIntervalFormat& itvfmt) : Format(itvfmt), - fInfo(NULL), - fDateFormat(NULL), - fFromCalendar(NULL), - fToCalendar(NULL), + fInfo(nullptr), + fDateFormat(nullptr), + fFromCalendar(nullptr), + fToCalendar(nullptr), fLocale(itvfmt.fLocale), - fDatePattern(NULL), - fTimePattern(NULL), - fDateTimeFormat(NULL) { + fDatePattern(nullptr), + fTimePattern(nullptr), + fDateTimeFormat(nullptr) { *this = itvfmt; } @@ -172,23 +176,23 @@ DateIntervalFormat::operator=(const DateIntervalFormat& itvfmt) { if ( itvfmt.fDateFormat ) { fDateFormat = itvfmt.fDateFormat->clone(); } else { - fDateFormat = NULL; + fDateFormat = nullptr; } if ( itvfmt.fFromCalendar ) { fFromCalendar = itvfmt.fFromCalendar->clone(); } else { - fFromCalendar = NULL; + fFromCalendar = nullptr; } if ( itvfmt.fToCalendar ) { fToCalendar = itvfmt.fToCalendar->clone(); } else { - fToCalendar = NULL; + fToCalendar = nullptr; } } if ( itvfmt.fInfo ) { fInfo = itvfmt.fInfo->clone(); } else { - fInfo = NULL; + fInfo = nullptr; } fSkeleton = itvfmt.fSkeleton; int8_t i; @@ -196,9 +200,9 @@ DateIntervalFormat::operator=(const DateIntervalFormat& itvfmt) { fIntervalPatterns[i] = itvfmt.fIntervalPatterns[i]; } fLocale = itvfmt.fLocale; - fDatePattern = (itvfmt.fDatePattern)? itvfmt.fDatePattern->clone(): NULL; - fTimePattern = (itvfmt.fTimePattern)? itvfmt.fTimePattern->clone(): NULL; - fDateTimeFormat = (itvfmt.fDateTimeFormat)? itvfmt.fDateTimeFormat->clone(): NULL; + fDatePattern = (itvfmt.fDatePattern)? itvfmt.fDatePattern->clone(): nullptr; + fTimePattern = (itvfmt.fTimePattern)? itvfmt.fTimePattern->clone(): nullptr; + fDateTimeFormat = (itvfmt.fDateTimeFormat)? itvfmt.fDateTimeFormat->clone(): nullptr; } return *this; } @@ -227,21 +231,21 @@ DateIntervalFormat::operator==(const Format& other) const { const DateIntervalFormat* fmt = (DateIntervalFormat*)&other; if (this == fmt) {return TRUE;} if (!Format::operator==(other)) {return FALSE;} - if ((fInfo != fmt->fInfo) && (fInfo == NULL || fmt->fInfo == NULL)) {return FALSE;} + if ((fInfo != fmt->fInfo) && (fInfo == nullptr || fmt->fInfo == nullptr)) {return FALSE;} if (fInfo && fmt->fInfo && (*fInfo != *fmt->fInfo )) {return FALSE;} { Mutex lock(&gFormatterMutex); - if (fDateFormat != fmt->fDateFormat && (fDateFormat == NULL || fmt->fDateFormat == NULL)) {return FALSE;} + if (fDateFormat != fmt->fDateFormat && (fDateFormat == nullptr || fmt->fDateFormat == nullptr)) {return FALSE;} if (fDateFormat && fmt->fDateFormat && (*fDateFormat != *fmt->fDateFormat)) {return FALSE;} } // note: fFromCalendar and fToCalendar hold no persistent state, and therefore do not participate in operator ==. // fDateFormat has the master calendar for the DateIntervalFormat. if (fSkeleton != fmt->fSkeleton) {return FALSE;} - if (fDatePattern != fmt->fDatePattern && (fDatePattern == NULL || fmt->fDatePattern == NULL)) {return FALSE;} + if (fDatePattern != fmt->fDatePattern && (fDatePattern == nullptr || fmt->fDatePattern == nullptr)) {return FALSE;} if (fDatePattern && fmt->fDatePattern && (*fDatePattern != *fmt->fDatePattern)) {return FALSE;} - if (fTimePattern != fmt->fTimePattern && (fTimePattern == NULL || fmt->fTimePattern == NULL)) {return FALSE;} + if (fTimePattern != fmt->fTimePattern && (fTimePattern == nullptr || fmt->fTimePattern == nullptr)) {return FALSE;} if (fTimePattern && fmt->fTimePattern && (*fTimePattern != *fmt->fTimePattern)) {return FALSE;} - if (fDateTimeFormat != fmt->fDateTimeFormat && (fDateTimeFormat == NULL || fmt->fDateTimeFormat == NULL)) {return FALSE;} + if (fDateTimeFormat != fmt->fDateTimeFormat && (fDateTimeFormat == nullptr || fmt->fDateTimeFormat == nullptr)) {return FALSE;} if (fDateTimeFormat && fmt->fDateTimeFormat && (*fDateTimeFormat != *fmt->fDateTimeFormat)) {return FALSE;} if (fLocale != fmt->fLocale) {return FALSE;} @@ -266,7 +270,7 @@ DateIntervalFormat::format(const Formattable& obj, if ( obj.getType() == Formattable::kObject ) { const UObject* formatObj = obj.getObject(); const DateInterval* interval = dynamic_cast(formatObj); - if (interval != NULL) { + if (interval != nullptr) { return format(interval, appendTo, fieldPosition, status); } } @@ -283,7 +287,7 @@ DateIntervalFormat::format(const DateInterval* dtInterval, if ( U_FAILURE(status) ) { return appendTo; } - if (fDateFormat == NULL || fInfo == NULL) { + if (fDateFormat == nullptr || fInfo == nullptr) { status = U_INVALID_STATE_ERROR; return appendTo; } @@ -300,6 +304,10 @@ DateIntervalFormat::format(const DateInterval* dtInterval, FormattedDateInterval DateIntervalFormat::formatToValue( const DateInterval& dtInterval, UErrorCode& status) const { + if (U_FAILURE(status)) { + return FormattedDateInterval(status); + } + // LocalPointer only sets OOM status if U_SUCCESS is true. LocalPointer result(new FormattedDateIntervalData(status), status); if (U_FAILURE(status)) { return FormattedDateInterval(status); @@ -350,6 +358,10 @@ FormattedDateInterval DateIntervalFormat::formatToValue( Calendar& fromCalendar, Calendar& toCalendar, UErrorCode& status) const { + if (U_FAILURE(status)) { + return FormattedDateInterval(status); + } + // LocalPointer only sets OOM status if U_SUCCESS is true. LocalPointer result(new FormattedDateIntervalData(status), status); if (U_FAILURE(status)) { return FormattedDateInterval(status); @@ -444,6 +456,9 @@ DateIntervalFormat::formatImpl(Calendar& fromCalendar, } else if ( fromCalendar.get(UCAL_SECOND, status) != toCalendar.get(UCAL_SECOND, status) ) { field = UCAL_SECOND; + } else if ( fromCalendar.get(UCAL_MILLISECOND, status) != + toCalendar.get(UCAL_MILLISECOND, status) ) { + field = UCAL_MILLISECOND; } if ( U_FAILURE(status) ) { @@ -455,7 +470,7 @@ DateIntervalFormat::formatImpl(Calendar& fromCalendar, */ return fDateFormat->_format(fromCalendar, appendTo, fphandler, status); } - UBool fromToOnSameDay = (field==UCAL_AM_PM || field==UCAL_HOUR || field==UCAL_MINUTE || field==UCAL_SECOND); + UBool fromToOnSameDay = (field==UCAL_AM_PM || field==UCAL_HOUR || field==UCAL_MINUTE || field==UCAL_SECOND || field==UCAL_MILLISECOND); // following call should not set wrong status, // all the pass-in fields are valid till here @@ -537,14 +552,17 @@ DateIntervalFormat::setDateIntervalInfo(const DateIntervalInfo& newItvPattern, UErrorCode& status) { delete fInfo; fInfo = new DateIntervalInfo(newItvPattern); + if (fInfo == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + } // Delete patterns that get reset by initializePattern delete fDatePattern; - fDatePattern = NULL; + fDatePattern = nullptr; delete fTimePattern; - fTimePattern = NULL; + fTimePattern = nullptr; delete fDateTimeFormat; - fDateTimeFormat = NULL; + fDateTimeFormat = nullptr; if (fDateFormat) { initializePattern(status); @@ -562,7 +580,7 @@ DateIntervalFormat::getDateFormat() const { void DateIntervalFormat::adoptTimeZone(TimeZone* zone) { - if (fDateFormat != NULL) { + if (fDateFormat != nullptr) { fDateFormat->adoptTimeZone(zone); } // The fDateFormat has the master calendar for the DateIntervalFormat and has @@ -580,7 +598,7 @@ DateIntervalFormat::adoptTimeZone(TimeZone* zone) void DateIntervalFormat::setTimeZone(const TimeZone& zone) { - if (fDateFormat != NULL) { + if (fDateFormat != nullptr) { fDateFormat->setTimeZone(zone); } // The fDateFormat has the master calendar for the DateIntervalFormat; @@ -596,11 +614,11 @@ DateIntervalFormat::setTimeZone(const TimeZone& zone) const TimeZone& DateIntervalFormat::getTimeZone() const { - if (fDateFormat != NULL) { + if (fDateFormat != nullptr) { Mutex lock(&gFormatterMutex); return fDateFormat->getTimeZone(); } - // If fDateFormat is NULL (unexpected), create default timezone. + // If fDateFormat is nullptr (unexpected), create default timezone. return *(TimeZone::createDefault()); } @@ -608,14 +626,14 @@ DateIntervalFormat::DateIntervalFormat(const Locale& locale, DateIntervalInfo* dtItvInfo, const UnicodeString* skeleton, UErrorCode& status) -: fInfo(NULL), - fDateFormat(NULL), - fFromCalendar(NULL), - fToCalendar(NULL), +: fInfo(nullptr), + fDateFormat(nullptr), + fFromCalendar(nullptr), + fToCalendar(nullptr), fLocale(locale), - fDatePattern(NULL), - fTimePattern(NULL), - fDateTimeFormat(NULL) + fDatePattern(nullptr), + fTimePattern(nullptr), + fDateTimeFormat(nullptr) { LocalPointer info(dtItvInfo, status); LocalPointer dtfmt(static_cast( @@ -643,7 +661,7 @@ DateIntervalFormat::create(const Locale& locale, UErrorCode& status) { DateIntervalFormat* f = new DateIntervalFormat(locale, dtitvinf, skeleton, status); - if ( f == NULL ) { + if ( f == nullptr ) { status = U_MEMORY_ALLOCATION_ERROR; delete dtitvinf; } else if ( U_FAILURE(status) ) { @@ -760,7 +778,7 @@ DateIntervalFormat::initializePattern(UErrorCode& status) { // with the time interval. // The date/time pattern ( such as {0} {1} ) is saved in // calendar, that is why need to get the CalendarData here. - LocalUResourceBundlePointer dateTimePatternsRes(ures_open(NULL, locale.getBaseName(), &status)); + LocalUResourceBundlePointer dateTimePatternsRes(ures_open(nullptr, locale.getBaseName(), &status)); ures_getByKey(dateTimePatternsRes.getAlias(), gCalendarTag, dateTimePatternsRes.getAlias(), &status); ures_getByKeyWithFallback(dateTimePatternsRes.getAlias(), gGregorianTag, @@ -775,6 +793,10 @@ DateIntervalFormat::initializePattern(UErrorCode& status) { &dateTimeFormatLength, &status); if ( U_SUCCESS(status) && dateTimeFormatLength >= 3 ) { fDateTimeFormat = new UnicodeString(dateTimeFormat, dateTimeFormatLength); + if (fDateTimeFormat == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } } } @@ -798,9 +820,9 @@ DateIntervalFormat::initializePattern(UErrorCode& status) { // the first part of the pattern is empty, // the second part of the pattern is the full-pattern // should be used in fall-back. - setPatternInfo(UCAL_DATE, NULL, &pattern, fInfo->getDefaultOrder()); - setPatternInfo(UCAL_MONTH, NULL, &pattern, fInfo->getDefaultOrder()); - setPatternInfo(UCAL_YEAR, NULL, &pattern, fInfo->getDefaultOrder()); + setPatternInfo(UCAL_DATE, nullptr, &pattern, fInfo->getDefaultOrder()); + setPatternInfo(UCAL_MONTH, nullptr, &pattern, fInfo->getDefaultOrder()); + setPatternInfo(UCAL_YEAR, nullptr, &pattern, fInfo->getDefaultOrder()); } else { // TODO: fall back } @@ -824,9 +846,9 @@ DateIntervalFormat::initializePattern(UErrorCode& status) { // the first part of the pattern is empty, // the second part of the pattern is the full-pattern // should be used in fall-back. - setPatternInfo(UCAL_DATE, NULL, &pattern, fInfo->getDefaultOrder()); - setPatternInfo(UCAL_MONTH, NULL, &pattern, fInfo->getDefaultOrder()); - setPatternInfo(UCAL_YEAR, NULL, &pattern, fInfo->getDefaultOrder()); + setPatternInfo(UCAL_DATE, nullptr, &pattern, fInfo->getDefaultOrder()); + setPatternInfo(UCAL_MONTH, nullptr, &pattern, fInfo->getDefaultOrder()); + setPatternInfo(UCAL_YEAR, nullptr, &pattern, fInfo->getDefaultOrder()); } else { /* if both present, * 1) when the year, month, or day differs, @@ -861,7 +883,7 @@ DateIntervalFormat::initializePattern(UErrorCode& status) { * range expression for the time. */ - if ( fDateTimeFormat == NULL ) { + if ( fDateTimeFormat == nullptr ) { // earlier failure getting dateTimeFormat return; } @@ -1071,16 +1093,16 @@ DateIntervalFormat::setSeparateDateTimePtn( int8_t differenceInfo = 0; const UnicodeString* bestSkeleton = fInfo->getBestSkeleton(*skeleton, differenceInfo); - /* best skeleton could be NULL. + /* best skeleton could be nullptr. For example: in "ca" resource file, interval format is defined as following intervalFormats{ fallback{"{0} - {1}"} } there is no skeletons/interval patterns defined, - and the best skeleton match could be NULL + and the best skeleton match could be nullptr */ - if ( bestSkeleton == NULL ) { + if ( bestSkeleton == nullptr ) { return false; } @@ -1091,11 +1113,13 @@ DateIntervalFormat::setSeparateDateTimePtn( status = U_ZERO_ERROR; fDatePattern = new UnicodeString(DateFormat::getBestPattern( fLocale, dateSkeleton, status)); + // no way to report OOM. :( } if ( timeSkeleton.length() != 0) { status = U_ZERO_ERROR; fTimePattern = new UnicodeString(DateFormat::getBestPattern( fLocale, timeSkeleton, status)); + // no way to report OOM. :( } // difference: @@ -1151,7 +1175,7 @@ DateIntervalFormat::setFallbackPattern(UCalendarDateFields field, if ( U_FAILURE(status) ) { return; } - setPatternInfo(field, NULL, &pattern, fInfo->getDefaultOrder()); + setPatternInfo(field, nullptr, &pattern, fInfo->getDefaultOrder()); } diff --git a/deps/icu-small/source/i18n/dtitvinf.cpp b/deps/icu-small/source/i18n/dtitvinf.cpp index 0ee17e88e81808..25536346ec74f0 100644 --- a/deps/icu-small/source/i18n/dtitvinf.cpp +++ b/deps/icu-small/source/i18n/dtitvinf.cpp @@ -66,7 +66,7 @@ static const UChar gDefaultFallbackPattern[] = {LEFT_CURLY_BRACKET, DIGIT_ZERO, DateIntervalInfo::DateIntervalInfo(UErrorCode& status) : fFallbackIntervalPattern(gDefaultFallbackPattern), fFirstDateInPtnIsLaterDate(false), - fIntervalPatterns(NULL) + fIntervalPatterns(nullptr) { fIntervalPatterns = initHash(status); } @@ -76,7 +76,7 @@ DateIntervalInfo::DateIntervalInfo(UErrorCode& status) DateIntervalInfo::DateIntervalInfo(const Locale& locale, UErrorCode& status) : fFallbackIntervalPattern(gDefaultFallbackPattern), fFirstDateInPtnIsLaterDate(false), - fIntervalPatterns(NULL) + fIntervalPatterns(nullptr) { initializeData(locale, status); } @@ -126,7 +126,7 @@ DateIntervalInfo::setFallbackIntervalPattern( DateIntervalInfo::DateIntervalInfo(const DateIntervalInfo& dtitvinf) : UObject(dtitvinf), - fIntervalPatterns(NULL) + fIntervalPatterns(nullptr) { *this = dtitvinf; } @@ -161,7 +161,7 @@ DateIntervalInfo::clone() const { DateIntervalInfo::~DateIntervalInfo() { deleteHash(fIntervalPatterns); - fIntervalPatterns = NULL; + fIntervalPatterns = nullptr; } @@ -189,7 +189,7 @@ DateIntervalInfo::getIntervalPattern(const UnicodeString& skeleton, } const UnicodeString* patternsOfOneSkeleton = (UnicodeString*) fIntervalPatterns->get(skeleton); - if ( patternsOfOneSkeleton != NULL ) { + if ( patternsOfOneSkeleton != nullptr ) { IntervalPatternIndex index = calendarFieldToIntervalIndex(field, status); if ( U_FAILURE(status) ) { return result; @@ -363,7 +363,7 @@ struct DateIntervalInfo::DateIntervalSink : public ResourceSink { UnicodeString* patternsOfOneSkeleton = (UnicodeString*)(dateIntervalInfo.fIntervalPatterns->get(skeleton)); - if (patternsOfOneSkeleton == NULL || patternsOfOneSkeleton[index].isEmpty()) { + if (patternsOfOneSkeleton == nullptr || patternsOfOneSkeleton[index].isEmpty()) { UnicodeString pattern = value.getUnicodeString(errorCode); dateIntervalInfo.setIntervalPatternInternally(skeleton, lrgDiffCalUnit, pattern, errorCode); @@ -398,8 +398,8 @@ DateIntervalInfo::initializeData(const Locale& locale, UErrorCode& status) char calendarType[ULOC_KEYWORDS_CAPACITY]; // to be filled in with the type to use, if all goes well char localeWithCalendarKey[ULOC_LOCALE_IDENTIFIER_CAPACITY]; // obtain a locale that always has the calendar key value that should be used - (void)ures_getFunctionalEquivalent(localeWithCalendarKey, ULOC_LOCALE_IDENTIFIER_CAPACITY, NULL, - "calendar", "calendar", locName, NULL, FALSE, &status); + (void)ures_getFunctionalEquivalent(localeWithCalendarKey, ULOC_LOCALE_IDENTIFIER_CAPACITY, nullptr, + "calendar", "calendar", locName, nullptr, FALSE, &status); localeWithCalendarKey[ULOC_LOCALE_IDENTIFIER_CAPACITY-1] = 0; // ensure null termination // now get the calendar key value from that locale int32_t calendarTypeLen = uloc_getKeywordValue(localeWithCalendarKey, "calendar", calendarType, @@ -411,11 +411,11 @@ DateIntervalInfo::initializeData(const Locale& locale, UErrorCode& status) // Instantiate the resource bundles UResourceBundle *rb, *calBundle; - rb = ures_open(NULL, locName, &status); + rb = ures_open(nullptr, locName, &status); if (U_FAILURE(status)) { return; } - calBundle = ures_getByKeyWithFallback(rb, gCalendarTag, NULL, &status); + calBundle = ures_getByKeyWithFallback(rb, gCalendarTag, nullptr, &status); if (U_SUCCESS(status)) { @@ -424,9 +424,9 @@ DateIntervalInfo::initializeData(const Locale& locale, UErrorCode& status) // Get the fallback pattern const UChar* resStr = nullptr; int32_t resStrLen = 0; - calTypeBundle = ures_getByKeyWithFallback(calBundle, calendarTypeToUse, NULL, &status); + calTypeBundle = ures_getByKeyWithFallback(calBundle, calendarTypeToUse, nullptr, &status); itvDtPtnResource = ures_getByKeyWithFallback(calTypeBundle, - gIntervalDateTimePatternTag, NULL, &status); + gIntervalDateTimePatternTag, nullptr, &status); // TODO(ICU-20400): After the fixing, we should find the "fallback" from // the rb directly by the path "calendar/${calendar}/intervalFormats/fallback". if ( U_SUCCESS(status) ) { @@ -437,10 +437,10 @@ DateIntervalInfo::initializeData(const Locale& locale, UErrorCode& status) // ures_getByKeyWithFallback UErrorCode localStatus = U_ZERO_ERROR; UResourceBundle *genericCalBundle = - ures_getByKeyWithFallback(calBundle, gGenericTag, NULL, &localStatus); + ures_getByKeyWithFallback(calBundle, gGenericTag, nullptr, &localStatus); UResourceBundle *genericItvDtPtnResource = ures_getByKeyWithFallback( - genericCalBundle, gIntervalDateTimePatternTag, NULL, &localStatus); + genericCalBundle, gIntervalDateTimePatternTag, nullptr, &localStatus); resStr = ures_getStringByKeyWithFallback( genericItvDtPtnResource, gFallbackPatternTag, &resStrLen, &localStatus); ures_close(genericItvDtPtnResource); @@ -509,8 +509,12 @@ DateIntervalInfo::setIntervalPatternInternally(const UnicodeString& skeleton, } UnicodeString* patternsOfOneSkeleton = (UnicodeString*)(fIntervalPatterns->get(skeleton)); UBool emptyHash = false; - if ( patternsOfOneSkeleton == NULL ) { + if ( patternsOfOneSkeleton == nullptr ) { patternsOfOneSkeleton = new UnicodeString[kIPI_MAX_INDEX]; + if (patternsOfOneSkeleton == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } emptyHash = true; } @@ -608,7 +612,7 @@ DateIntervalInfo::getBestSkeleton(const UnicodeString& skeleton, parseSkeleton(*inputSkeleton, inputSkeletonFieldWidth); int32_t bestDistance = MAX_POSITIVE_INT; - const UnicodeString* bestSkeleton = NULL; + const UnicodeString* bestSkeleton = nullptr; // 0 means exact the same skeletons; // 1 means having the same field, but with different length, @@ -618,8 +622,8 @@ DateIntervalInfo::getBestSkeleton(const UnicodeString& skeleton, int8_t fieldLength = UPRV_LENGTHOF(skeletonFieldWidth); int32_t pos = UHASH_FIRST; - const UHashElement* elem = NULL; - while ( (elem = fIntervalPatterns->nextElement(pos)) != NULL ) { + const UHashElement* elem = nullptr; + while ( (elem = fIntervalPatterns->nextElement(pos)) != nullptr ) { const UHashTok keyTok = elem->key; UnicodeString* newSkeleton = (UnicodeString*)keyTok.pointer; #ifdef DTITVINF_DEBUG @@ -711,6 +715,9 @@ DateIntervalInfo::calendarFieldToIntervalIndex(UCalendarDateFields field, case UCAL_SECOND: index = kIPI_SECOND; break; + case UCAL_MILLISECOND: + index = kIPI_MILLISECOND; + break; default: status = U_ILLEGAL_ARGUMENT_ERROR; } @@ -722,12 +729,12 @@ DateIntervalInfo::calendarFieldToIntervalIndex(UCalendarDateFields field, void DateIntervalInfo::deleteHash(Hashtable* hTable) { - if ( hTable == NULL ) { + if ( hTable == nullptr ) { return; } int32_t pos = UHASH_FIRST; - const UHashElement* element = NULL; - while ( (element = hTable->nextElement(pos)) != NULL ) { + const UHashElement* element = nullptr; + while ( (element = hTable->nextElement(pos)) != nullptr ) { const UHashTok valueTok = element->value; const UnicodeString* value = (UnicodeString*)valueTok.pointer; delete[] value; @@ -765,16 +772,16 @@ U_CDECL_END Hashtable* DateIntervalInfo::initHash(UErrorCode& status) { if ( U_FAILURE(status) ) { - return NULL; + return nullptr; } Hashtable* hTable; - if ( (hTable = new Hashtable(FALSE, status)) == NULL ) { + if ( (hTable = new Hashtable(FALSE, status)) == nullptr ) { status = U_MEMORY_ALLOCATION_ERROR; - return NULL; + return nullptr; } if ( U_FAILURE(status) ) { delete hTable; - return NULL; + return nullptr; } hTable->setValueComparator(dtitvinfHashTableValueComparator); return hTable; @@ -789,14 +796,18 @@ DateIntervalInfo::copyHash(const Hashtable* source, return; } int32_t pos = UHASH_FIRST; - const UHashElement* element = NULL; + const UHashElement* element = nullptr; if ( source ) { - while ( (element = source->nextElement(pos)) != NULL ) { + while ( (element = source->nextElement(pos)) != nullptr ) { const UHashTok keyTok = element->key; const UnicodeString* key = (UnicodeString*)keyTok.pointer; const UHashTok valueTok = element->value; const UnicodeString* value = (UnicodeString*)valueTok.pointer; UnicodeString* copy = new UnicodeString[kIPI_MAX_INDEX]; + if (copy == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } int8_t i; for ( i = 0; i < kIPI_MAX_INDEX; ++i ) { copy[i] = value[i]; diff --git a/deps/icu-small/source/i18n/dtptngen.cpp b/deps/icu-small/source/i18n/dtptngen.cpp index 50a377259aa80e..279fb49a7aa9b9 100644 --- a/deps/icu-small/source/i18n/dtptngen.cpp +++ b/deps/icu-small/source/i18n/dtptngen.cpp @@ -324,6 +324,7 @@ DateTimePatternGenerator::createEmptyInstance(UErrorCode& status) { DateTimePatternGenerator::DateTimePatternGenerator(UErrorCode &status) : skipMatcher(nullptr), fAvailableFormatKeyHash(nullptr), + fDefaultHourFormatChar(0), internalErrorCode(U_ZERO_ERROR) { fp = new FormatParser(); @@ -338,6 +339,7 @@ DateTimePatternGenerator::DateTimePatternGenerator(UErrorCode &status) : DateTimePatternGenerator::DateTimePatternGenerator(const Locale& locale, UErrorCode &status) : skipMatcher(nullptr), fAvailableFormatKeyHash(nullptr), + fDefaultHourFormatChar(0), internalErrorCode(U_ZERO_ERROR) { fp = new FormatParser(); @@ -356,6 +358,7 @@ DateTimePatternGenerator::DateTimePatternGenerator(const DateTimePatternGenerato UObject(), skipMatcher(nullptr), fAvailableFormatKeyHash(nullptr), + fDefaultHourFormatChar(0), internalErrorCode(U_ZERO_ERROR) { fp = new FormatParser(); @@ -654,6 +657,23 @@ void DateTimePatternGenerator::getAllowedHourFormats(const Locale &locale, UErro int32_t* allowedFormats = getAllowedHourFormatsLangCountry(language, country, status); + // We need to check if there is an hour cycle on locale + char buffer[8]; + int32_t count = locale.getKeywordValue("hours", buffer, sizeof(buffer), status); + + fDefaultHourFormatChar = 0; + if (U_SUCCESS(status) && count > 0) { + if(uprv_strcmp(buffer, "h24") == 0) { + fDefaultHourFormatChar = LOW_K; + } else if(uprv_strcmp(buffer, "h23") == 0) { + fDefaultHourFormatChar = CAP_H; + } else if(uprv_strcmp(buffer, "h12") == 0) { + fDefaultHourFormatChar = LOW_H; + } else if(uprv_strcmp(buffer, "h11") == 0) { + fDefaultHourFormatChar = CAP_K; + } + } + // Check if the region has an alias if (allowedFormats == nullptr) { UErrorCode localStatus = U_ZERO_ERROR; @@ -667,13 +687,16 @@ void DateTimePatternGenerator::getAllowedHourFormats(const Locale &locale, UErro if (allowedFormats != nullptr) { // Lookup is successful // Here allowedFormats points to a list consisting of key for preferredFormat, // followed by one or more keys for allowedFormats, then followed by ALLOWED_HOUR_FORMAT_UNKNOWN. - switch (allowedFormats[0]) { - case ALLOWED_HOUR_FORMAT_h: fDefaultHourFormatChar = LOW_H; break; - case ALLOWED_HOUR_FORMAT_H: fDefaultHourFormatChar = CAP_H; break; - case ALLOWED_HOUR_FORMAT_K: fDefaultHourFormatChar = CAP_K; break; - case ALLOWED_HOUR_FORMAT_k: fDefaultHourFormatChar = LOW_K; break; - default: fDefaultHourFormatChar = CAP_H; break; + if (!fDefaultHourFormatChar) { + switch (allowedFormats[0]) { + case ALLOWED_HOUR_FORMAT_h: fDefaultHourFormatChar = LOW_H; break; + case ALLOWED_HOUR_FORMAT_H: fDefaultHourFormatChar = CAP_H; break; + case ALLOWED_HOUR_FORMAT_K: fDefaultHourFormatChar = CAP_K; break; + case ALLOWED_HOUR_FORMAT_k: fDefaultHourFormatChar = LOW_K; break; + default: fDefaultHourFormatChar = CAP_H; break; + } } + for (int32_t i = 0; i < UPRV_LENGTHOF(fAllowedHourFormats); ++i) { fAllowedHourFormats[i] = allowedFormats[i + 1]; if (fAllowedHourFormats[i] == ALLOWED_HOUR_FORMAT_UNKNOWN) { @@ -681,12 +704,39 @@ void DateTimePatternGenerator::getAllowedHourFormats(const Locale &locale, UErro } } } else { // Lookup failed, twice - fDefaultHourFormatChar = CAP_H; + if (!fDefaultHourFormatChar) { + fDefaultHourFormatChar = CAP_H; + } fAllowedHourFormats[0] = ALLOWED_HOUR_FORMAT_H; fAllowedHourFormats[1] = ALLOWED_HOUR_FORMAT_UNKNOWN; } } +UDateFormatHourCycle +DateTimePatternGenerator::getDefaultHourCycle(UErrorCode& status) const { + if (U_FAILURE(status)) { + return UDAT_HOUR_CYCLE_23; + } + if (fDefaultHourFormatChar == 0) { + // We need to return something, but the caller should ignore it + // anyways since the returned status is a failure. + status = U_UNSUPPORTED_ERROR; + return UDAT_HOUR_CYCLE_23; + } + switch (fDefaultHourFormatChar) { + case CAP_K: + return UDAT_HOUR_CYCLE_11; + case LOW_H: + return UDAT_HOUR_CYCLE_12; + case CAP_H: + return UDAT_HOUR_CYCLE_23; + case LOW_K: + return UDAT_HOUR_CYCLE_24; + default: + UPRV_UNREACHABLE; + } +} + UnicodeString DateTimePatternGenerator::getSkeleton(const UnicodeString& pattern, UErrorCode& /*status*/) { @@ -1479,6 +1529,7 @@ DateTimePatternGenerator::getBestRaw(DateTimeMatcher& source, UErrorCode &status, const PtnSkeleton** specifiedSkeletonPtr) { int32_t bestDistance = 0x7fffffff; + int32_t bestMissingFieldMask = -1; DistanceInfo tempInfo; const UnicodeString *bestPattern=nullptr; const PtnSkeleton* specifiedSkeleton=nullptr; @@ -1492,8 +1543,15 @@ DateTimePatternGenerator::getBestRaw(DateTimeMatcher& source, continue; } int32_t distance=source.getDistance(trial, includeMask, tempInfo); - if (distancegetPatternFromSkeleton(*trial.getSkeletonPtr(), &specifiedSkeleton); missingFields->setTo(tempInfo); if (distance==0) { @@ -1546,14 +1604,16 @@ DateTimePatternGenerator::adjustFieldTypes(const UnicodeString& pattern, dtMatcher->skeleton.original.appendFieldTo(UDATPG_FRACTIONAL_SECOND_FIELD, field); } else if (dtMatcher->skeleton.type[typeValue]!=0) { // Here: - // - "reqField" is the field from the originally requested skeleton, with length - // "reqFieldLen". + // - "reqField" is the field from the originally requested skeleton after replacement + // of metacharacters 'j', 'C' and 'J', with length "reqFieldLen". // - "field" is the field from the found pattern. // // The adjusted field should consist of characters from the originally requested - // skeleton, except in the case of UDATPG_HOUR_FIELD or UDATPG_MONTH_FIELD or + // skeleton, except in the case of UDATPG_MONTH_FIELD or // UDATPG_WEEKDAY_FIELD or UDATPG_YEAR_FIELD, in which case it should consist - // of characters from the found pattern. + // of characters from the found pattern. In some cases of UDATPG_HOUR_FIELD, + // there is adjustment following the "defaultHourFormatChar". There is explanation + // how it is done below. // // The length of the adjusted field (adjFieldLen) should match that in the originally // requested skeleton, except that in the following cases the length of the adjusted field @@ -1591,9 +1651,28 @@ DateTimePatternGenerator::adjustFieldTypes(const UnicodeString& pattern, && (typeValue!= UDATPG_YEAR_FIELD || reqFieldChar==CAP_Y)) ? reqFieldChar : field.charAt(0); - if (typeValue == UDATPG_HOUR_FIELD && (flags & kDTPGSkeletonUsesCapJ) != 0) { - c = fDefaultHourFormatChar; + if (typeValue == UDATPG_HOUR_FIELD && fDefaultHourFormatChar != 0) { + // The adjustment here is required to match spec (https://www.unicode.org/reports/tr35/tr35-dates.html#dfst-hour). + // It is necessary to match the hour-cycle preferred by the Locale. + // Given that, we need to do the following adjustments: + // 1. When hour-cycle is h11 it should replace 'h' by 'K'. + // 2. When hour-cycle is h23 it should replace 'H' by 'k'. + // 3. When hour-cycle is h24 it should replace 'k' by 'H'. + // 4. When hour-cycle is h12 it should replace 'K' by 'h'. + + if ((flags & kDTPGSkeletonUsesCapJ) != 0 || reqFieldChar == fDefaultHourFormatChar) { + c = fDefaultHourFormatChar; + } else if (reqFieldChar == LOW_H && fDefaultHourFormatChar == CAP_K) { + c = CAP_K; + } else if (reqFieldChar == CAP_H && fDefaultHourFormatChar == LOW_K) { + c = LOW_K; + } else if (reqFieldChar == LOW_K && fDefaultHourFormatChar == CAP_H) { + c = CAP_H; + } else if (reqFieldChar == CAP_K && fDefaultHourFormatChar == LOW_H) { + c = LOW_H; + } } + field.remove(); for (int32_t j=adjFieldLen; j>0; --j) { field += c; @@ -2118,6 +2197,11 @@ DateTimeMatcher::DateTimeMatcher(const DateTimeMatcher& other) { copyFrom(other.skeleton); } +DateTimeMatcher& DateTimeMatcher::operator=(const DateTimeMatcher& other) { + copyFrom(other.skeleton); + return *this; +} + void DateTimeMatcher::set(const UnicodeString& pattern, FormatParser* fp) { @@ -2162,6 +2246,33 @@ DateTimeMatcher::set(const UnicodeString& pattern, FormatParser* fp, PtnSkeleton } skeletonResult.type[field] = subField; } + + // #20739, we have a skeleton with minutes and milliseconds, but no seconds + // + // Theoretically we would need to check and fix all fields with "gaps": + // for example year-day (no month), month-hour (no day), and so on, All the possible field combinations. + // Plus some smartness: year + hour => should we add month, or add day-of-year? + // What about month + day-of-week, or month + am/pm indicator. + // I think beyond a certain point we should not try to fix bad developer input and try guessing what they mean. + // Garbage in, garbage out. + if (!skeletonResult.original.isFieldEmpty(UDATPG_MINUTE_FIELD) + && !skeletonResult.original.isFieldEmpty(UDATPG_FRACTIONAL_SECOND_FIELD) + && skeletonResult.original.isFieldEmpty(UDATPG_SECOND_FIELD)) { + // Force the use of seconds + for (i = 0; dtTypes[i].patternChar != 0; i++) { + if (dtTypes[i].field == UDATPG_SECOND_FIELD) { + // first entry for UDATPG_SECOND_FIELD + skeletonResult.original.populate(UDATPG_SECOND_FIELD, dtTypes[i].patternChar, dtTypes[i].minLen); + skeletonResult.baseOriginal.populate(UDATPG_SECOND_FIELD, dtTypes[i].patternChar, dtTypes[i].minLen); + // We add value.length, same as above, when type is first initialized. + // The value we want to "fake" here is "s", and 1 means "s".length() + int16_t subField = dtTypes[i].type; + skeletonResult.type[UDATPG_SECOND_FIELD] = (subField > 0) ? subField + 1 : subField; + break; + } + } + } + // #13183, handle special behavior for day period characters (a, b, B) if (!skeletonResult.original.isFieldEmpty(UDATPG_HOUR_FIELD)) { if (skeletonResult.original.getFieldChar(UDATPG_HOUR_FIELD)==LOW_H || skeletonResult.original.getFieldChar(UDATPG_HOUR_FIELD)==CAP_K) { diff --git a/deps/icu-small/source/i18n/dtptngen_impl.h b/deps/icu-small/source/i18n/dtptngen_impl.h index 95219f0ba257f5..ade9f57331e769 100644 --- a/deps/icu-small/source/i18n/dtptngen_impl.h +++ b/deps/icu-small/source/i18n/dtptngen_impl.h @@ -238,6 +238,7 @@ class DateTimeMatcher: public UMemory { int32_t getDistance(const DateTimeMatcher& other, int32_t includeMask, DistanceInfo& distanceInfo) const; DateTimeMatcher(); DateTimeMatcher(const DateTimeMatcher& other); + DateTimeMatcher& operator=(const DateTimeMatcher& other); virtual ~DateTimeMatcher(); int32_t getFieldMask() const; }; diff --git a/deps/icu-small/source/i18n/formatted_string_builder.cpp b/deps/icu-small/source/i18n/formatted_string_builder.cpp index 3024bff6addacc..5aabc31cc4391b 100644 --- a/deps/icu-small/source/i18n/formatted_string_builder.cpp +++ b/deps/icu-small/source/i18n/formatted_string_builder.cpp @@ -8,6 +8,7 @@ #include "formatted_string_builder.h" #include "unicode/ustring.h" #include "unicode/utf16.h" +#include "unicode/unum.h" // for UNumberFormatFields literals namespace { @@ -246,7 +247,7 @@ void FormattedStringBuilder::writeTerminator(UErrorCode& status) { return; } getCharPtr()[position] = 0; - getFieldPtr()[position] = UNUM_FIELD_COUNT; + getFieldPtr()[position] = kUndefinedField; fLength--; } @@ -360,11 +361,11 @@ UnicodeString FormattedStringBuilder::toDebugString() const { sb.append(toUnicodeString()); sb.append(u"] [", -1); for (int i = 0; i < fLength; i++) { - if (fieldAt(i) == UNUM_FIELD_COUNT) { + if (fieldAt(i) == kUndefinedField) { sb.append(u'n'); - } else { + } else if (fieldAt(i).getCategory() == UFIELD_CATEGORY_NUMBER) { char16_t c; - switch (fieldAt(i)) { + switch (fieldAt(i).getField()) { case UNUM_SIGN_FIELD: c = u'-'; break; @@ -399,10 +400,12 @@ UnicodeString FormattedStringBuilder::toDebugString() const { c = u'$'; break; default: - c = u'?'; + c = u'0' + fieldAt(i).getField(); break; } sb.append(c); + } else { + sb.append(u'0' + fieldAt(i).getCategory()); } } sb.append(u"]>", -1); diff --git a/deps/icu-small/source/i18n/formatted_string_builder.h b/deps/icu-small/source/i18n/formatted_string_builder.h index 2949ae73e0ff9e..4567dc1d66b0ce 100644 --- a/deps/icu-small/source/i18n/formatted_string_builder.h +++ b/deps/icu-small/source/i18n/formatted_string_builder.h @@ -9,7 +9,8 @@ #include -#include "unicode/unum.h" // for UNUM_FIELD_COUNT +#include + #include "cstring.h" #include "uassert.h" #include "fphdlimp.h" @@ -55,7 +56,20 @@ class U_I18N_API FormattedStringBuilder : public UMemory { // Field category 0 implies the number category so that the number field // literals can be directly passed as a Field type. // See the helper functions in "StringBuilderFieldUtils" below. - typedef uint8_t Field; + // Exported as U_I18N_API so it can be used by other exports on Windows. + struct U_I18N_API Field { + uint8_t bits; + + Field() = default; + constexpr Field(uint8_t category, uint8_t field); + + inline UFieldCategory getCategory() const; + inline int32_t getField() const; + inline bool isNumeric() const; + inline bool isUndefined() const; + inline bool operator==(const Field& other) const; + inline bool operator!=(const Field& other) const; + }; FormattedStringBuilder &operator=(const FormattedStringBuilder &other); @@ -204,46 +218,50 @@ class U_I18N_API FormattedStringBuilder : public UMemory { friend class FormattedValueStringBuilderImpl; }; +static_assert( + std::is_pod::value, + "Field should be a POD type for efficient initialization"); + +constexpr FormattedStringBuilder::Field::Field(uint8_t category, uint8_t field) + : bits(( + U_ASSERT(category <= 0xf), + U_ASSERT(field <= 0xf), + static_cast((category << 4) | field) + )) {} + /** - * Helper functions for dealing with the Field typedef, which stores fields - * in a compressed format. + * Internal constant for the undefined field for use in FormattedStringBuilder. */ -class StringBuilderFieldUtils { -public: - struct CategoryFieldPair { - int32_t category; - int32_t field; - }; +constexpr FormattedStringBuilder::Field kUndefinedField = {UFIELD_CATEGORY_UNDEFINED, 0}; - /** Compile-time function to construct a Field from a category and a field */ - template - static constexpr FormattedStringBuilder::Field compress() { - static_assert(category != 0, "cannot use Undefined category in FieldUtils"); - static_assert(category <= 0xf, "only 4 bits for category"); - static_assert(field <= 0xf, "only 4 bits for field"); - return static_cast((category << 4) | field); - } +/** + * Internal field to signal "numeric" when fields are not supported in NumberFormat. + */ +constexpr FormattedStringBuilder::Field kGeneralNumericField = {UFIELD_CATEGORY_UNDEFINED, 1}; - /** Runtime inline function to unpack the category and field from the Field */ - static inline CategoryFieldPair expand(FormattedStringBuilder::Field field) { - if (field == UNUM_FIELD_COUNT) { - return {UFIELD_CATEGORY_UNDEFINED, 0}; - } - CategoryFieldPair ret = { - (field >> 4), - (field & 0xf) - }; - if (ret.category == 0) { - ret.category = UFIELD_CATEGORY_NUMBER; - } - return ret; - } +inline UFieldCategory FormattedStringBuilder::Field::getCategory() const { + return static_cast(bits >> 4); +} - static inline bool isNumericField(FormattedStringBuilder::Field field) { - int8_t category = field >> 4; - return category == 0 || category == UFIELD_CATEGORY_NUMBER; - } -}; +inline int32_t FormattedStringBuilder::Field::getField() const { + return bits & 0xf; +} + +inline bool FormattedStringBuilder::Field::isNumeric() const { + return getCategory() == UFIELD_CATEGORY_NUMBER || *this == kGeneralNumericField; +} + +inline bool FormattedStringBuilder::Field::isUndefined() const { + return getCategory() == UFIELD_CATEGORY_UNDEFINED; +} + +inline bool FormattedStringBuilder::Field::operator==(const Field& other) const { + return bits == other.bits; +} + +inline bool FormattedStringBuilder::Field::operator!=(const Field& other) const { + return bits != other.bits; +} U_NAMESPACE_END diff --git a/deps/icu-small/source/i18n/formattedval_impl.h b/deps/icu-small/source/i18n/formattedval_impl.h index 4ee53e4589b2e9..73ae9a3ea2ab3a 100644 --- a/deps/icu-small/source/i18n/formattedval_impl.h +++ b/deps/icu-small/source/i18n/formattedval_impl.h @@ -153,7 +153,6 @@ class U_I18N_API FormattedValueStringBuilderImpl : public UMemory, public Format bool nextPositionImpl(ConstrainedFieldPosition& cfpos, FormattedStringBuilder::Field numericField, UErrorCode& status) const; static bool isIntOrGroup(FormattedStringBuilder::Field field); - static bool isNumericField(FormattedStringBuilder::Field field); int32_t trimBack(int32_t limit) const; int32_t trimFront(int32_t start) const; }; diff --git a/deps/icu-small/source/i18n/formattedval_sbimpl.cpp b/deps/icu-small/source/i18n/formattedval_sbimpl.cpp index ca28f222813afc..dfe3af6686df2f 100644 --- a/deps/icu-small/source/i18n/formattedval_sbimpl.cpp +++ b/deps/icu-small/source/i18n/formattedval_sbimpl.cpp @@ -63,7 +63,7 @@ UBool FormattedValueStringBuilderImpl::nextFieldPosition(FieldPosition& fp, UErr ConstrainedFieldPosition cfpos; cfpos.constrainField(UFIELD_CATEGORY_NUMBER, rawField); cfpos.setState(UFIELD_CATEGORY_NUMBER, rawField, fp.getBeginIndex(), fp.getEndIndex()); - if (nextPositionImpl(cfpos, 0, status)) { + if (nextPositionImpl(cfpos, kUndefinedField, status)) { fp.setBeginIndex(cfpos.getStart()); fp.setEndIndex(cfpos.getLimit()); return TRUE; @@ -74,7 +74,7 @@ UBool FormattedValueStringBuilderImpl::nextFieldPosition(FieldPosition& fp, UErr bool inside = false; int32_t i = fString.fZero; for (; i < fString.fZero + fString.fLength; i++) { - if (isIntOrGroup(fString.getFieldPtr()[i]) || fString.getFieldPtr()[i] == UNUM_DECIMAL_SEPARATOR_FIELD) { + if (isIntOrGroup(fString.getFieldPtr()[i]) || fString.getFieldPtr()[i] == Field(UFIELD_CATEGORY_NUMBER, UNUM_DECIMAL_SEPARATOR_FIELD)) { inside = true; } else if (inside) { break; @@ -90,42 +90,40 @@ UBool FormattedValueStringBuilderImpl::nextFieldPosition(FieldPosition& fp, UErr void FormattedValueStringBuilderImpl::getAllFieldPositions(FieldPositionIteratorHandler& fpih, UErrorCode& status) const { ConstrainedFieldPosition cfpos; - while (nextPositionImpl(cfpos, 0, status)) { + while (nextPositionImpl(cfpos, kUndefinedField, status)) { fpih.addAttribute(cfpos.getField(), cfpos.getStart(), cfpos.getLimit()); } } // Signal the end of the string using a field that doesn't exist and that is -// different from UNUM_FIELD_COUNT, which is used for "null number field". -static constexpr Field kEndField = 0xff; +// different from kUndefinedField, which is used for "null field". +static constexpr Field kEndField = Field(0xf, 0xf); bool FormattedValueStringBuilderImpl::nextPositionImpl(ConstrainedFieldPosition& cfpos, Field numericField, UErrorCode& /*status*/) const { - auto numericCAF = StringBuilderFieldUtils::expand(numericField); int32_t fieldStart = -1; - Field currField = UNUM_FIELD_COUNT; + Field currField = kUndefinedField; for (int32_t i = fString.fZero + cfpos.getLimit(); i <= fString.fZero + fString.fLength; i++) { Field _field = (i < fString.fZero + fString.fLength) ? fString.getFieldPtr()[i] : kEndField; // Case 1: currently scanning a field. - if (currField != UNUM_FIELD_COUNT) { + if (currField != kUndefinedField) { if (currField != _field) { int32_t end = i - fString.fZero; // Grouping separators can be whitespace; don't throw them out! - if (currField != UNUM_GROUPING_SEPARATOR_FIELD) { + if (currField != Field(UFIELD_CATEGORY_NUMBER, UNUM_GROUPING_SEPARATOR_FIELD)) { end = trimBack(i - fString.fZero); } if (end <= fieldStart) { // Entire field position is ignorable; skip. fieldStart = -1; - currField = UNUM_FIELD_COUNT; + currField = kUndefinedField; i--; // look at this index again continue; } int32_t start = fieldStart; - if (currField != UNUM_GROUPING_SEPARATOR_FIELD) { + if (currField != Field(UFIELD_CATEGORY_NUMBER, UNUM_GROUPING_SEPARATOR_FIELD)) { start = trimFront(start); } - auto caf = StringBuilderFieldUtils::expand(currField); - cfpos.setState(caf.category, caf.field, start, end); + cfpos.setState(currField.getCategory(), currField.getField(), start, end); return true; } continue; @@ -147,51 +145,46 @@ bool FormattedValueStringBuilderImpl::nextPositionImpl(ConstrainedFieldPosition& return true; } // Special case: coalesce NUMERIC if we are pointing at the end of the NUMERIC. - if (numericField != 0 - && cfpos.matchesField(numericCAF.category, numericCAF.field) + if (numericField != kUndefinedField + && cfpos.matchesField(numericField.getCategory(), numericField.getField()) && i > fString.fZero // don't return the same field twice in a row: && (i - fString.fZero > cfpos.getLimit() - || cfpos.getCategory() != numericCAF.category - || cfpos.getField() != numericCAF.field) - && isNumericField(fString.getFieldPtr()[i - 1]) - && !isNumericField(_field)) { + || cfpos.getCategory() != numericField.getCategory() + || cfpos.getField() != numericField.getField()) + && fString.getFieldPtr()[i - 1].isNumeric() + && !_field.isNumeric()) { int j = i - 1; - for (; j >= fString.fZero && isNumericField(fString.getFieldPtr()[j]); j--) {} + for (; j >= fString.fZero && fString.getFieldPtr()[j].isNumeric(); j--) {} cfpos.setState( - numericCAF.category, - numericCAF.field, + numericField.getCategory(), + numericField.getField(), j - fString.fZero + 1, i - fString.fZero); return true; } // Special case: skip over INTEGER; will be coalesced later. - if (_field == UNUM_INTEGER_FIELD) { - _field = UNUM_FIELD_COUNT; + if (_field == Field(UFIELD_CATEGORY_NUMBER, UNUM_INTEGER_FIELD)) { + _field = kUndefinedField; } // Case 2: no field starting at this position. - if (_field == UNUM_FIELD_COUNT || _field == kEndField) { + if (_field.isUndefined() || _field == kEndField) { continue; } // Case 3: check for field starting at this position - auto caf = StringBuilderFieldUtils::expand(_field); - if (cfpos.matchesField(caf.category, caf.field)) { + if (cfpos.matchesField(_field.getCategory(), _field.getField())) { fieldStart = i - fString.fZero; currField = _field; } } - U_ASSERT(currField == UNUM_FIELD_COUNT); + U_ASSERT(currField == kUndefinedField); return false; } bool FormattedValueStringBuilderImpl::isIntOrGroup(Field field) { - return field == UNUM_INTEGER_FIELD - || field == UNUM_GROUPING_SEPARATOR_FIELD; -} - -bool FormattedValueStringBuilderImpl::isNumericField(Field field) { - return StringBuilderFieldUtils::isNumericField(field); + return field == Field(UFIELD_CATEGORY_NUMBER, UNUM_INTEGER_FIELD) + || field == Field(UFIELD_CATEGORY_NUMBER, UNUM_GROUPING_SEPARATOR_FIELD); } int32_t FormattedValueStringBuilderImpl::trimBack(int32_t limit) const { diff --git a/deps/icu-small/source/i18n/fphdlimp.h b/deps/icu-small/source/i18n/fphdlimp.h index 00937830fe7b80..b9fa9b218149d4 100644 --- a/deps/icu-small/source/i18n/fphdlimp.h +++ b/deps/icu-small/source/i18n/fphdlimp.h @@ -62,8 +62,9 @@ class FieldPositionOnlyHandler : public FieldPositionHandler { // utility subclass FieldPositionIteratorHandler +// exported as U_I18N_API for tests -class FieldPositionIteratorHandler : public FieldPositionHandler { +class U_I18N_API FieldPositionIteratorHandler : public FieldPositionHandler { FieldPositionIterator* iter; // can be NULL UVector32* vec; UErrorCode status; diff --git a/deps/icu-small/source/i18n/gender.cpp b/deps/icu-small/source/i18n/gender.cpp index 03c03cecad94ba..e3ec5ad27298f4 100644 --- a/deps/icu-small/source/i18n/gender.cpp +++ b/deps/icu-small/source/i18n/gender.cpp @@ -160,7 +160,7 @@ const GenderInfo* GenderInfo::loadInstance(const Locale& locale, UErrorCode& sta if (s == NULL) { return &gObjs[NEUTRAL]; } - char type_str[256]; + char type_str[256] = ""; u_UCharsToChars(s, type_str, resLen + 1); if (uprv_strcmp(type_str, gNeutralStr) == 0) { return &gObjs[NEUTRAL]; diff --git a/deps/icu-small/source/i18n/listformatter.cpp b/deps/icu-small/source/i18n/listformatter.cpp index 35cc00de252aa7..4b27587555219c 100644 --- a/deps/icu-small/source/i18n/listformatter.cpp +++ b/deps/icu-small/source/i18n/listformatter.cpp @@ -21,6 +21,7 @@ #include "unicode/listformatter.h" #include "unicode/simpleformatter.h" #include "unicode/ulistformatter.h" +#include "unicode/uscript.h" #include "fphdlimp.h" #include "mutex.h" #include "hash.h" @@ -35,34 +36,203 @@ U_NAMESPACE_BEGIN -struct ListFormatInternal : public UMemory { +namespace { + +class PatternHandler : public UObject { +public: + PatternHandler(const UnicodeString& two, const UnicodeString& end, UErrorCode& errorCode) : + twoPattern(two, 2, 2, errorCode), + endPattern(end, 2, 2, errorCode) { } + + PatternHandler(const SimpleFormatter& two, const SimpleFormatter& end) : + twoPattern(two), + endPattern(end) { } + + virtual ~PatternHandler(); + + virtual PatternHandler* clone() const { return new PatternHandler(twoPattern, endPattern); } + + virtual const SimpleFormatter& getTwoPattern(const UnicodeString&) const { + return twoPattern; + } + + virtual const SimpleFormatter& getEndPattern(const UnicodeString&) const { + return endPattern; + } + +protected: SimpleFormatter twoPattern; + SimpleFormatter endPattern; +}; + +PatternHandler::~PatternHandler() { +} + +class ContextualHandler : public PatternHandler { +public: + ContextualHandler(bool (*testFunc)(const UnicodeString& text), + const UnicodeString& thenTwo, + const UnicodeString& elseTwo, + const UnicodeString& thenEnd, + const UnicodeString& elseEnd, + UErrorCode& errorCode) : + PatternHandler(elseTwo, elseEnd, errorCode), + test(testFunc), + thenTwoPattern(thenTwo, 2, 2, errorCode), + thenEndPattern(thenEnd, 2, 2, errorCode) { } + + ContextualHandler(bool (*testFunc)(const UnicodeString& text), + const SimpleFormatter& thenTwo, SimpleFormatter elseTwo, + const SimpleFormatter& thenEnd, SimpleFormatter elseEnd) : + PatternHandler(elseTwo, elseEnd), + test(testFunc), + thenTwoPattern(thenTwo), + thenEndPattern(thenEnd) { } + + ~ContextualHandler() override; + + PatternHandler* clone() const override { + return new ContextualHandler( + test, thenTwoPattern, twoPattern, thenEndPattern, endPattern); + } + + const SimpleFormatter& getTwoPattern( + const UnicodeString& text) const override { + return (test)(text) ? thenTwoPattern : twoPattern; + } + + const SimpleFormatter& getEndPattern( + const UnicodeString& text) const override { + return (test)(text) ? thenEndPattern : endPattern; + } + +private: + bool (*test)(const UnicodeString&); + SimpleFormatter thenTwoPattern; + SimpleFormatter thenEndPattern; +}; + +ContextualHandler::~ContextualHandler() { +} + +static const char16_t *spanishY = u"{0} y {1}"; +static const char16_t *spanishE = u"{0} e {1}"; +static const char16_t *spanishO = u"{0} o {1}"; +static const char16_t *spanishU = u"{0} u {1}"; +static const char16_t *hebrewVav = u"{0} \u05D5{1}"; +static const char16_t *hebrewVavDash = u"{0} \u05D5-{1}"; + +// Condiction to change to e. +// Starts with "hi" or "i" but not with "hie" nor "hia" +static bool shouldChangeToE(const UnicodeString& text) { + int32_t len = text.length(); + if (len == 0) { return false; } + // Case insensitive match hi but not hie nor hia. + if ((text[0] == u'h' || text[0] == u'H') && + ((len > 1) && (text[1] == u'i' || text[1] == u'I')) && + ((len == 2) || !(text[2] == u'a' || text[2] == u'A' || text[2] == u'e' || text[2] == u'E'))) { + return true; + } + // Case insensitive for "start with i" + if (text[0] == u'i' || text[0] == u'I') { return true; } + return false; +} + +// Condiction to change to u. +// Starts with "o", "ho", and "8". Also "11" by itself. +// re: ^((o|ho|8).*|11)$ +static bool shouldChangeToU(const UnicodeString& text) { + int32_t len = text.length(); + if (len == 0) { return false; } + // Case insensitive match o.* and 8.* + if (text[0] == u'o' || text[0] == u'O' || text[0] == u'8') { return true; } + // Case insensitive match ho.* + if ((text[0] == u'h' || text[0] == u'H') && + ((len > 1) && (text[1] == 'o' || text[1] == u'O'))) { + return true; + } + // match "^11$" and "^11 .*" + if ((len >= 2) && text[0] == u'1' && text[1] == u'1' && (len == 2 || text[2] == u' ')) { return true; } + return false; +} + +// Condiction to change to VAV follow by a dash. +// Starts with non Hebrew letter. +static bool shouldChangeToVavDash(const UnicodeString& text) { + if (text.isEmpty()) { return false; } + UErrorCode status = U_ZERO_ERROR; + return uscript_getScript(text.char32At(0), &status) != USCRIPT_HEBREW; +} + +PatternHandler* createPatternHandler( + const char* lang, const UnicodeString& two, const UnicodeString& end, + UErrorCode& status) { + if (uprv_strcmp(lang, "es") == 0) { + // Spanish + UnicodeString spanishYStr(TRUE, spanishY, -1); + bool twoIsY = two == spanishYStr; + bool endIsY = end == spanishYStr; + if (twoIsY || endIsY) { + UnicodeString replacement(TRUE, spanishE, -1); + return new ContextualHandler( + shouldChangeToE, + twoIsY ? replacement : two, two, + endIsY ? replacement : end, end, status); + } + UnicodeString spanishOStr(TRUE, spanishO, -1); + bool twoIsO = two == spanishOStr; + bool endIsO = end == spanishOStr; + if (twoIsO || endIsO) { + UnicodeString replacement(TRUE, spanishU, -1); + return new ContextualHandler( + shouldChangeToU, + twoIsO ? replacement : two, two, + endIsO ? replacement : end, end, status); + } + } else if (uprv_strcmp(lang, "he") == 0 || uprv_strcmp(lang, "iw") == 0) { + // Hebrew + UnicodeString hebrewVavStr(TRUE, hebrewVav, -1); + bool twoIsVav = two == hebrewVavStr; + bool endIsVav = end == hebrewVavStr; + if (twoIsVav || endIsVav) { + UnicodeString replacement(TRUE, hebrewVavDash, -1); + return new ContextualHandler( + shouldChangeToVavDash, + twoIsVav ? replacement : two, two, + endIsVav ? replacement : end, end, status); + } + } + return new PatternHandler(two, end, status); +} + +} // namespace + +struct ListFormatInternal : public UMemory { SimpleFormatter startPattern; SimpleFormatter middlePattern; - SimpleFormatter endPattern; + LocalPointer patternHandler; ListFormatInternal( const UnicodeString& two, const UnicodeString& start, const UnicodeString& middle, const UnicodeString& end, + const Locale& locale, UErrorCode &errorCode) : - twoPattern(two, 2, 2, errorCode), startPattern(start, 2, 2, errorCode), middlePattern(middle, 2, 2, errorCode), - endPattern(end, 2, 2, errorCode) {} + patternHandler(createPatternHandler(locale.getLanguage(), two, end, errorCode), errorCode) { } ListFormatInternal(const ListFormatData &data, UErrorCode &errorCode) : - twoPattern(data.twoPattern, errorCode), startPattern(data.startPattern, errorCode), middlePattern(data.middlePattern, errorCode), - endPattern(data.endPattern, errorCode) { } + patternHandler(createPatternHandler( + data.locale.getLanguage(), data.twoPattern, data.endPattern, errorCode), errorCode) { } ListFormatInternal(const ListFormatInternal &other) : - twoPattern(other.twoPattern), startPattern(other.startPattern), middlePattern(other.middlePattern), - endPattern(other.endPattern) { } + patternHandler(other.patternHandler->clone()) { } }; @@ -80,7 +250,6 @@ UPRV_FORMATTED_VALUE_SUBCLASS_AUTO_IMPL(FormattedList) static Hashtable* listPatternHash = nullptr; -static const char STANDARD_STYLE[] = "standard"; U_CDECL_BEGIN static UBool U_CALLCONV uprv_listformatter_cleanup() { @@ -179,6 +348,52 @@ const ListFormatInternal* ListFormatter::getListFormatInternal( return result; } +#if !UCONFIG_NO_FORMATTING +static const char* typeWidthToStyleString(UListFormatterType type, UListFormatterWidth width) { + switch (type) { + case ULISTFMT_TYPE_AND: + switch (width) { + case ULISTFMT_WIDTH_WIDE: + return "standard"; + case ULISTFMT_WIDTH_SHORT: + return "standard-short"; + case ULISTFMT_WIDTH_NARROW: + return "standard-narrow"; + default: + return nullptr; + } + break; + + case ULISTFMT_TYPE_OR: + switch (width) { + case ULISTFMT_WIDTH_WIDE: + return "or"; + case ULISTFMT_WIDTH_SHORT: + return "or-short"; + case ULISTFMT_WIDTH_NARROW: + return "or-narrow"; + default: + return nullptr; + } + break; + + case ULISTFMT_TYPE_UNITS: + switch (width) { + case ULISTFMT_WIDTH_WIDE: + return "unit"; + case ULISTFMT_WIDTH_SHORT: + return "unit-short"; + case ULISTFMT_WIDTH_NARROW: + return "unit-narrow"; + default: + return nullptr; + } + } + + return nullptr; +} +#endif + static const UChar solidus = 0x2F; static const UChar aliasPrefix[] = { 0x6C,0x69,0x73,0x74,0x50,0x61,0x74,0x74,0x65,0x72,0x6E,0x2F }; // "listPattern/" enum { @@ -279,7 +494,8 @@ ListFormatInternal* ListFormatter::loadListFormatInternal( errorCode = U_MISSING_RESOURCE_ERROR; return nullptr; } - ListFormatInternal* result = new ListFormatInternal(sink.two, sink.start, sink.middle, sink.end, errorCode); + + ListFormatInternal* result = new ListFormatInternal(sink.two, sink.start, sink.middle, sink.end, locale, errorCode); if (result == nullptr) { errorCode = U_MEMORY_ALLOCATION_ERROR; return nullptr; @@ -297,9 +513,25 @@ ListFormatter* ListFormatter::createInstance(UErrorCode& errorCode) { } ListFormatter* ListFormatter::createInstance(const Locale& locale, UErrorCode& errorCode) { - return createInstance(locale, STANDARD_STYLE, errorCode); +#if !UCONFIG_NO_FORMATTING + return createInstance(locale, ULISTFMT_TYPE_AND, ULISTFMT_WIDTH_WIDE, errorCode); +#else + return createInstance(locale, "standard", errorCode); +#endif } +#if !UCONFIG_NO_FORMATTING +ListFormatter* ListFormatter::createInstance( + const Locale& locale, UListFormatterType type, UListFormatterWidth width, UErrorCode& errorCode) { + const char* style = typeWidthToStyleString(type, width); + if (style == nullptr) { + errorCode = U_ILLEGAL_ARGUMENT_ERROR; + return nullptr; + } + return createInstance(locale, style, errorCode); +} +#endif + ListFormatter* ListFormatter::createInstance(const Locale& locale, const char *style, UErrorCode& errorCode) { const ListFormatInternal* listFormatInternal = getListFormatInternal(locale, style, errorCode); if (U_FAILURE(errorCode)) { @@ -380,19 +612,6 @@ UnicodeString& ListFormatter::format( return format(items, nItems, appendTo, -1, offset, errorCode); } -#if !UCONFIG_NO_FORMATTING -UnicodeString& ListFormatter::format( - const UnicodeString items[], - int32_t nItems, - UnicodeString & appendTo, - FieldPositionIterator* posIter, - UErrorCode& errorCode) const { - int32_t offset; - FieldPositionIteratorHandler handler(posIter, errorCode); - return format_(items, nItems, appendTo, -1, offset, &handler, errorCode); -} -#endif - UnicodeString& ListFormatter::format( const UnicodeString items[], int32_t nItems, @@ -484,16 +703,29 @@ UnicodeString& ListFormatter::format_( // for n items, there are 2 * (n + 1) boundary including 0 and the upper // edge. MaybeStackArray offsets((handler != nullptr) ? 2 * (nItems + 1): 0); - joinStringsAndReplace( - nItems == 2 ? data->twoPattern : data->startPattern, - result, - items[1], - result, - index == 1, - offset, - &offsetFirst, - &offsetSecond, - errorCode); + if (nItems == 2) { + joinStringsAndReplace( + data->patternHandler->getTwoPattern(items[1]), + result, + items[1], + result, + index == 1, + offset, + &offsetFirst, + &offsetSecond, + errorCode); + } else { + joinStringsAndReplace( + data->startPattern, + result, + items[1], + result, + index == 1, + offset, + &offsetFirst, + &offsetSecond, + errorCode); + } if (handler != nullptr) { offsets[0] = 0; prefixLength += offsetFirst; @@ -517,7 +749,7 @@ UnicodeString& ListFormatter::format_( } } joinStringsAndReplace( - data->endPattern, + data->patternHandler->getEndPattern(items[nItems - 1]), result, items[nItems - 1], result, diff --git a/deps/icu-small/source/i18n/measfmt.cpp b/deps/icu-small/source/i18n/measfmt.cpp index 47ffb140cf6712..a98a6dda4705b5 100644 --- a/deps/icu-small/source/i18n/measfmt.cpp +++ b/deps/icu-small/source/i18n/measfmt.cpp @@ -38,6 +38,7 @@ #include "uassert.h" #include "unicode/numberformatter.h" #include "number_longnames.h" +#include "number_utypes.h" #include "sharednumberformat.h" #include "sharedpluralrules.h" @@ -47,6 +48,8 @@ U_NAMESPACE_BEGIN +using number::impl::UFormattedNumberData; + static constexpr int32_t WIDTH_INDEX_COUNT = UMEASFMT_WIDTH_NARROW + 1; UOBJECT_DEFINE_RTTI_IMPLEMENTATION(MeasureFormat) @@ -504,12 +507,13 @@ UnicodeString &MeasureFormat::formatMeasurePerUnit( status = U_UNSUPPORTED_ERROR; return appendTo; } - number::FormattedNumber result; + UFormattedNumberData result; if (auto* lnf = df->toNumberFormatter(status)) { - result = lnf->unit(measure.getUnit()) + result.quantity.setToDouble(measure.getNumber().getDouble(status)); + lnf->unit(measure.getUnit()) .perUnit(perUnit) .unitWidth(getUnitWidth(fWidth)) - .formatDouble(measure.getNumber().getDouble(status), status); + .formatImpl(&result, status); } DecimalFormat::fieldPositionHelper(result, pos, appendTo.length(), status); appendTo.append(result.toTempString(status)); @@ -699,11 +703,12 @@ UnicodeString &MeasureFormat::formatMeasure( SimpleFormatter formatter(pattern, 0, 1, status); return QuantityFormatter::format(formatter, formattedNumber, appendTo, pos, status); } - number::FormattedNumber result; + UFormattedNumberData result; if (auto* lnf = df->toNumberFormatter(status)) { - result = lnf->unit(amtUnit) + result.quantity.setToDouble(amtNumber.getDouble(status)); + lnf->unit(amtUnit) .unitWidth(getUnitWidth(fWidth)) - .formatDouble(amtNumber.getDouble(status), status); + .formatImpl(&result, status); } DecimalFormat::fieldPositionHelper(result, pos, appendTo.length(), status); appendTo.append(result.toTempString(status)); @@ -774,11 +779,6 @@ UnicodeString &MeasureFormat::formatNumeric( case u's': value = seconds; break; } - // For undefined field we use UNUM_FIELD_COUNT, for historical reasons. - // See cleanup bug: https://unicode-org.atlassian.net/browse/ICU-20665 - // But we give it a clear name, to keep "the ugly part" in one place. - constexpr UNumberFormatFields undefinedField = UNUM_FIELD_COUNT; - // There is not enough info to add Field(s) for the unit because all we have are plain // text patterns. For example in "21:51" there is no text for something like "hour", // while in something like "21h51" there is ("h"). But we can't really tell... @@ -787,7 +787,7 @@ UnicodeString &MeasureFormat::formatNumeric( case u'm': case u's': if (protect) { - fsb.appendChar16(c, undefinedField, status); + fsb.appendChar16(c, kUndefinedField, status); } else { UnicodeString tmp; if ((i + 1 < patternLength) && pattern[i + 1] == c) { // doubled @@ -797,20 +797,20 @@ UnicodeString &MeasureFormat::formatNumeric( numberFormatter->format(value, tmp, status); } // TODO: Use proper Field - fsb.append(tmp, undefinedField, status); + fsb.append(tmp, kUndefinedField, status); } break; case u'\'': // '' is escaped apostrophe if ((i + 1 < patternLength) && pattern[i + 1] == c) { - fsb.appendChar16(c, undefinedField, status); + fsb.appendChar16(c, kUndefinedField, status); i++; } else { protect = !protect; } break; default: - fsb.appendChar16(c, undefinedField, status); + fsb.appendChar16(c, kUndefinedField, status); } } diff --git a/deps/icu-small/source/i18n/measunit.cpp b/deps/icu-small/source/i18n/measunit.cpp index 917c0cdfadf235..2486ca9b15a05e 100644 --- a/deps/icu-small/source/i18n/measunit.cpp +++ b/deps/icu-small/source/i18n/measunit.cpp @@ -17,9 +17,11 @@ #if !UCONFIG_NO_FORMATTING #include "unicode/uenum.h" +#include "unicode/errorcode.h" #include "ustrenum.h" #include "cstring.h" #include "uassert.h" +#include "measunit_impl.h" U_NAMESPACE_BEGIN @@ -118,7 +120,7 @@ static const char * const gTypes[] = { // Must be grouped by type and sorted alphabetically within each type. static const char * const gSubTypes[] = { "g-force", - "meter-per-second-squared", + "meter-per-square-second", "arc-minute", "arc-second", "degree", @@ -138,11 +140,11 @@ static const char * const gSubTypes[] = { "milligram-per-deciliter", "millimole-per-liter", "mole", - "part-per-million", "percent", "permille", + "permillion", "permyriad", - "liter-per-100kilometers", + "liter-per-100-kilometer", "liter-per-kilometer", "mile-per-gallon", "mile-per-gallon-imperial", @@ -535,9 +537,9 @@ static const char * const gSubTypes[] = { "solar-mass", "stone", "ton", - "base", - "percent", - "permille", + "", // TODO(ICU-21076): manual edit of what should have been generated by Java. + "percent", // TODO(ICU-21076): regenerate, deal with duplication. + "permille", // TODO(ICU-21076): regenerate, deal with duplication. "gigawatt", "horsepower", "kilowatt", @@ -547,13 +549,13 @@ static const char * const gSubTypes[] = { "atmosphere", "bar", "hectopascal", - "inch-hg", + "inch-ofhg", "kilopascal", "megapascal", "millibar", - "millimeter-of-mercury", + "millimeter-ofhg", "pascal", - "pound-per-square-inch", + "pound-force-per-square-inch", "kilometer-per-hour", "knot", "meter-per-second", @@ -563,7 +565,7 @@ static const char * const gSubTypes[] = { "generic", "kelvin", "newton-meter", - "pound-foot", + "pound-force-foot", "acre-foot", "barrel", "bushel", @@ -780,27 +782,27 @@ MeasureUnit MeasureUnit::getMole() { } MeasureUnit *MeasureUnit::createPartPerMillion(UErrorCode &status) { - return MeasureUnit::create(3, 4, status); + return MeasureUnit::create(3, 6, status); } MeasureUnit MeasureUnit::getPartPerMillion() { - return MeasureUnit(3, 4); + return MeasureUnit(3, 6); } MeasureUnit *MeasureUnit::createPercent(UErrorCode &status) { - return MeasureUnit::create(3, 5, status); + return MeasureUnit::create(3, 4, status); } MeasureUnit MeasureUnit::getPercent() { - return MeasureUnit(3, 5); + return MeasureUnit(3, 4); } MeasureUnit *MeasureUnit::createPermille(UErrorCode &status) { - return MeasureUnit::create(3, 6, status); + return MeasureUnit::create(3, 5, status); } MeasureUnit MeasureUnit::getPermille() { - return MeasureUnit(3, 6); + return MeasureUnit(3, 5); } MeasureUnit *MeasureUnit::createPermyriad(UErrorCode &status) { @@ -1990,10 +1992,10 @@ MeasureUnit MeasureUnit::getTeaspoon() { // End generated code static int32_t binarySearch( - const char * const * array, int32_t start, int32_t end, const char * key) { + const char * const * array, int32_t start, int32_t end, StringPiece key) { while (start < end) { int32_t mid = (start + end) / 2; - int32_t cmp = uprv_strcmp(array[mid], key); + int32_t cmp = StringPiece(array[mid]).compare(key); if (cmp < 0) { start = mid + 1; continue; @@ -2006,24 +2008,62 @@ static int32_t binarySearch( return -1; } -MeasureUnit::MeasureUnit() { - fCurrency[0] = 0; - fTypeId = kBaseTypeIdx; - fSubTypeId = kBaseSubTypeIdx; +MeasureUnit::MeasureUnit() : MeasureUnit(kBaseTypeIdx, kBaseSubTypeIdx) { +} + +MeasureUnit::MeasureUnit(int32_t typeId, int32_t subTypeId) + : fImpl(nullptr), fSubTypeId(subTypeId), fTypeId(typeId) { } MeasureUnit::MeasureUnit(const MeasureUnit &other) - : fTypeId(other.fTypeId), fSubTypeId(other.fSubTypeId) { - uprv_strcpy(fCurrency, other.fCurrency); + : fImpl(nullptr) { + *this = other; +} + +MeasureUnit::MeasureUnit(MeasureUnit &&other) noexcept + : fImpl(other.fImpl), + fSubTypeId(other.fSubTypeId), + fTypeId(other.fTypeId) { + other.fImpl = nullptr; +} + +MeasureUnit::MeasureUnit(MeasureUnitImpl&& impl) + : fImpl(nullptr), fSubTypeId(-1), fTypeId(-1) { + if (!findBySubType(impl.identifier.toStringPiece(), this)) { + fImpl = new MeasureUnitImpl(std::move(impl)); + } } MeasureUnit &MeasureUnit::operator=(const MeasureUnit &other) { if (this == &other) { return *this; } + delete fImpl; + if (other.fImpl) { + ErrorCode localStatus; + fImpl = new MeasureUnitImpl(other.fImpl->copy(localStatus)); + if (!fImpl || localStatus.isFailure()) { + // Unrecoverable allocation error; set to the default unit + *this = MeasureUnit(); + return *this; + } + } else { + fImpl = nullptr; + } + fTypeId = other.fTypeId; + fSubTypeId = other.fSubTypeId; + return *this; +} + +MeasureUnit &MeasureUnit::operator=(MeasureUnit &&other) noexcept { + if (this == &other) { + return *this; + } + delete fImpl; + fImpl = other.fImpl; + other.fImpl = nullptr; fTypeId = other.fTypeId; fSubTypeId = other.fSubTypeId; - uprv_strcpy(fCurrency, other.fCurrency); return *this; } @@ -2032,14 +2072,28 @@ MeasureUnit *MeasureUnit::clone() const { } MeasureUnit::~MeasureUnit() { + delete fImpl; + fImpl = nullptr; } const char *MeasureUnit::getType() const { + // We have a type & subtype only if fTypeId is present. + if (fTypeId == -1) { + return ""; + } return gTypes[fTypeId]; } const char *MeasureUnit::getSubtype() const { - return fCurrency[0] == 0 ? gSubTypes[getOffset()] : fCurrency; + // We have a type & subtype only if fTypeId is present. + if (fTypeId == -1) { + return ""; + } + return getIdentifier(); +} + +const char *MeasureUnit::getIdentifier() const { + return fImpl ? fImpl->identifier.data() : gSubTypes[getOffset()]; } UBool MeasureUnit::operator==(const UObject& other) const { @@ -2050,10 +2104,7 @@ UBool MeasureUnit::operator==(const UObject& other) const { return FALSE; } const MeasureUnit &rhs = static_cast(other); - return ( - fTypeId == rhs.fTypeId - && fSubTypeId == rhs.fSubTypeId - && uprv_strcmp(fCurrency, rhs.fCurrency) == 0); + return uprv_strcmp(getIdentifier(), rhs.getIdentifier()) == 0; } int32_t MeasureUnit::getIndex() const { @@ -2138,10 +2189,29 @@ int32_t MeasureUnit::internalGetIndexForTypeAndSubtype(const char *type, const c return gIndexes[t] + st - gOffsets[t]; } +bool MeasureUnit::findBySubType(StringPiece subType, MeasureUnit* output) { + for (int32_t t = 0; t < UPRV_LENGTHOF(gOffsets) - 1; t++) { + // Skip currency units + if (gIndexes[t] == gIndexes[t + 1]) { + continue; + } + int32_t st = binarySearch(gSubTypes, gOffsets[t], gOffsets[t + 1], subType); + if (st >= 0) { + output->setTo(t, st - gOffsets[t]); + return true; + } + } + return false; +} + MeasureUnit MeasureUnit::resolveUnitPerUnit( const MeasureUnit &unit, const MeasureUnit &perUnit, bool* isResolved) { int32_t unitOffset = unit.getOffset(); int32_t perUnitOffset = perUnit.getOffset(); + if (unitOffset == -1 || perUnitOffset == -1) { + *isResolved = false; + return MeasureUnit(); + } // binary search for (unitOffset, perUnitOffset) int32_t start = 0; @@ -2189,18 +2259,24 @@ void MeasureUnit::initTime(const char *timeId) { fSubTypeId = result - gOffsets[fTypeId]; } -void MeasureUnit::initCurrency(const char *isoCurrency) { +void MeasureUnit::initCurrency(StringPiece isoCurrency) { int32_t result = binarySearch(gTypes, 0, UPRV_LENGTHOF(gTypes), "currency"); U_ASSERT(result != -1); fTypeId = result; result = binarySearch( gSubTypes, gOffsets[fTypeId], gOffsets[fTypeId + 1], isoCurrency); - if (result != -1) { - fSubTypeId = result - gOffsets[fTypeId]; - } else { - uprv_strncpy(fCurrency, isoCurrency, UPRV_LENGTHOF(fCurrency)); - fCurrency[3] = 0; + if (result == -1) { + fImpl = new MeasureUnitImpl(MeasureUnitImpl::forCurrencyCode(isoCurrency)); + if (fImpl) { + fSubTypeId = -1; + return; + } + // malloc error: fall back to the undefined currency + result = binarySearch( + gSubTypes, gOffsets[fTypeId], gOffsets[fTypeId + 1], kDefaultCurrency8); + U_ASSERT(result != -1); } + fSubTypeId = result - gOffsets[fTypeId]; } void MeasureUnit::initNoUnit(const char *subtype) { @@ -2215,10 +2291,14 @@ void MeasureUnit::initNoUnit(const char *subtype) { void MeasureUnit::setTo(int32_t typeId, int32_t subTypeId) { fTypeId = typeId; fSubTypeId = subTypeId; - fCurrency[0] = 0; + delete fImpl; + fImpl = nullptr; } int32_t MeasureUnit::getOffset() const { + if (fTypeId < 0 || fSubTypeId < 0) { + return -1; + } return gOffsets[fTypeId] + fSubTypeId; } diff --git a/deps/icu-small/source/i18n/measunit_extra.cpp b/deps/icu-small/source/i18n/measunit_extra.cpp new file mode 100644 index 00000000000000..aeb60017a18fce --- /dev/null +++ b/deps/icu-small/source/i18n/measunit_extra.cpp @@ -0,0 +1,893 @@ +// © 2020 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +// Extra functions for MeasureUnit not needed for all clients. +// Separate .o file so that it can be removed for modularity. + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +// Allow implicit conversion from char16_t* to UnicodeString for this file: +// Helpful in toString methods and elsewhere. +#define UNISTR_FROM_STRING_EXPLICIT + +#include +#include "cstring.h" +#include "measunit_impl.h" +#include "uarrsort.h" +#include "uassert.h" +#include "ucln_in.h" +#include "umutex.h" +#include "unicode/errorcode.h" +#include "unicode/localpointer.h" +#include "unicode/measunit.h" +#include "unicode/ucharstrie.h" +#include "unicode/ucharstriebuilder.h" + +#include "cstr.h" + +U_NAMESPACE_BEGIN + + +namespace { + +// TODO: Propose a new error code for this? +constexpr UErrorCode kUnitIdentifierSyntaxError = U_ILLEGAL_ARGUMENT_ERROR; + +// Trie value offset for SI Prefixes. This is big enough to ensure we only +// insert positive integers into the trie. +constexpr int32_t kSIPrefixOffset = 64; + +// Trie value offset for compound parts, e.g. "-per-", "-", "-and-". +constexpr int32_t kCompoundPartOffset = 128; + +enum CompoundPart { + // Represents "-per-" + COMPOUND_PART_PER = kCompoundPartOffset, + // Represents "-" + COMPOUND_PART_TIMES, + // Represents "-and-" + COMPOUND_PART_AND, +}; + +// Trie value offset for "per-". +constexpr int32_t kInitialCompoundPartOffset = 192; + +enum InitialCompoundPart { + // Represents "per-", the only compound part that can appear at the start of + // an identifier. + INITIAL_COMPOUND_PART_PER = kInitialCompoundPartOffset, +}; + +// Trie value offset for powers like "square-", "cubic-", "p2-" etc. +constexpr int32_t kPowerPartOffset = 256; + +enum PowerPart { + POWER_PART_P2 = kPowerPartOffset + 2, + POWER_PART_P3, + POWER_PART_P4, + POWER_PART_P5, + POWER_PART_P6, + POWER_PART_P7, + POWER_PART_P8, + POWER_PART_P9, + POWER_PART_P10, + POWER_PART_P11, + POWER_PART_P12, + POWER_PART_P13, + POWER_PART_P14, + POWER_PART_P15, +}; + +// Trie value offset for simple units, e.g. "gram", "nautical-mile", +// "fluid-ounce-imperial". +constexpr int32_t kSimpleUnitOffset = 512; + +const struct SIPrefixStrings { + const char* const string; + UMeasureSIPrefix value; +} gSIPrefixStrings[] = { + { "yotta", UMEASURE_SI_PREFIX_YOTTA }, + { "zetta", UMEASURE_SI_PREFIX_ZETTA }, + { "exa", UMEASURE_SI_PREFIX_EXA }, + { "peta", UMEASURE_SI_PREFIX_PETA }, + { "tera", UMEASURE_SI_PREFIX_TERA }, + { "giga", UMEASURE_SI_PREFIX_GIGA }, + { "mega", UMEASURE_SI_PREFIX_MEGA }, + { "kilo", UMEASURE_SI_PREFIX_KILO }, + { "hecto", UMEASURE_SI_PREFIX_HECTO }, + { "deka", UMEASURE_SI_PREFIX_DEKA }, + { "deci", UMEASURE_SI_PREFIX_DECI }, + { "centi", UMEASURE_SI_PREFIX_CENTI }, + { "milli", UMEASURE_SI_PREFIX_MILLI }, + { "micro", UMEASURE_SI_PREFIX_MICRO }, + { "nano", UMEASURE_SI_PREFIX_NANO }, + { "pico", UMEASURE_SI_PREFIX_PICO }, + { "femto", UMEASURE_SI_PREFIX_FEMTO }, + { "atto", UMEASURE_SI_PREFIX_ATTO }, + { "zepto", UMEASURE_SI_PREFIX_ZEPTO }, + { "yocto", UMEASURE_SI_PREFIX_YOCTO }, +}; + +// TODO(ICU-21059): Get this list from data +const char16_t* const gSimpleUnits[] = { + u"candela", + u"carat", + u"gram", + u"ounce", + u"ounce-troy", + u"pound", + u"kilogram", + u"stone", + u"ton", + u"metric-ton", + u"earth-mass", + u"solar-mass", + u"point", + u"inch", + u"foot", + u"yard", + u"meter", + u"fathom", + u"furlong", + u"mile", + u"nautical-mile", + u"mile-scandinavian", + u"100-kilometer", + u"earth-radius", + u"solar-radius", + u"astronomical-unit", + u"light-year", + u"parsec", + u"second", + u"minute", + u"hour", + u"day", + u"day-person", + u"week", + u"week-person", + u"month", + u"month-person", + u"year", + u"year-person", + u"decade", + u"century", + u"ampere", + u"fahrenheit", + u"kelvin", + u"celsius", + u"arc-second", + u"arc-minute", + u"degree", + u"radian", + u"revolution", + u"item", + u"mole", + u"permillion", + u"permyriad", + u"permille", + u"percent", + u"karat", + u"portion", + u"bit", + u"byte", + u"dot", + u"pixel", + u"em", + u"hertz", + u"newton", + u"pound-force", + u"pascal", + u"bar", + u"atmosphere", + u"ofhg", + u"electronvolt", + u"dalton", + u"joule", + u"calorie", + u"british-thermal-unit", + u"foodcalorie", + u"therm-us", + u"watt", + u"horsepower", + u"solar-luminosity", + u"volt", + u"ohm", + u"dunam", + u"acre", + u"hectare", + u"teaspoon", + u"tablespoon", + u"fluid-ounce-imperial", + u"fluid-ounce", + u"cup", + u"cup-metric", + u"pint", + u"pint-metric", + u"quart", + u"liter", + u"gallon", + u"gallon-imperial", + u"bushel", + u"barrel", + u"knot", + u"g-force", + u"lux", +}; + +icu::UInitOnce gUnitExtrasInitOnce = U_INITONCE_INITIALIZER; + +char16_t* kSerializedUnitExtrasStemTrie = nullptr; + +UBool U_CALLCONV cleanupUnitExtras() { + uprv_free(kSerializedUnitExtrasStemTrie); + kSerializedUnitExtrasStemTrie = nullptr; + gUnitExtrasInitOnce.reset(); + return TRUE; +} + +void U_CALLCONV initUnitExtras(UErrorCode& status) { + ucln_i18n_registerCleanup(UCLN_I18N_UNIT_EXTRAS, cleanupUnitExtras); + + UCharsTrieBuilder b(status); + if (U_FAILURE(status)) { return; } + + // Add SI prefixes + for (const auto& siPrefixInfo : gSIPrefixStrings) { + UnicodeString uSIPrefix(siPrefixInfo.string, -1, US_INV); + b.add(uSIPrefix, siPrefixInfo.value + kSIPrefixOffset, status); + } + if (U_FAILURE(status)) { return; } + + // Add syntax parts (compound, power prefixes) + b.add(u"-per-", COMPOUND_PART_PER, status); + b.add(u"-", COMPOUND_PART_TIMES, status); + b.add(u"-and-", COMPOUND_PART_AND, status); + b.add(u"per-", INITIAL_COMPOUND_PART_PER, status); + b.add(u"square-", POWER_PART_P2, status); + b.add(u"cubic-", POWER_PART_P3, status); + b.add(u"p2-", POWER_PART_P2, status); + b.add(u"p3-", POWER_PART_P3, status); + b.add(u"p4-", POWER_PART_P4, status); + b.add(u"p5-", POWER_PART_P5, status); + b.add(u"p6-", POWER_PART_P6, status); + b.add(u"p7-", POWER_PART_P7, status); + b.add(u"p8-", POWER_PART_P8, status); + b.add(u"p9-", POWER_PART_P9, status); + b.add(u"p10-", POWER_PART_P10, status); + b.add(u"p11-", POWER_PART_P11, status); + b.add(u"p12-", POWER_PART_P12, status); + b.add(u"p13-", POWER_PART_P13, status); + b.add(u"p14-", POWER_PART_P14, status); + b.add(u"p15-", POWER_PART_P15, status); + if (U_FAILURE(status)) { return; } + + // Add sanctioned simple units by offset + int32_t simpleUnitOffset = kSimpleUnitOffset; + for (auto simpleUnit : gSimpleUnits) { + b.add(simpleUnit, simpleUnitOffset++, status); + } + + // Build the CharsTrie + // TODO: Use SLOW or FAST here? + UnicodeString result; + b.buildUnicodeString(USTRINGTRIE_BUILD_FAST, result, status); + if (U_FAILURE(status)) { return; } + + // Copy the result into the global constant pointer + size_t numBytes = result.length() * sizeof(char16_t); + kSerializedUnitExtrasStemTrie = static_cast(uprv_malloc(numBytes)); + uprv_memcpy(kSerializedUnitExtrasStemTrie, result.getBuffer(), numBytes); +} + +class Token { +public: + Token(int32_t match) : fMatch(match) {} + + enum Type { + TYPE_UNDEFINED, + TYPE_SI_PREFIX, + // Token type for "-per-", "-", and "-and-". + TYPE_COMPOUND_PART, + // Token type for "per-". + TYPE_INITIAL_COMPOUND_PART, + TYPE_POWER_PART, + TYPE_SIMPLE_UNIT, + }; + + // Calling getType() is invalid, resulting in an assertion failure, if Token + // value isn't positive. + Type getType() const { + U_ASSERT(fMatch > 0); + if (fMatch < kCompoundPartOffset) { + return TYPE_SI_PREFIX; + } + if (fMatch < kInitialCompoundPartOffset) { + return TYPE_COMPOUND_PART; + } + if (fMatch < kPowerPartOffset) { + return TYPE_INITIAL_COMPOUND_PART; + } + if (fMatch < kSimpleUnitOffset) { + return TYPE_POWER_PART; + } + return TYPE_SIMPLE_UNIT; + } + + UMeasureSIPrefix getSIPrefix() const { + U_ASSERT(getType() == TYPE_SI_PREFIX); + return static_cast(fMatch - kSIPrefixOffset); + } + + // Valid only for tokens with type TYPE_COMPOUND_PART. + int32_t getMatch() const { + U_ASSERT(getType() == TYPE_COMPOUND_PART); + return fMatch; + } + + int32_t getInitialCompoundPart() const { + // Even if there is only one InitialCompoundPart value, we have this + // function for the simplicity of code consistency. + U_ASSERT(getType() == TYPE_INITIAL_COMPOUND_PART); + // Defensive: if this assert fails, code using this function also needs + // to change. + U_ASSERT(fMatch == INITIAL_COMPOUND_PART_PER); + return fMatch; + } + + int8_t getPower() const { + U_ASSERT(getType() == TYPE_POWER_PART); + return static_cast(fMatch - kPowerPartOffset); + } + + int32_t getSimpleUnitIndex() const { + U_ASSERT(getType() == TYPE_SIMPLE_UNIT); + return fMatch - kSimpleUnitOffset; + } + +private: + int32_t fMatch; +}; + +class Parser { +public: + /** + * Factory function for parsing the given identifier. + * + * @param source The identifier to parse. This function does not make a copy + * of source: the underlying string that source points at, must outlive the + * parser. + * @param status ICU error code. + */ + static Parser from(StringPiece source, UErrorCode& status) { + if (U_FAILURE(status)) { + return Parser(); + } + umtx_initOnce(gUnitExtrasInitOnce, &initUnitExtras, status); + if (U_FAILURE(status)) { + return Parser(); + } + return Parser(source); + } + + MeasureUnitImpl parse(UErrorCode& status) { + MeasureUnitImpl result; + parseImpl(result, status); + return result; + } + +private: + // Tracks parser progress: the offset into fSource. + int32_t fIndex = 0; + + // Since we're not owning this memory, whatever is passed to the constructor + // should live longer than this Parser - and the parser shouldn't return any + // references to that string. + StringPiece fSource; + UCharsTrie fTrie; + + // Set to true when we've seen a "-per-" or a "per-", after which all units + // are in the denominator. Until we find an "-and-", at which point the + // identifier is invalid pending TODO(CLDR-13700). + bool fAfterPer = false; + + Parser() : fSource(""), fTrie(u"") {} + + Parser(StringPiece source) + : fSource(source), fTrie(kSerializedUnitExtrasStemTrie) {} + + inline bool hasNext() const { + return fIndex < fSource.length(); + } + + // Returns the next Token parsed from fSource, advancing fIndex to the end + // of that token in fSource. In case of U_FAILURE(status), the token + // returned will cause an abort if getType() is called on it. + Token nextToken(UErrorCode& status) { + fTrie.reset(); + int32_t match = -1; + // Saves the position in the fSource string for the end of the most + // recent matching token. + int32_t previ = -1; + // Find the longest token that matches a value in the trie: + while (fIndex < fSource.length()) { + auto result = fTrie.next(fSource.data()[fIndex++]); + if (result == USTRINGTRIE_NO_MATCH) { + break; + } else if (result == USTRINGTRIE_NO_VALUE) { + continue; + } + U_ASSERT(USTRINGTRIE_HAS_VALUE(result)); + match = fTrie.getValue(); + previ = fIndex; + if (result == USTRINGTRIE_FINAL_VALUE) { + break; + } + U_ASSERT(result == USTRINGTRIE_INTERMEDIATE_VALUE); + // continue; + } + + if (match < 0) { + status = kUnitIdentifierSyntaxError; + } else { + fIndex = previ; + } + return Token(match); + } + + /** + * Returns the next "single unit" via result. + * + * If a "-per-" was parsed, the result will have appropriate negative + * dimensionality. + * + * Returns an error if we parse both compound units and "-and-", since mixed + * compound units are not yet supported - TODO(CLDR-13700). + * + * @param result Will be overwritten by the result, if status shows success. + * @param sawAnd If an "-and-" was parsed prior to finding the "single + * unit", sawAnd is set to true. If not, it is left as is. + * @param status ICU error code. + */ + void nextSingleUnit(SingleUnitImpl& result, bool& sawAnd, UErrorCode& status) { + if (U_FAILURE(status)) { + return; + } + + // state: + // 0 = no tokens seen yet (will accept power, SI prefix, or simple unit) + // 1 = power token seen (will not accept another power token) + // 2 = SI prefix token seen (will not accept a power or SI prefix token) + int32_t state = 0; + + bool atStart = fIndex == 0; + Token token = nextToken(status); + if (U_FAILURE(status)) { return; } + + if (atStart) { + // Identifiers optionally start with "per-". + if (token.getType() == Token::TYPE_INITIAL_COMPOUND_PART) { + U_ASSERT(token.getInitialCompoundPart() == INITIAL_COMPOUND_PART_PER); + fAfterPer = true; + result.dimensionality = -1; + + token = nextToken(status); + if (U_FAILURE(status)) { return; } + } + } else { + // All other SingleUnit's are separated from previous SingleUnit's + // via a compound part: + if (token.getType() != Token::TYPE_COMPOUND_PART) { + status = kUnitIdentifierSyntaxError; + return; + } + + switch (token.getMatch()) { + case COMPOUND_PART_PER: + if (sawAnd) { + // Mixed compound units not yet supported, + // TODO(CLDR-13700). + status = kUnitIdentifierSyntaxError; + return; + } + fAfterPer = true; + result.dimensionality = -1; + break; + + case COMPOUND_PART_TIMES: + if (fAfterPer) { + result.dimensionality = -1; + } + break; + + case COMPOUND_PART_AND: + if (fAfterPer) { + // Can't start with "-and-", and mixed compound units + // not yet supported, TODO(CLDR-13700). + status = kUnitIdentifierSyntaxError; + return; + } + sawAnd = true; + break; + } + + token = nextToken(status); + if (U_FAILURE(status)) { return; } + } + + // Read tokens until we have a complete SingleUnit or we reach the end. + while (true) { + switch (token.getType()) { + case Token::TYPE_POWER_PART: + if (state > 0) { + status = kUnitIdentifierSyntaxError; + return; + } + result.dimensionality *= token.getPower(); + state = 1; + break; + + case Token::TYPE_SI_PREFIX: + if (state > 1) { + status = kUnitIdentifierSyntaxError; + return; + } + result.siPrefix = token.getSIPrefix(); + state = 2; + break; + + case Token::TYPE_SIMPLE_UNIT: + result.index = token.getSimpleUnitIndex(); + return; + + default: + status = kUnitIdentifierSyntaxError; + return; + } + + if (!hasNext()) { + // We ran out of tokens before finding a complete single unit. + status = kUnitIdentifierSyntaxError; + return; + } + token = nextToken(status); + if (U_FAILURE(status)) { + return; + } + } + } + + /// @param result is modified, not overridden. Caller must pass in a + /// default-constructed (empty) MeasureUnitImpl instance. + void parseImpl(MeasureUnitImpl& result, UErrorCode& status) { + if (U_FAILURE(status)) { + return; + } + if (fSource.empty()) { + // The dimenionless unit: nothing to parse. leave result as is. + return; + } + int32_t unitNum = 0; + while (hasNext()) { + bool sawAnd = false; + SingleUnitImpl singleUnit; + nextSingleUnit(singleUnit, sawAnd, status); + if (U_FAILURE(status)) { + return; + } + U_ASSERT(!singleUnit.isDimensionless()); + bool added = result.append(singleUnit, status); + if (sawAnd && !added) { + // Two similar units are not allowed in a mixed unit + status = kUnitIdentifierSyntaxError; + return; + } + if ((++unitNum) >= 2) { + // nextSingleUnit fails appropriately for "per" and "and" in the + // same identifier. It doesn't fail for other compound units + // (COMPOUND_PART_TIMES). Consequently we take care of that + // here. + UMeasureUnitComplexity complexity = + sawAnd ? UMEASURE_UNIT_MIXED : UMEASURE_UNIT_COMPOUND; + if (unitNum == 2) { + U_ASSERT(result.complexity == UMEASURE_UNIT_SINGLE); + result.complexity = complexity; + } else if (result.complexity != complexity) { + // Can't have mixed compound units + status = kUnitIdentifierSyntaxError; + return; + } + } + } + } +}; + +int32_t U_CALLCONV +compareSingleUnits(const void* /*context*/, const void* left, const void* right) { + auto realLeft = static_cast(left); + auto realRight = static_cast(right); + return (*realLeft)->compareTo(**realRight); +} + +/** + * Generate the identifier string for a single unit in place. + * + * Does not support the dimensionless SingleUnitImpl: calling serializeSingle + * with the dimensionless unit results in an U_INTERNAL_PROGRAM_ERROR. + * + * @param first If singleUnit is part of a compound unit, and not its first + * single unit, set this to false. Otherwise: set to true. + */ +void serializeSingle(const SingleUnitImpl& singleUnit, bool first, CharString& output, UErrorCode& status) { + if (first && singleUnit.dimensionality < 0) { + // Essentially the "unary per". For compound units with a numerator, the + // caller takes care of the "binary per". + output.append("per-", status); + } + + if (singleUnit.isDimensionless()) { + status = U_INTERNAL_PROGRAM_ERROR; + return; + } + int8_t posPower = std::abs(singleUnit.dimensionality); + if (posPower == 0) { + status = U_INTERNAL_PROGRAM_ERROR; + } else if (posPower == 1) { + // no-op + } else if (posPower == 2) { + output.append("square-", status); + } else if (posPower == 3) { + output.append("cubic-", status); + } else if (posPower < 10) { + output.append('p', status); + output.append(posPower + '0', status); + output.append('-', status); + } else if (posPower <= 15) { + output.append("p1", status); + output.append('0' + (posPower % 10), status); + output.append('-', status); + } else { + status = kUnitIdentifierSyntaxError; + } + if (U_FAILURE(status)) { + return; + } + + if (singleUnit.siPrefix != UMEASURE_SI_PREFIX_ONE) { + for (const auto& siPrefixInfo : gSIPrefixStrings) { + if (siPrefixInfo.value == singleUnit.siPrefix) { + output.append(siPrefixInfo.string, status); + break; + } + } + } + if (U_FAILURE(status)) { + return; + } + + output.appendInvariantChars(gSimpleUnits[singleUnit.index], status); +} + +/** + * Normalize a MeasureUnitImpl and generate the identifier string in place. + */ +void serialize(MeasureUnitImpl& impl, UErrorCode& status) { + if (U_FAILURE(status)) { + return; + } + U_ASSERT(impl.identifier.isEmpty()); + if (impl.units.length() == 0) { + // Dimensionless, constructed by the default constructor: no appending + // to impl.identifier, we wish it to contain the zero-length string. + return; + } + if (impl.complexity == UMEASURE_UNIT_COMPOUND) { + // Note: don't sort a MIXED unit + uprv_sortArray( + impl.units.getAlias(), + impl.units.length(), + sizeof(impl.units[0]), + compareSingleUnits, + nullptr, + false, + &status); + if (U_FAILURE(status)) { + return; + } + } + serializeSingle(*impl.units[0], true, impl.identifier, status); + if (impl.units.length() == 1) { + return; + } + for (int32_t i = 1; i < impl.units.length(); i++) { + const SingleUnitImpl& prev = *impl.units[i-1]; + const SingleUnitImpl& curr = *impl.units[i]; + if (impl.complexity == UMEASURE_UNIT_MIXED) { + impl.identifier.append("-and-", status); + serializeSingle(curr, true, impl.identifier, status); + } else { + if (prev.dimensionality > 0 && curr.dimensionality < 0) { + impl.identifier.append("-per-", status); + } else { + impl.identifier.append('-', status); + } + serializeSingle(curr, false, impl.identifier, status); + } + } + +} + +/** + * Appends a SingleUnitImpl to a MeasureUnitImpl. + * + * @return true if a new item was added. If unit is the dimensionless unit, it + * is never added: the return value will always be false. + */ +bool appendImpl(MeasureUnitImpl& impl, const SingleUnitImpl& unit, UErrorCode& status) { + if (unit.isDimensionless()) { + // We don't append dimensionless units. + return false; + } + // Find a similar unit that already exists, to attempt to coalesce + SingleUnitImpl* oldUnit = nullptr; + for (int32_t i = 0; i < impl.units.length(); i++) { + auto* candidate = impl.units[i]; + if (candidate->isCompatibleWith(unit)) { + oldUnit = candidate; + } + } + if (oldUnit) { + // Both dimensionalities will be positive, or both will be negative, by + // virtue of isCompatibleWith(). + oldUnit->dimensionality += unit.dimensionality; + } else { + SingleUnitImpl* destination = impl.units.emplaceBack(); + if (!destination) { + status = U_MEMORY_ALLOCATION_ERROR; + return false; + } + *destination = unit; + } + return (oldUnit == nullptr); +} + +} // namespace + + +SingleUnitImpl SingleUnitImpl::forMeasureUnit(const MeasureUnit& measureUnit, UErrorCode& status) { + MeasureUnitImpl temp; + const MeasureUnitImpl& impl = MeasureUnitImpl::forMeasureUnit(measureUnit, temp, status); + if (U_FAILURE(status)) { + return {}; + } + if (impl.units.length() == 0) { + return {}; + } + if (impl.units.length() == 1) { + return *impl.units[0]; + } + status = U_ILLEGAL_ARGUMENT_ERROR; + return {}; +} + +MeasureUnit SingleUnitImpl::build(UErrorCode& status) const { + MeasureUnitImpl temp; + temp.append(*this, status); + return std::move(temp).build(status); +} + + +MeasureUnitImpl MeasureUnitImpl::forIdentifier(StringPiece identifier, UErrorCode& status) { + return Parser::from(identifier, status).parse(status); +} + +const MeasureUnitImpl& MeasureUnitImpl::forMeasureUnit( + const MeasureUnit& measureUnit, MeasureUnitImpl& memory, UErrorCode& status) { + if (measureUnit.fImpl) { + return *measureUnit.fImpl; + } else { + memory = Parser::from(measureUnit.getIdentifier(), status).parse(status); + return memory; + } +} + +MeasureUnitImpl MeasureUnitImpl::forMeasureUnitMaybeCopy( + const MeasureUnit& measureUnit, UErrorCode& status) { + if (measureUnit.fImpl) { + return measureUnit.fImpl->copy(status); + } else { + return Parser::from(measureUnit.getIdentifier(), status).parse(status); + } +} + +void MeasureUnitImpl::takeReciprocal(UErrorCode& /*status*/) { + identifier.clear(); + for (int32_t i = 0; i < units.length(); i++) { + units[i]->dimensionality *= -1; + } +} + +bool MeasureUnitImpl::append(const SingleUnitImpl& singleUnit, UErrorCode& status) { + identifier.clear(); + return appendImpl(*this, singleUnit, status); +} + +MeasureUnit MeasureUnitImpl::build(UErrorCode& status) && { + serialize(*this, status); + return MeasureUnit(std::move(*this)); +} + + +MeasureUnit MeasureUnit::forIdentifier(StringPiece identifier, UErrorCode& status) { + return Parser::from(identifier, status).parse(status).build(status); +} + +UMeasureUnitComplexity MeasureUnit::getComplexity(UErrorCode& status) const { + MeasureUnitImpl temp; + return MeasureUnitImpl::forMeasureUnit(*this, temp, status).complexity; +} + +UMeasureSIPrefix MeasureUnit::getSIPrefix(UErrorCode& status) const { + return SingleUnitImpl::forMeasureUnit(*this, status).siPrefix; +} + +MeasureUnit MeasureUnit::withSIPrefix(UMeasureSIPrefix prefix, UErrorCode& status) const { + SingleUnitImpl singleUnit = SingleUnitImpl::forMeasureUnit(*this, status); + singleUnit.siPrefix = prefix; + return singleUnit.build(status); +} + +int32_t MeasureUnit::getDimensionality(UErrorCode& status) const { + SingleUnitImpl singleUnit = SingleUnitImpl::forMeasureUnit(*this, status); + if (U_FAILURE(status)) { return 0; } + if (singleUnit.isDimensionless()) { + return 0; + } + return singleUnit.dimensionality; +} + +MeasureUnit MeasureUnit::withDimensionality(int32_t dimensionality, UErrorCode& status) const { + SingleUnitImpl singleUnit = SingleUnitImpl::forMeasureUnit(*this, status); + singleUnit.dimensionality = dimensionality; + return singleUnit.build(status); +} + +MeasureUnit MeasureUnit::reciprocal(UErrorCode& status) const { + MeasureUnitImpl impl = MeasureUnitImpl::forMeasureUnitMaybeCopy(*this, status); + impl.takeReciprocal(status); + return std::move(impl).build(status); +} + +MeasureUnit MeasureUnit::product(const MeasureUnit& other, UErrorCode& status) const { + MeasureUnitImpl impl = MeasureUnitImpl::forMeasureUnitMaybeCopy(*this, status); + MeasureUnitImpl temp; + const MeasureUnitImpl& otherImpl = MeasureUnitImpl::forMeasureUnit(other, temp, status); + if (impl.complexity == UMEASURE_UNIT_MIXED || otherImpl.complexity == UMEASURE_UNIT_MIXED) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return {}; + } + for (int32_t i = 0; i < otherImpl.units.length(); i++) { + impl.append(*otherImpl.units[i], status); + } + if (impl.units.length() > 1) { + impl.complexity = UMEASURE_UNIT_COMPOUND; + } + return std::move(impl).build(status); +} + +LocalArray MeasureUnit::splitToSingleUnits(int32_t& outCount, UErrorCode& status) const { + MeasureUnitImpl temp; + const MeasureUnitImpl& impl = MeasureUnitImpl::forMeasureUnit(*this, temp, status); + outCount = impl.units.length(); + MeasureUnit* arr = new MeasureUnit[outCount]; + for (int32_t i = 0; i < outCount; i++) { + arr[i] = impl.units[i]->build(status); + } + return LocalArray(arr, status); +} + + +U_NAMESPACE_END + +#endif /* !UNCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/measunit_impl.h b/deps/icu-small/source/i18n/measunit_impl.h new file mode 100644 index 00000000000000..c886d3c29a38b2 --- /dev/null +++ b/deps/icu-small/source/i18n/measunit_impl.h @@ -0,0 +1,213 @@ +// © 2020 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#ifndef __MEASUNIT_IMPL_H__ +#define __MEASUNIT_IMPL_H__ + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +#include "unicode/measunit.h" +#include "cmemory.h" +#include "charstr.h" + +U_NAMESPACE_BEGIN + + +static const char16_t kDefaultCurrency[] = u"XXX"; +static const char kDefaultCurrency8[] = "XXX"; + + +/** + * A struct representing a single unit (optional SI prefix and dimensionality). + */ +struct SingleUnitImpl : public UMemory { + /** + * Gets a single unit from the MeasureUnit. If there are multiple single units, sets an error + * code and returns the base dimensionless unit. Parses if necessary. + */ + static SingleUnitImpl forMeasureUnit(const MeasureUnit& measureUnit, UErrorCode& status); + + /** Transform this SingleUnitImpl into a MeasureUnit, simplifying if possible. */ + MeasureUnit build(UErrorCode& status) const; + + /** + * Compare this SingleUnitImpl to another SingleUnitImpl for the sake of + * sorting and coalescing. + * + * Takes the sign of dimensionality into account, but not the absolute + * value: per-meter is not considered the same as meter, but meter is + * considered the same as square-meter. + * + * The dimensionless unit generally does not get compared, but if it did, it + * would sort before other units by virtue of index being < 0 and + * dimensionality not being negative. + */ + int32_t compareTo(const SingleUnitImpl& other) const { + if (dimensionality < 0 && other.dimensionality > 0) { + // Positive dimensions first + return 1; + } + if (dimensionality > 0 && other.dimensionality < 0) { + return -1; + } + if (index < other.index) { + return -1; + } + if (index > other.index) { + return 1; + } + if (siPrefix < other.siPrefix) { + return -1; + } + if (siPrefix > other.siPrefix) { + return 1; + } + return 0; + } + + /** + * Return whether this SingleUnitImpl is compatible with another for the purpose of coalescing. + * + * Units with the same base unit and SI prefix should match, except that they must also have + * the same dimensionality sign, such that we don't merge numerator and denominator. + */ + bool isCompatibleWith(const SingleUnitImpl& other) const { + return (compareTo(other) == 0); + } + + /** + * Returns true if this unit is the "dimensionless base unit", as produced + * by the MeasureUnit() default constructor. (This does not include the + * likes of concentrations or angles.) + */ + bool isDimensionless() const { + return index == -1; + } + + /** + * Simple unit index, unique for every simple unit, -1 for the dimensionless + * unit. This is an index into a string list in measunit_extra.cpp. + * + * The default value is -1, meaning the dimensionless unit: + * isDimensionless() will return true, until index is changed. + */ + int32_t index = -1; + + /** + * SI prefix. + * + * This is ignored for the dimensionless unit. + */ + UMeasureSIPrefix siPrefix = UMEASURE_SI_PREFIX_ONE; + + /** + * Dimensionality. + * + * This is meaningless for the dimensionless unit. + */ + int32_t dimensionality = 1; +}; + + +/** + * Internal representation of measurement units. Capable of representing all complexities of units, + * including mixed and compound units. + */ +struct MeasureUnitImpl : public UMemory { + /** Extract the MeasureUnitImpl from a MeasureUnit. */ + static inline const MeasureUnitImpl* get(const MeasureUnit& measureUnit) { + return measureUnit.fImpl; + } + + /** + * Parse a unit identifier into a MeasureUnitImpl. + * + * @param identifier The unit identifier string. + * @param status Set if the identifier string is not valid. + * @return A newly parsed value object. Behaviour of this unit is + * unspecified if an error is returned via status. + */ + static MeasureUnitImpl forIdentifier(StringPiece identifier, UErrorCode& status); + + /** + * Extract the MeasureUnitImpl from a MeasureUnit, or parse if it is not present. + * + * @param measureUnit The source MeasureUnit. + * @param memory A place to write the new MeasureUnitImpl if parsing is required. + * @param status Set if an error occurs. + * @return A reference to either measureUnit.fImpl or memory. + */ + static const MeasureUnitImpl& forMeasureUnit( + const MeasureUnit& measureUnit, MeasureUnitImpl& memory, UErrorCode& status); + + /** + * Extract the MeasureUnitImpl from a MeasureUnit, or parse if it is not present. + * + * @param measureUnit The source MeasureUnit. + * @param status Set if an error occurs. + * @return A value object, either newly parsed or copied from measureUnit. + */ + static MeasureUnitImpl forMeasureUnitMaybeCopy( + const MeasureUnit& measureUnit, UErrorCode& status); + + /** + * Used for currency units. + */ + static inline MeasureUnitImpl forCurrencyCode(StringPiece currencyCode) { + MeasureUnitImpl result; + UErrorCode localStatus = U_ZERO_ERROR; + result.identifier.append(currencyCode, localStatus); + // localStatus is not expected to fail since currencyCode should be 3 chars long + return result; + } + + /** Transform this MeasureUnitImpl into a MeasureUnit, simplifying if possible. */ + MeasureUnit build(UErrorCode& status) &&; + + /** + * Create a copy of this MeasureUnitImpl. Don't use copy constructor to make this explicit. + */ + inline MeasureUnitImpl copy(UErrorCode& status) const { + MeasureUnitImpl result; + result.complexity = complexity; + result.units.appendAll(units, status); + result.identifier.append(identifier, status); + return result; + } + + /** Mutates this MeasureUnitImpl to take the reciprocal. */ + void takeReciprocal(UErrorCode& status); + + /** + * Mutates this MeasureUnitImpl to append a single unit. + * + * @return true if a new item was added. If unit is the dimensionless unit, + * it is never added: the return value will always be false. + */ + bool append(const SingleUnitImpl& singleUnit, UErrorCode& status); + + /** The complexity, either SINGLE, COMPOUND, or MIXED. */ + UMeasureUnitComplexity complexity = UMEASURE_UNIT_SINGLE; + + /** + * The list of simple units. These may be summed or multiplied, based on the + * value of the complexity field. + * + * The "dimensionless" unit (SingleUnitImpl default constructor) must not be + * added to this list. + */ + MaybeStackVector units; + + /** + * The full unit identifier. Owned by the MeasureUnitImpl. Empty if not computed. + */ + CharString identifier; +}; + + +U_NAMESPACE_END + +#endif /* #if !UCONFIG_NO_FORMATTING */ +#endif //__MEASUNIT_IMPL_H__ diff --git a/deps/icu-small/source/i18n/name2uni.cpp b/deps/icu-small/source/i18n/name2uni.cpp index 90bca9d71bef87..b1812178660421 100644 --- a/deps/icu-small/source/i18n/name2uni.cpp +++ b/deps/icu-small/source/i18n/name2uni.cpp @@ -190,6 +190,7 @@ void NameUnicodeTransliterator::handleTransliterate(Replaceable& text, UTransPos } if (uprv_isInvariantUString(name.getBuffer(), len)) { + cbuf[0] = 0; name.extract(0, len, cbuf, maxLen, US_INV); UErrorCode status = U_ZERO_ERROR; diff --git a/deps/icu-small/source/i18n/nounit.cpp b/deps/icu-small/source/i18n/nounit.cpp index 076f76f199c737..1d4aa05506e98d 100644 --- a/deps/icu-small/source/i18n/nounit.cpp +++ b/deps/icu-small/source/i18n/nounit.cpp @@ -11,7 +11,7 @@ U_NAMESPACE_BEGIN UOBJECT_DEFINE_RTTI_IMPLEMENTATION(NoUnit) NoUnit U_EXPORT2 NoUnit::base() { - return NoUnit("base"); + return NoUnit(""); } NoUnit U_EXPORT2 NoUnit::percent() { diff --git a/deps/icu-small/source/i18n/number_affixutils.cpp b/deps/icu-small/source/i18n/number_affixutils.cpp index 1039a84c656124..a74ec2d634799e 100644 --- a/deps/icu-small/source/i18n/number_affixutils.cpp +++ b/deps/icu-small/source/i18n/number_affixutils.cpp @@ -131,25 +131,25 @@ UnicodeString AffixUtils::escape(const UnicodeString &input) { Field AffixUtils::getFieldForType(AffixPatternType type) { switch (type) { case TYPE_MINUS_SIGN: - return UNUM_SIGN_FIELD; + return {UFIELD_CATEGORY_NUMBER, UNUM_SIGN_FIELD}; case TYPE_PLUS_SIGN: - return UNUM_SIGN_FIELD; + return {UFIELD_CATEGORY_NUMBER, UNUM_SIGN_FIELD}; case TYPE_PERCENT: - return UNUM_PERCENT_FIELD; + return {UFIELD_CATEGORY_NUMBER, UNUM_PERCENT_FIELD}; case TYPE_PERMILLE: - return UNUM_PERMILL_FIELD; + return {UFIELD_CATEGORY_NUMBER, UNUM_PERMILL_FIELD}; case TYPE_CURRENCY_SINGLE: - return UNUM_CURRENCY_FIELD; + return {UFIELD_CATEGORY_NUMBER, UNUM_CURRENCY_FIELD}; case TYPE_CURRENCY_DOUBLE: - return UNUM_CURRENCY_FIELD; + return {UFIELD_CATEGORY_NUMBER, UNUM_CURRENCY_FIELD}; case TYPE_CURRENCY_TRIPLE: - return UNUM_CURRENCY_FIELD; + return {UFIELD_CATEGORY_NUMBER, UNUM_CURRENCY_FIELD}; case TYPE_CURRENCY_QUAD: - return UNUM_CURRENCY_FIELD; + return {UFIELD_CATEGORY_NUMBER, UNUM_CURRENCY_FIELD}; case TYPE_CURRENCY_QUINT: - return UNUM_CURRENCY_FIELD; + return {UFIELD_CATEGORY_NUMBER, UNUM_CURRENCY_FIELD}; case TYPE_CURRENCY_OVERFLOW: - return UNUM_CURRENCY_FIELD; + return {UFIELD_CATEGORY_NUMBER, UNUM_CURRENCY_FIELD}; default: UPRV_UNREACHABLE; } @@ -165,7 +165,11 @@ AffixUtils::unescape(const UnicodeString &affixPattern, FormattedStringBuilder & if (U_FAILURE(status)) { return length; } if (tag.type == TYPE_CURRENCY_OVERFLOW) { // Don't go to the provider for this special case - length += output.insertCodePoint(position + length, 0xFFFD, UNUM_CURRENCY_FIELD, status); + length += output.insertCodePoint( + position + length, + 0xFFFD, + {UFIELD_CATEGORY_NUMBER, UNUM_CURRENCY_FIELD}, + status); } else if (tag.type < 0) { length += output.insert( position + length, provider.getSymbol(tag.type), getFieldForType(tag.type), status); @@ -218,7 +222,7 @@ bool AffixUtils::hasCurrencySymbols(const UnicodeString &affixPattern, UErrorCod while (hasNext(tag, affixPattern)) { tag = nextToken(tag, affixPattern, status); if (U_FAILURE(status)) { return false; } - if (tag.type < 0 && getFieldForType(tag.type) == UNUM_CURRENCY_FIELD) { + if (tag.type < 0 && getFieldForType(tag.type) == Field(UFIELD_CATEGORY_NUMBER, UNUM_CURRENCY_FIELD)) { return true; } } diff --git a/deps/icu-small/source/i18n/number_asformat.cpp b/deps/icu-small/source/i18n/number_asformat.cpp index e876174fdce0ee..9d10d1f5580fbe 100644 --- a/deps/icu-small/source/i18n/number_asformat.cpp +++ b/deps/icu-small/source/i18n/number_asformat.cpp @@ -102,4 +102,16 @@ const LocalizedNumberFormatter& LocalizedNumberFormatterAsFormat::getNumberForma return fFormatter; } + +// Definitions of public API methods (put here for dependency disentanglement) + +Format* LocalizedNumberFormatter::toFormat(UErrorCode& status) const { + if (U_FAILURE(status)) { + return nullptr; + } + LocalPointer retval( + new LocalizedNumberFormatterAsFormat(*this, fMacros.locale), status); + return retval.orphan(); +} + #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/number_capi.cpp b/deps/icu-small/source/i18n/number_capi.cpp index 712e0a6631db56..d61440d081e9fb 100644 --- a/deps/icu-small/source/i18n/number_capi.cpp +++ b/deps/icu-small/source/i18n/number_capi.cpp @@ -156,7 +156,7 @@ unumf_resultToString(const UFormattedNumber* uresult, UChar* buffer, int32_t buf return 0; } - return result->fImpl.toTempString(*ec).extract(buffer, bufferCapacity, *ec); + return result->fData.toTempString(*ec).extract(buffer, bufferCapacity, *ec); } U_CAPI UBool U_EXPORT2 @@ -173,7 +173,7 @@ unumf_resultNextFieldPosition(const UFormattedNumber* uresult, UFieldPosition* u fp.setField(ufpos->field); fp.setBeginIndex(ufpos->beginIndex); fp.setEndIndex(ufpos->endIndex); - bool retval = result->fImpl.nextFieldPosition(fp, *ec); + bool retval = result->fData.nextFieldPosition(fp, *ec); ufpos->beginIndex = fp.getBeginIndex(); ufpos->endIndex = fp.getEndIndex(); // NOTE: MSVC sometimes complains when implicitly converting between bool and UBool @@ -192,7 +192,8 @@ unumf_resultGetAllFieldPositions(const UFormattedNumber* uresult, UFieldPosition } auto* fpi = reinterpret_cast(ufpositer); - result->fImpl.getAllFieldPositions(*fpi, *ec); + FieldPositionIteratorHandler fpih(fpi, *ec); + result->fData.getAllFieldPositions(fpih, *ec); } U_CAPI void U_EXPORT2 diff --git a/deps/icu-small/source/i18n/number_compact.cpp b/deps/icu-small/source/i18n/number_compact.cpp index 3d259999d6ce52..e1fef8feb52298 100644 --- a/deps/icu-small/source/i18n/number_compact.cpp +++ b/deps/icu-small/source/i18n/number_compact.cpp @@ -215,19 +215,25 @@ void CompactData::CompactDataSink::put(const char *key, ResourceValue &value, UB /// END OF CompactData.java; BEGIN CompactNotation.java /// /////////////////////////////////////////////////////////// -CompactHandler::CompactHandler(CompactStyle compactStyle, const Locale &locale, const char *nsName, - CompactType compactType, const PluralRules *rules, - MutablePatternModifier *buildReference, const MicroPropsGenerator *parent, - UErrorCode &status) - : rules(rules), parent(parent) { +CompactHandler::CompactHandler( + CompactStyle compactStyle, + const Locale &locale, + const char *nsName, + CompactType compactType, + const PluralRules *rules, + MutablePatternModifier *buildReference, + bool safe, + const MicroPropsGenerator *parent, + UErrorCode &status) + : rules(rules), parent(parent), safe(safe) { data.populate(locale, nsName, compactStyle, compactType, status); - if (buildReference != nullptr) { + if (safe) { // Safe code path precomputeAllModifiers(*buildReference, status); - safe = TRUE; } else { // Unsafe code path - safe = FALSE; + // Store the MutablePatternModifier reference. + unsafePatternModifier = buildReference; } } @@ -260,7 +266,7 @@ void CompactHandler::precomputeAllModifiers(MutablePatternModifier &buildReferen ParsedPatternInfo patternInfo; PatternParser::parseToPatternInfo(UnicodeString(patternString), patternInfo, status); if (U_FAILURE(status)) { return; } - buildReference.setPatternInfo(&patternInfo, UNUM_COMPACT_FIELD); + buildReference.setPatternInfo(&patternInfo, {UFIELD_CATEGORY_NUMBER, UNUM_COMPACT_FIELD}); info.mod = buildReference.createImmutable(status); if (U_FAILURE(status)) { return; } info.patternString = patternString; @@ -274,12 +280,13 @@ void CompactHandler::processQuantity(DecimalQuantity &quantity, MicroProps &micr // Treat zero, NaN, and infinity as if they had magnitude 0 int32_t magnitude; + int32_t multiplier = 0; if (quantity.isZeroish()) { magnitude = 0; micros.rounder.apply(quantity, status); } else { // TODO: Revisit chooseMultiplierAndApply - int32_t multiplier = micros.rounder.chooseMultiplierAndApply(quantity, data, status); + multiplier = micros.rounder.chooseMultiplierAndApply(quantity, data, status); magnitude = quantity.isZeroish() ? 0 : quantity.getMagnitude(); magnitude -= multiplier; } @@ -309,10 +316,18 @@ void CompactHandler::processQuantity(DecimalQuantity &quantity, MicroProps &micr // C++ Note: Use unsafePatternInfo for proper lifecycle. ParsedPatternInfo &patternInfo = const_cast(this)->unsafePatternInfo; PatternParser::parseToPatternInfo(UnicodeString(patternString), patternInfo, status); - static_cast(const_cast(micros.modMiddle)) - ->setPatternInfo(&patternInfo, UNUM_COMPACT_FIELD); + unsafePatternModifier->setPatternInfo( + &unsafePatternInfo, + {UFIELD_CATEGORY_NUMBER, UNUM_COMPACT_FIELD}); + unsafePatternModifier->setNumberProperties(quantity.signum(), StandardPlural::Form::COUNT); + micros.modMiddle = unsafePatternModifier; } + // Change the exponent only after we select appropriate plural form + // for formatting purposes so that we preserve expected formatted + // string behavior. + quantity.adjustExponent(-1 * multiplier); + // We already performed rounding. Do not perform it again. micros.rounder = RoundingImpl::passThrough(); } diff --git a/deps/icu-small/source/i18n/number_compact.h b/deps/icu-small/source/i18n/number_compact.h index dda5f9f9b2dc91..199d39f65911ca 100644 --- a/deps/icu-small/source/i18n/number_compact.h +++ b/deps/icu-small/source/i18n/number_compact.h @@ -56,10 +56,16 @@ struct CompactModInfo { class CompactHandler : public MicroPropsGenerator, public UMemory { public: - CompactHandler(CompactStyle compactStyle, const Locale &locale, const char *nsName, - CompactType compactType, const PluralRules *rules, - MutablePatternModifier *buildReference, const MicroPropsGenerator *parent, - UErrorCode &status); + CompactHandler( + CompactStyle compactStyle, + const Locale &locale, + const char *nsName, + CompactType compactType, + const PluralRules *rules, + MutablePatternModifier *buildReference, + bool safe, + const MicroPropsGenerator *parent, + UErrorCode &status); ~CompactHandler() U_OVERRIDE; @@ -74,6 +80,7 @@ class CompactHandler : public MicroPropsGenerator, public UMemory { int32_t precomputedModsLength = 0; CompactData data; ParsedPatternInfo unsafePatternInfo; + MutablePatternModifier* unsafePatternModifier; UBool safe; /** Used by the safe code path */ diff --git a/deps/icu-small/source/i18n/number_decimalquantity.cpp b/deps/icu-small/source/i18n/number_decimalquantity.cpp index 2c4c2ce7e9931b..5ce9c27cbf4a76 100644 --- a/deps/icu-small/source/i18n/number_decimalquantity.cpp +++ b/deps/icu-small/source/i18n/number_decimalquantity.cpp @@ -120,6 +120,7 @@ void DecimalQuantity::copyFieldsFrom(const DecimalQuantity& other) { origDouble = other.origDouble; origDelta = other.origDelta; isApproximate = other.isApproximate; + exponent = other.exponent; } void DecimalQuantity::clear() { @@ -269,11 +270,21 @@ double DecimalQuantity::getPluralOperand(PluralOperand operand) const { return fractionCount(); case PLURAL_OPERAND_W: return fractionCountWithoutTrailingZeros(); + case PLURAL_OPERAND_E: + return static_cast(getExponent()); default: return std::abs(toDouble()); } } +int32_t DecimalQuantity::getExponent() const { + return exponent; +} + +void DecimalQuantity::adjustExponent(int delta) { + exponent = exponent + delta; +} + bool DecimalQuantity::hasIntegerValue() const { return scale >= 0; } @@ -307,11 +318,13 @@ int8_t DecimalQuantity::getDigit(int32_t magnitude) const { } int32_t DecimalQuantity::fractionCount() const { - return -getLowerDisplayMagnitude(); + int32_t fractionCountWithExponent = -getLowerDisplayMagnitude() - exponent; + return fractionCountWithExponent > 0 ? fractionCountWithExponent : 0; } int32_t DecimalQuantity::fractionCountWithoutTrailingZeros() const { - return -scale > 0 ? -scale : 0; // max(-scale, 0) + int32_t fractionCountWithExponent = -scale - exponent; + return fractionCountWithExponent > 0 ? fractionCountWithExponent : 0; // max(-fractionCountWithExponent, 0) } bool DecimalQuantity::isNegative() const { @@ -319,10 +332,14 @@ bool DecimalQuantity::isNegative() const { } Signum DecimalQuantity::signum() const { - if (isNegative()) { + bool isZero = (isZeroish() && !isInfinite()); + bool isNeg = isNegative(); + if (isZero && isNeg) { + return SIGNUM_NEG_ZERO; + } else if (isZero) { + return SIGNUM_POS_ZERO; + } else if (isNeg) { return SIGNUM_NEG; - } else if (isZeroish() && !isInfinite()) { - return SIGNUM_ZERO; } else { return SIGNUM_POS; } @@ -422,9 +439,6 @@ void DecimalQuantity::_setToDoubleFast(double n) { // TODO: Make a fast path for other types of doubles. if (!std::numeric_limits::is_iec559) { convertToAccurateDouble(); - // Turn off the approximate double flag, since the value is now exact. - isApproximate = false; - origDouble = 0.0; return; } @@ -439,8 +453,14 @@ void DecimalQuantity::_setToDoubleFast(double n) { return; } + if (exponent == -1023 || exponent == 1024) { + // The extreme values of exponent are special; use slow path. + convertToAccurateDouble(); + return; + } + // 3.3219... is log2(10) - auto fracLength = static_cast ((52 - exponent) / 3.32192809489); + auto fracLength = static_cast ((52 - exponent) / 3.32192809488736234787031942948939017586); if (fracLength >= 0) { int32_t i = fracLength; // 1e22 is the largest exact double. @@ -452,7 +472,7 @@ void DecimalQuantity::_setToDoubleFast(double n) { for (; i <= -22; i += 22) n /= 1e22; n /= DOUBLE_MULTIPLIERS[-i]; } - auto result = static_cast(std::round(n)); + auto result = static_cast(uprv_round(n)); if (result != 0) { _setToLong(result); scale -= fracLength; @@ -521,12 +541,12 @@ int64_t DecimalQuantity::toLong(bool truncateIfOverflow) const { // if (dq.fitsInLong()) { /* use dq.toLong() */ } else { /* use some fallback */ } // Fallback behavior upon truncateIfOverflow is to truncate at 17 digits. uint64_t result = 0L; - int32_t upperMagnitude = scale + precision - 1; + int32_t upperMagnitude = exponent + scale + precision - 1; if (truncateIfOverflow) { upperMagnitude = std::min(upperMagnitude, 17); } for (int32_t magnitude = upperMagnitude; magnitude >= 0; magnitude--) { - result = result * 10 + getDigitPos(magnitude - scale); + result = result * 10 + getDigitPos(magnitude - scale - exponent); } if (isNegative()) { return static_cast(0LL - result); // i.e., -result @@ -536,7 +556,7 @@ int64_t DecimalQuantity::toLong(bool truncateIfOverflow) const { uint64_t DecimalQuantity::toFractionLong(bool includeTrailingZeros) const { uint64_t result = 0L; - int32_t magnitude = -1; + int32_t magnitude = -1 - exponent; int32_t lowerMagnitude = scale; if (includeTrailingZeros) { lowerMagnitude = std::min(lowerMagnitude, rReqPos); @@ -560,7 +580,7 @@ bool DecimalQuantity::fitsInLong(bool ignoreFraction) const { if (isZeroish()) { return true; } - if (scale < 0 && !ignoreFraction) { + if (exponent + scale < 0 && !ignoreFraction) { return false; } int magnitude = getMagnitude(); @@ -877,12 +897,30 @@ UnicodeString DecimalQuantity::toPlainString() const { if (isNegative()) { sb.append(u'-'); } - if (precision == 0 || getMagnitude() < 0) { + if (precision == 0) { + sb.append(u'0'); + return sb; + } + int32_t upper = scale + precision + exponent - 1; + int32_t lower = scale + exponent; + if (upper < lReqPos - 1) { + upper = lReqPos - 1; + } + if (lower > rReqPos) { + lower = rReqPos; + } + int32_t p = upper; + if (p < 0) { sb.append(u'0'); } - for (int m = getUpperDisplayMagnitude(); m >= getLowerDisplayMagnitude(); m--) { - if (m == -1) { sb.append(u'.'); } - sb.append(getDigit(m) + u'0'); + for (; p >= 0; p--) { + sb.append(u'0' + getDigitPos(p - scale - exponent)); + } + if (lower < 0) { + sb.append(u'.'); + } + for(; p >= lower; p--) { + sb.append(u'0' + getDigitPos(p - scale - exponent)); } return sb; } @@ -908,7 +946,7 @@ UnicodeString DecimalQuantity::toScientificString() const { } } result.append(u'E'); - int32_t _scale = upperPos + scale; + int32_t _scale = upperPos + scale + exponent; if (_scale == INT32_MIN) { result.append({u"-2147483648", -1}); return result; @@ -1021,6 +1059,7 @@ void DecimalQuantity::setBcdToZero() { isApproximate = false; origDouble = 0; origDelta = 0; + exponent = 0; } void DecimalQuantity::readIntToBcd(int32_t n) { diff --git a/deps/icu-small/source/i18n/number_decimalquantity.h b/deps/icu-small/source/i18n/number_decimalquantity.h index 4ec6c5a5b2bcf7..53a9eb33b26caf 100644 --- a/deps/icu-small/source/i18n/number_decimalquantity.h +++ b/deps/icu-small/source/i18n/number_decimalquantity.h @@ -146,6 +146,26 @@ class U_I18N_API DecimalQuantity : public IFixedDecimal, public UMemory { */ int32_t getMagnitude() const; + /** + * @return The value of the (suppressed) exponent after the number has been + * put into a notation with exponents (ex: compact, scientific). Ex: given + * the number 1000 as "1K" / "1E3", the return value will be 3 (positive). + */ + int32_t getExponent() const; + + /** + * Adjusts the value for the (suppressed) exponent stored when using + * notation with exponents (ex: compact, scientific). + * + *

Adjusting the exponent is decoupled from {@link #adjustMagnitude} in + * order to allow flexibility for {@link StandardPlural} to be selected in + * formatting (ex: for compact notation) either with or without the exponent + * applied in the value of the number. + * @param delta + * The value to adjust the exponent by. + */ + void adjustExponent(int32_t delta); + /** * @return Whether the value represented by this {@link DecimalQuantity} is * zero, infinity, or NaN. @@ -164,9 +184,19 @@ class U_I18N_API DecimalQuantity : public IFixedDecimal, public UMemory { /** @return Whether the value represented by this {@link DecimalQuantity} is not a number. */ bool isNaN() const U_OVERRIDE; - /** @param truncateIfOverflow if false and the number does NOT fit, fails with an assertion error. */ + /** + * Note: this method incorporates the value of {@code exponent} + * (for cases such as compact notation) to return the proper long value + * represented by the result. + * @param truncateIfOverflow if false and the number does NOT fit, fails with an assertion error. + */ int64_t toLong(bool truncateIfOverflow = false) const; + /** + * Note: this method incorporates the value of {@code exponent} + * (for cases such as compact notation) to return the proper long value + * represented by the result. + */ uint64_t toFractionLong(bool includeTrailingZeros) const; /** @@ -351,6 +381,10 @@ class U_I18N_API DecimalQuantity : public IFixedDecimal, public UMemory { int32_t lReqPos = 0; int32_t rReqPos = 0; + // The value of the (suppressed) exponent after the number has been put into + // a notation with exponents (ex: compact, scientific). + int32_t exponent = 0; + /** * The BCD of the 16 digits of the number represented by this object. Every 4 bits of the long map * to one digit. For example, the number "12345" in BCD is "0x12345". @@ -423,7 +457,7 @@ class U_I18N_API DecimalQuantity : public IFixedDecimal, public UMemory { /** * Sets the internal representation to zero. Clears any values stored in scale, precision, - * hasDouble, origDouble, origDelta, and BCD data. + * hasDouble, origDouble, origDelta, exponent, and BCD data. */ void setBcdToZero(); diff --git a/deps/icu-small/source/i18n/number_fluent.cpp b/deps/icu-small/source/i18n/number_fluent.cpp index 2dbd2fa6cd5acf..9cdb8b7156e614 100644 --- a/deps/icu-small/source/i18n/number_fluent.cpp +++ b/deps/icu-small/source/i18n/number_fluent.cpp @@ -11,7 +11,6 @@ #include "number_formatimpl.h" #include "umutex.h" #include "number_asformat.h" -#include "number_skeletons.h" #include "number_utils.h" #include "number_utypes.h" #include "util.h" @@ -21,6 +20,16 @@ using namespace icu; using namespace icu::number; using namespace icu::number::impl; +#if (U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN) && defined(_MSC_VER) +// Ignore MSVC warning 4661. This is generated for NumberFormatterSettings<>::toSkeleton() as this method +// is defined elsewhere (in number_skeletons.cpp). The compiler is warning that the explicit template instantiation +// inside this single translation unit (CPP file) is incomplete, and thus it isn't sure if the template class is +// fully defined. However, since each translation unit explicitly instantiates all the necessary template classes, +// they will all be passed to the linker, and the linker will still find and export all the class members. +#pragma warning(push) +#pragma warning(disable: 4661) +#endif + template Derived NumberFormatterSettings::notation(const Notation& notation) const& { Derived copy(*this); @@ -320,16 +329,7 @@ Derived NumberFormatterSettings::macros(impl::MacroProps&& macros)&& { return move; } -template -UnicodeString NumberFormatterSettings::toSkeleton(UErrorCode& status) const { - if (U_FAILURE(status)) { - return ICU_Utility::makeBogusString(); - } - if (fMacros.copyErrorTo(status)) { - return ICU_Utility::makeBogusString(); - } - return skeleton::generate(fMacros, status); -} +// Note: toSkeleton defined in number_skeletons.cpp template LocalPointer NumberFormatterSettings::clone() const & { @@ -358,15 +358,7 @@ LocalizedNumberFormatter NumberFormatter::withLocale(const Locale& locale) { return with().locale(locale); } -UnlocalizedNumberFormatter -NumberFormatter::forSkeleton(const UnicodeString& skeleton, UErrorCode& status) { - return skeleton::create(skeleton, nullptr, status); -} - -UnlocalizedNumberFormatter -NumberFormatter::forSkeleton(const UnicodeString& skeleton, UParseError& perror, UErrorCode& status) { - return skeleton::create(skeleton, &perror, status); -} +// Note: forSkeleton defined in number_skeletons.cpp template using NFS = NumberFormatterSettings; @@ -766,14 +758,11 @@ int32_t LocalizedNumberFormatter::getCallCount() const { return umtx_loadAcquire(*callCount); } -Format* LocalizedNumberFormatter::toFormat(UErrorCode& status) const { - if (U_FAILURE(status)) { - return nullptr; - } - LocalPointer retval( - new LocalizedNumberFormatterAsFormat(*this, fMacros.locale), status); - return retval.orphan(); -} +// Note: toFormat defined in number_asformat.cpp +#if (U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN) && defined(_MSC_VER) +// Warning 4661. +#pragma warning(pop) +#endif #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/number_formatimpl.cpp b/deps/icu-small/source/i18n/number_formatimpl.cpp index 2e2c4a9620c77c..5bba09cfb5293e 100644 --- a/deps/icu-small/source/i18n/number_formatimpl.cpp +++ b/deps/icu-small/source/i18n/number_formatimpl.cpp @@ -24,45 +24,6 @@ using namespace icu; using namespace icu::number; using namespace icu::number::impl; -namespace { - -struct CurrencyFormatInfoResult { - bool exists; - const char16_t* pattern; - const char16_t* decimalSeparator; - const char16_t* groupingSeparator; -}; - -CurrencyFormatInfoResult -getCurrencyFormatInfo(const Locale& locale, const char* isoCode, UErrorCode& status) { - // TODO: Load this data in a centralized location like ICU4J? - // TODO: Move this into the CurrencySymbols class? - // TODO: Parts of this same data are loaded in dcfmtsym.cpp; should clean up. - CurrencyFormatInfoResult result = {false, nullptr, nullptr, nullptr}; - if (U_FAILURE(status)) { return result; } - CharString key; - key.append("Currencies/", status); - key.append(isoCode, status); - UErrorCode localStatus = status; - LocalUResourceBundlePointer bundle(ures_open(U_ICUDATA_CURR, locale.getName(), &localStatus)); - ures_getByKeyWithFallback(bundle.getAlias(), key.data(), bundle.getAlias(), &localStatus); - if (U_SUCCESS(localStatus) && - ures_getSize(bundle.getAlias()) > 2) { // the length is 3 if more data is present - ures_getByIndex(bundle.getAlias(), 2, bundle.getAlias(), &localStatus); - int32_t dummy; - result.exists = true; - result.pattern = ures_getStringByIndex(bundle.getAlias(), 0, &dummy, &localStatus); - result.decimalSeparator = ures_getStringByIndex(bundle.getAlias(), 1, &dummy, &localStatus); - result.groupingSeparator = ures_getStringByIndex(bundle.getAlias(), 2, &dummy, &localStatus); - status = localStatus; - } else if (localStatus != U_MISSING_RESOURCE_ERROR) { - status = localStatus; - } - return result; -} - -} // namespace - MicroPropsGenerator::~MicroPropsGenerator() = default; @@ -111,7 +72,6 @@ void NumberFormatterImpl::preProcess(DecimalQuantity& inValue, MicroProps& micro return; } fMicroPropsGenerator->processQuantity(inValue, microsOut, status); - microsOut.rounder.apply(inValue, status); microsOut.integerWidth.apply(inValue, status); } @@ -124,7 +84,6 @@ MicroProps& NumberFormatterImpl::preProcessUnsafe(DecimalQuantity& inValue, UErr return fMicros; // must always return a value } fMicroPropsGenerator->processQuantity(inValue, fMicros, status); - fMicros.rounder.apply(inValue, status); fMicros.integerWidth.apply(inValue, status); return fMicros; } @@ -181,14 +140,6 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe, if (isCurrency) { currency = CurrencyUnit(macros.unit, status); // Restore CurrencyUnit from MeasureUnit } - const CurrencySymbols* currencySymbols; - if (macros.currencySymbols != nullptr) { - // Used by the DecimalFormat code path - currencySymbols = macros.currencySymbols; - } else { - fWarehouse.fCurrencySymbols = {currency, macros.locale, status}; - currencySymbols = &fWarehouse.fCurrencySymbols; - } UNumberUnitWidth unitWidth = UNUM_UNIT_WIDTH_SHORT; if (macros.unitWidth != UNUM_UNIT_WIDTH_COUNT) { unitWidth = macros.unitWidth; @@ -215,41 +166,26 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe, if (macros.symbols.isDecimalFormatSymbols()) { fMicros.symbols = macros.symbols.getDecimalFormatSymbols(); } else { - auto newSymbols = new DecimalFormatSymbols(macros.locale, *ns, status); - if (newSymbols == nullptr) { - status = U_MEMORY_ALLOCATION_ERROR; + LocalPointer newSymbols( + new DecimalFormatSymbols(macros.locale, *ns, status), status); + if (U_FAILURE(status)) { return nullptr; } - fMicros.symbols = newSymbols; - // Give ownership to the NumberFormatterImpl. - fSymbols.adoptInstead(fMicros.symbols); + if (isCurrency) { + newSymbols->setCurrency(currency.getISOCurrency(), status); + if (U_FAILURE(status)) { + return nullptr; + } + } + fMicros.symbols = newSymbols.getAlias(); + fSymbols.adoptInstead(newSymbols.orphan()); } // Load and parse the pattern string. It is used for grouping sizes and affixes only. // If we are formatting currency, check for a currency-specific pattern. const char16_t* pattern = nullptr; - if (isCurrency) { - CurrencyFormatInfoResult info = getCurrencyFormatInfo( - macros.locale, currency.getSubtype(), status); - if (info.exists) { - pattern = info.pattern; - // It's clunky to clone an object here, but this code is not frequently executed. - auto symbols = new DecimalFormatSymbols(*fMicros.symbols); - if (symbols == nullptr) { - status = U_MEMORY_ALLOCATION_ERROR; - return nullptr; - } - fMicros.symbols = symbols; - fSymbols.adoptInstead(symbols); - symbols->setSymbol( - DecimalFormatSymbols::ENumberFormatSymbol::kMonetarySeparatorSymbol, - UnicodeString(info.decimalSeparator), - FALSE); - symbols->setSymbol( - DecimalFormatSymbols::ENumberFormatSymbol::kMonetaryGroupingSeparatorSymbol, - UnicodeString(info.groupingSeparator), - FALSE); - } + if (isCurrency && fMicros.symbols->getCurrencyPattern() != nullptr) { + pattern = fMicros.symbols->getCurrencyPattern(); } if (pattern == nullptr) { CldrPatternStyle patternStyle; @@ -267,6 +203,9 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe, patternStyle = CLDR_PATTERN_STYLE_CURRENCY; } pattern = utils::getPatternForStyle(macros.locale, nsName, patternStyle, status); + if (U_FAILURE(status)) { + return nullptr; + } } auto patternInfo = new ParsedPatternInfo(); if (patternInfo == nullptr) { @@ -275,6 +214,9 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe, } fPatternInfo.adoptInstead(patternInfo); PatternParser::parseToPatternInfo(UnicodeString(pattern), *patternInfo, status); + if (U_FAILURE(status)) { + return nullptr; + } ///////////////////////////////////////////////////////////////////////////////////// /// START POPULATING THE DEFAULT MICROPROPS AND BUILDING THE MICROPROPS GENERATOR /// @@ -305,6 +247,9 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe, roundingMode = precision.fRoundingMode; } fMicros.rounder = {precision, roundingMode, currency, status}; + if (U_FAILURE(status)) { + return nullptr; + } // Grouping strategy if (!macros.grouper.isBogus()) { @@ -372,23 +317,23 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe, patternModifier->setPatternInfo( macros.affixProvider != nullptr ? macros.affixProvider : static_cast(fPatternInfo.getAlias()), - UNUM_FIELD_COUNT); + kUndefinedField); patternModifier->setPatternAttributes(fMicros.sign, isPermille); if (patternModifier->needsPlurals()) { patternModifier->setSymbols( fMicros.symbols, - currencySymbols, + currency, unitWidth, - resolvePluralRules(macros.rules, macros.locale, status)); + resolvePluralRules(macros.rules, macros.locale, status), + status); } else { - patternModifier->setSymbols(fMicros.symbols, currencySymbols, unitWidth, nullptr); + patternModifier->setSymbols(fMicros.symbols, currency, unitWidth, nullptr, status); } if (safe) { - fImmutablePatternModifier.adoptInstead(patternModifier->createImmutableAndChain(chain, status)); - chain = fImmutablePatternModifier.getAlias(); - } else { - patternModifier->addToChain(chain); - chain = patternModifier; + fImmutablePatternModifier.adoptInstead(patternModifier->createImmutable(status)); + } + if (U_FAILURE(status)) { + return nullptr; } // Outer modifier (CLDR units and currency long names) @@ -416,10 +361,11 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe, // No outer modifier required fMicros.modOuter = &fMicros.helpers.emptyWeakModifier; } + if (U_FAILURE(status)) { + return nullptr; + } // Compact notation - // NOTE: Compact notation can (but might not) override the middle modifier and rounding. - // It therefore needs to go at the end of the chain. if (macros.notation.fType == Notation::NTN_COMPACT) { CompactType compactType = (isCurrency && unitWidth != UNUM_UNIT_WIDTH_FULL_NAME) ? CompactType::TYPE_CURRENCY : CompactType::TYPE_DECIMAL; @@ -429,7 +375,8 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe, nsName, compactType, resolvePluralRules(macros.rules, macros.locale, status), - safe ? patternModifier : nullptr, + patternModifier, + safe, chain, status); if (newCompactHandler == nullptr) { @@ -439,6 +386,18 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe, fCompactHandler.adoptInstead(newCompactHandler); chain = fCompactHandler.getAlias(); } + if (U_FAILURE(status)) { + return nullptr; + } + + // Always add the pattern modifier as the last element of the chain. + if (safe) { + fImmutablePatternModifier->addToChain(chain); + chain = fImmutablePatternModifier.getAlias(); + } else { + patternModifier->addToChain(chain); + chain = patternModifier; + } return chain; } @@ -478,14 +437,14 @@ int32_t NumberFormatterImpl::writeNumber(const MicroProps& micros, DecimalQuanti length += string.insert( length + index, micros.symbols->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kInfinitySymbol), - UNUM_INTEGER_FIELD, + {UFIELD_CATEGORY_NUMBER, UNUM_INTEGER_FIELD}, status); } else if (quantity.isNaN()) { length += string.insert( length + index, micros.symbols->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kNaNSymbol), - UNUM_INTEGER_FIELD, + {UFIELD_CATEGORY_NUMBER, UNUM_INTEGER_FIELD}, status); } else { @@ -501,12 +460,23 @@ int32_t NumberFormatterImpl::writeNumber(const MicroProps& micros, DecimalQuanti .symbols ->getSymbol( DecimalFormatSymbols::ENumberFormatSymbol::kDecimalSeparatorSymbol), - UNUM_DECIMAL_SEPARATOR_FIELD, + {UFIELD_CATEGORY_NUMBER, UNUM_DECIMAL_SEPARATOR_FIELD}, status); } // Add the fraction digits length += writeFractionDigits(micros, quantity, string, length + index, status); + + if (length == 0) { + // Force output of the digit for value 0 + length += utils::insertDigitFromSymbols( + string, + index, + 0, + *micros.symbols, + {UFIELD_CATEGORY_NUMBER, UNUM_INTEGER_FIELD}, + status); + } } return length; @@ -526,14 +496,20 @@ int32_t NumberFormatterImpl::writeIntegerDigits(const MicroProps& micros, Decima DecimalFormatSymbols::ENumberFormatSymbol::kMonetaryGroupingSeparatorSymbol) : micros.symbols->getSymbol( DecimalFormatSymbols::ENumberFormatSymbol::kGroupingSeparatorSymbol), - UNUM_GROUPING_SEPARATOR_FIELD, + {UFIELD_CATEGORY_NUMBER, UNUM_GROUPING_SEPARATOR_FIELD}, status); } // Get and append the next digit value int8_t nextDigit = quantity.getDigit(i); length += utils::insertDigitFromSymbols( - string, index, nextDigit, *micros.symbols, UNUM_INTEGER_FIELD, status); + string, + index, + nextDigit, + *micros.symbols, + {UFIELD_CATEGORY_NUMBER, + UNUM_INTEGER_FIELD}, + status); } return length; } @@ -547,7 +523,12 @@ int32_t NumberFormatterImpl::writeFractionDigits(const MicroProps& micros, Decim // Get and append the next digit value int8_t nextDigit = quantity.getDigit(-i - 1); length += utils::insertDigitFromSymbols( - string, length + index, nextDigit, *micros.symbols, UNUM_FRACTION_FIELD, status); + string, + length + index, + nextDigit, + *micros.symbols, + {UFIELD_CATEGORY_NUMBER, UNUM_FRACTION_FIELD}, + status); } return length; } diff --git a/deps/icu-small/source/i18n/number_formatimpl.h b/deps/icu-small/source/i18n/number_formatimpl.h index 206c5f58c576a1..084bc4a9d0b209 100644 --- a/deps/icu-small/source/i18n/number_formatimpl.h +++ b/deps/icu-small/source/i18n/number_formatimpl.h @@ -95,7 +95,7 @@ class NumberFormatterImpl : public UMemory { LocalPointer fPatternInfo; LocalPointer fScientificHandler; LocalPointer fPatternModifier; - LocalPointer fImmutablePatternModifier; + LocalPointer fImmutablePatternModifier; LocalPointer fLongNameHandler; LocalPointer fCompactHandler; diff --git a/deps/icu-small/source/i18n/number_longnames.cpp b/deps/icu-small/source/i18n/number_longnames.cpp index 817aa0e0d9c39d..bb32d0381a507e 100644 --- a/deps/icu-small/source/i18n/number_longnames.cpp +++ b/deps/icu-small/source/i18n/number_longnames.cpp @@ -188,6 +188,12 @@ LongNameHandler* LongNameHandler::forMeasureUnit(const Locale &loc, const MeasureUnit &unitRef, const MeasureUnit &perUnit, const UNumberUnitWidth &width, const PluralRules *rules, const MicroPropsGenerator *parent, UErrorCode &status) { + if (uprv_strlen(unitRef.getType()) == 0 || uprv_strlen(perUnit.getType()) == 0) { + // TODO(ICU-20941): Unsanctioned unit. Not yet fully supported. Set an error code. + status = U_UNSUPPORTED_ERROR; + return nullptr; + } + MeasureUnit unit = unitRef; if (uprv_strcmp(perUnit.getType(), "none") != 0) { // Compound unit: first try to simplify (e.g., meters per second is its own unit). @@ -209,7 +215,7 @@ LongNameHandler::forMeasureUnit(const Locale &loc, const MeasureUnit &unitRef, c UnicodeString simpleFormats[ARRAY_LENGTH]; getMeasureData(loc, unit, width, simpleFormats, status); if (U_FAILURE(status)) { return result; } - result->simpleFormatsToModifiers(simpleFormats, UNUM_MEASURE_UNIT_FIELD, status); + result->simpleFormatsToModifiers(simpleFormats, {UFIELD_CATEGORY_NUMBER, UNUM_MEASURE_UNIT_FIELD}, status); return result; } @@ -240,14 +246,15 @@ LongNameHandler::forCompoundUnit(const Locale &loc, const MeasureUnit &unit, con if (U_FAILURE(status)) { return result; } UnicodeString secondaryFormat = getWithPlural(secondaryData, StandardPlural::Form::ONE, status); if (U_FAILURE(status)) { return result; } - SimpleFormatter secondaryCompiled(secondaryFormat, 1, 1, status); + // Some "one" pattern may not contain "{0}". For example in "ar" or "ne" locale. + SimpleFormatter secondaryCompiled(secondaryFormat, 0, 1, status); if (U_FAILURE(status)) { return result; } UnicodeString secondaryString = secondaryCompiled.getTextWithNoArguments().trim(); // TODO: Why does UnicodeString need to be explicit in the following line? compiled.format(UnicodeString(u"{0}"), secondaryString, perUnitFormat, status); if (U_FAILURE(status)) { return result; } } - result->multiSimpleFormatsToModifiers(primaryData, perUnitFormat, UNUM_MEASURE_UNIT_FIELD, status); + result->multiSimpleFormatsToModifiers(primaryData, perUnitFormat, {UFIELD_CATEGORY_NUMBER, UNUM_MEASURE_UNIT_FIELD}, status); return result; } @@ -296,7 +303,7 @@ LongNameHandler* LongNameHandler::forCurrencyLongNames(const Locale &loc, const UnicodeString simpleFormats[ARRAY_LENGTH]; getCurrencyLongNameData(loc, currency, simpleFormats, status); if (U_FAILURE(status)) { return nullptr; } - result->simpleFormatsToModifiers(simpleFormats, UNUM_CURRENCY_FIELD, status); + result->simpleFormatsToModifiers(simpleFormats, {UFIELD_CATEGORY_NUMBER, UNUM_CURRENCY_FIELD}, status); return result; } @@ -308,7 +315,7 @@ void LongNameHandler::simpleFormatsToModifiers(const UnicodeString *simpleFormat if (U_FAILURE(status)) { return; } SimpleFormatter compiledFormatter(simpleFormat, 0, 1, status); if (U_FAILURE(status)) { return; } - fModifiers[i] = SimpleModifier(compiledFormatter, field, false, {this, SIGNUM_ZERO, plural}); + fModifiers[i] = SimpleModifier(compiledFormatter, field, false, {this, SIGNUM_POS_ZERO, plural}); } } @@ -325,7 +332,7 @@ void LongNameHandler::multiSimpleFormatsToModifiers(const UnicodeString *leadFor if (U_FAILURE(status)) { return; } SimpleFormatter compoundCompiled(compoundFormat, 0, 1, status); if (U_FAILURE(status)) { return; } - fModifiers[i] = SimpleModifier(compoundCompiled, field, false, {this, SIGNUM_ZERO, plural}); + fModifiers[i] = SimpleModifier(compoundCompiled, field, false, {this, SIGNUM_POS_ZERO, plural}); } } diff --git a/deps/icu-small/source/i18n/number_mapper.cpp b/deps/icu-small/source/i18n/number_mapper.cpp index 40fd5284b86649..ec617438c9a9e3 100644 --- a/deps/icu-small/source/i18n/number_mapper.cpp +++ b/deps/icu-small/source/i18n/number_mapper.cpp @@ -13,7 +13,6 @@ #include "number_patternstring.h" #include "unicode/errorcode.h" #include "number_utils.h" -#include "number_currencysymbols.h" using namespace icu; using namespace icu::number; @@ -63,17 +62,8 @@ MacroProps NumberPropertyMapper::oldToNew(const DecimalFormatProperties& propert // AFFIXES // ///////////// - AffixPatternProvider* affixProvider; - if (properties.currencyPluralInfo.fPtr.isNull()) { - warehouse.currencyPluralInfoAPP.setToBogus(); - warehouse.propertiesAPP.setTo(properties, status); - affixProvider = &warehouse.propertiesAPP; - } else { - warehouse.currencyPluralInfoAPP.setTo(*properties.currencyPluralInfo.fPtr, properties, status); - warehouse.propertiesAPP.setToBogus(); - affixProvider = &warehouse.currencyPluralInfoAPP; - } - macros.affixProvider = affixProvider; + warehouse.affixProvider.setTo(properties, status); + macros.affixProvider = &warehouse.affixProvider.get(); /////////// // UNITS // @@ -83,15 +73,13 @@ MacroProps NumberPropertyMapper::oldToNew(const DecimalFormatProperties& propert !properties.currency.isNull() || !properties.currencyPluralInfo.fPtr.isNull() || !properties.currencyUsage.isNull() || - affixProvider->hasCurrencySign()); + warehouse.affixProvider.get().hasCurrencySign()); CurrencyUnit currency = resolveCurrency(properties, locale, status); UCurrencyUsage currencyUsage = properties.currencyUsage.getOrDefault(UCURR_USAGE_STANDARD); if (useCurrency) { // NOTE: Slicing is OK. macros.unit = currency; // NOLINT } - warehouse.currencySymbols = {currency, locale, symbols, status}; - macros.currencySymbols = &warehouse.currencySymbols; /////////////////////// // ROUNDING STRATEGY // @@ -125,10 +113,8 @@ MacroProps NumberPropertyMapper::oldToNew(const DecimalFormatProperties& propert } // Validate min/max int/frac. // For backwards compatibility, minimum overrides maximum if the two conflict. - // The following logic ensures that there is always a minimum of at least one digit. if (minInt == 0 && maxFrac != 0) { - // Force a digit after the decimal point. - minFrac = minFrac <= 0 ? 1 : minFrac; + minFrac = (minFrac < 0 || (minFrac == 0 && maxInt == 0)) ? 1 : minFrac; maxFrac = maxFrac < 0 ? -1 : maxFrac < minFrac ? minFrac : maxFrac; minInt = 0; maxInt = maxInt < 0 ? -1 : maxInt > kMaxIntFracSig ? -1 : maxInt; diff --git a/deps/icu-small/source/i18n/number_mapper.h b/deps/icu-small/source/i18n/number_mapper.h index de7d9c3865c8df..d18b8b3c438cf4 100644 --- a/deps/icu-small/source/i18n/number_mapper.h +++ b/deps/icu-small/source/i18n/number_mapper.h @@ -20,6 +20,10 @@ namespace number { namespace impl { +class AutoAffixPatternProvider; +class CurrencyPluralInfoAffixProvider; + + class PropertiesAffixPatternProvider : public AffixPatternProvider, public UMemory { public: bool isBogus() const { @@ -32,12 +36,6 @@ class PropertiesAffixPatternProvider : public AffixPatternProvider, public UMemo void setTo(const DecimalFormatProperties& properties, UErrorCode& status); - PropertiesAffixPatternProvider() = default; // puts instance in valid but undefined state - - PropertiesAffixPatternProvider(const DecimalFormatProperties& properties, UErrorCode& status) { - setTo(properties, status); - } - // AffixPatternProvider Methods: char16_t charAt(int32_t flags, int32_t i) const U_OVERRIDE; @@ -65,9 +63,14 @@ class PropertiesAffixPatternProvider : public AffixPatternProvider, public UMemo UnicodeString negSuffix; bool isCurrencyPattern; + PropertiesAffixPatternProvider() = default; // puts instance in valid but undefined state + const UnicodeString& getStringInternal(int32_t flags) const; bool fBogus{true}; + + friend class AutoAffixPatternProvider; + friend class CurrencyPluralInfoAffixProvider; }; @@ -107,7 +110,43 @@ class CurrencyPluralInfoAffixProvider : public AffixPatternProvider, public UMem private: PropertiesAffixPatternProvider affixesByPlural[StandardPlural::COUNT]; + CurrencyPluralInfoAffixProvider() = default; + bool fBogus{true}; + + friend class AutoAffixPatternProvider; +}; + + +class AutoAffixPatternProvider { + public: + inline AutoAffixPatternProvider() = default; + + inline AutoAffixPatternProvider(const DecimalFormatProperties& properties, UErrorCode& status) { + setTo(properties, status); + } + + inline void setTo(const DecimalFormatProperties& properties, UErrorCode& status) { + if (properties.currencyPluralInfo.fPtr.isNull()) { + propertiesAPP.setTo(properties, status); + currencyPluralInfoAPP.setToBogus(); + } else { + propertiesAPP.setToBogus(); + currencyPluralInfoAPP.setTo(*properties.currencyPluralInfo.fPtr, properties, status); + } + } + + inline const AffixPatternProvider& get() const { + if (!currencyPluralInfoAPP.isBogus()) { + return currencyPluralInfoAPP; + } else { + return propertiesAPP; + } + } + + private: + PropertiesAffixPatternProvider propertiesAPP; + CurrencyPluralInfoAffixProvider currencyPluralInfoAPP; }; @@ -115,9 +154,8 @@ class CurrencyPluralInfoAffixProvider : public AffixPatternProvider, public UMem * A struct for ownership of a few objects needed for formatting. */ struct DecimalFormatWarehouse { - PropertiesAffixPatternProvider propertiesAPP; - CurrencyPluralInfoAffixProvider currencyPluralInfoAPP; - CurrencySymbols currencySymbols; + AutoAffixPatternProvider affixProvider; + }; diff --git a/deps/icu-small/source/i18n/number_microprops.h b/deps/icu-small/source/i18n/number_microprops.h index d2393aea50c098..56512f5e6f94ac 100644 --- a/deps/icu-small/source/i18n/number_microprops.h +++ b/deps/icu-small/source/i18n/number_microprops.h @@ -37,7 +37,7 @@ struct MicroProps : public MicroPropsGenerator { // Note: This struct has no direct ownership of the following pointers. const DecimalFormatSymbols* symbols; const Modifier* modOuter; - const Modifier* modMiddle; + const Modifier* modMiddle = nullptr; const Modifier* modInner; // The following "helper" fields may optionally be used during the MicroPropsGenerator. diff --git a/deps/icu-small/source/i18n/number_modifiers.cpp b/deps/icu-small/source/i18n/number_modifiers.cpp index 3a44f8f6f15328..3becb7ba852336 100644 --- a/deps/icu-small/source/i18n/number_modifiers.cpp +++ b/deps/icu-small/source/i18n/number_modifiers.cpp @@ -89,7 +89,7 @@ bool ConstantAffixModifier::isStrong() const { return fStrong; } -bool ConstantAffixModifier::containsField(UNumberFormatFields field) const { +bool ConstantAffixModifier::containsField(Field field) const { (void)field; // This method is not currently used. UPRV_UNREACHABLE; @@ -151,7 +151,7 @@ SimpleModifier::SimpleModifier(const SimpleFormatter &simpleFormatter, Field fie } SimpleModifier::SimpleModifier() - : fField(UNUM_FIELD_COUNT), fStrong(false), fPrefixLength(0), fSuffixLength(0) { + : fField(kUndefinedField), fStrong(false), fPrefixLength(0), fSuffixLength(0) { } int32_t SimpleModifier::apply(FormattedStringBuilder &output, int leftIndex, int rightIndex, @@ -178,7 +178,7 @@ bool SimpleModifier::isStrong() const { return fStrong; } -bool SimpleModifier::containsField(UNumberFormatFields field) const { +bool SimpleModifier::containsField(Field field) const { (void)field; // This method is not currently used. UPRV_UNREACHABLE; @@ -292,7 +292,7 @@ int32_t ConstantMultiFieldModifier::apply(FormattedStringBuilder &output, int le leftIndex + length, rightIndex + length, UnicodeString(), 0, 0, - UNUM_FIELD_COUNT, status); + kUndefinedField, status); } length += output.insert(rightIndex + length, fSuffix, status); return length; @@ -310,7 +310,7 @@ bool ConstantMultiFieldModifier::isStrong() const { return fStrong; } -bool ConstantMultiFieldModifier::containsField(UNumberFormatFields field) const { +bool ConstantMultiFieldModifier::containsField(Field field) const { return fPrefix.containsField(field) || fSuffix.containsField(field); } @@ -342,7 +342,7 @@ CurrencySpacingEnabledModifier::CurrencySpacingEnabledModifier(const FormattedSt : ConstantMultiFieldModifier(prefix, suffix, overwrite, strong) { // Check for currency spacing. Do not build the UnicodeSets unless there is // a currency code point at a boundary. - if (prefix.length() > 0 && prefix.fieldAt(prefix.length() - 1) == UNUM_CURRENCY_FIELD) { + if (prefix.length() > 0 && prefix.fieldAt(prefix.length() - 1) == Field(UFIELD_CATEGORY_NUMBER, UNUM_CURRENCY_FIELD)) { int prefixCp = prefix.getLastCodePoint(); UnicodeSet prefixUnicodeSet = getUnicodeSet(symbols, IN_CURRENCY, PREFIX, status); if (prefixUnicodeSet.contains(prefixCp)) { @@ -357,8 +357,8 @@ CurrencySpacingEnabledModifier::CurrencySpacingEnabledModifier(const FormattedSt fAfterPrefixUnicodeSet.setToBogus(); fAfterPrefixInsert.setToBogus(); } - if (suffix.length() > 0 && suffix.fieldAt(0) == UNUM_CURRENCY_FIELD) { - int suffixCp = suffix.getLastCodePoint(); + if (suffix.length() > 0 && suffix.fieldAt(0) == Field(UFIELD_CATEGORY_NUMBER, UNUM_CURRENCY_FIELD)) { + int suffixCp = suffix.getFirstCodePoint(); UnicodeSet suffixUnicodeSet = getUnicodeSet(symbols, IN_CURRENCY, SUFFIX, status); if (suffixUnicodeSet.contains(suffixCp)) { fBeforeSuffixUnicodeSet = getUnicodeSet(symbols, IN_NUMBER, SUFFIX, status); @@ -381,12 +381,20 @@ int32_t CurrencySpacingEnabledModifier::apply(FormattedStringBuilder &output, in if (rightIndex - leftIndex > 0 && !fAfterPrefixUnicodeSet.isBogus() && fAfterPrefixUnicodeSet.contains(output.codePointAt(leftIndex))) { // TODO: Should we use the CURRENCY field here? - length += output.insert(leftIndex, fAfterPrefixInsert, UNUM_FIELD_COUNT, status); + length += output.insert( + leftIndex, + fAfterPrefixInsert, + kUndefinedField, + status); } if (rightIndex - leftIndex > 0 && !fBeforeSuffixUnicodeSet.isBogus() && fBeforeSuffixUnicodeSet.contains(output.codePointBefore(rightIndex))) { // TODO: Should we use the CURRENCY field here? - length += output.insert(rightIndex + length, fBeforeSuffixInsert, UNUM_FIELD_COUNT, status); + length += output.insert( + rightIndex + length, + fBeforeSuffixInsert, + kUndefinedField, + status); } // Call super for the remaining logic @@ -422,7 +430,7 @@ CurrencySpacingEnabledModifier::applyCurrencySpacingAffix(FormattedStringBuilder // This works even if the last code point in the prefix is 2 code units because the // field value gets populated to both indices in the field array. Field affixField = (affix == PREFIX) ? output.fieldAt(index - 1) : output.fieldAt(index); - if (affixField != UNUM_CURRENCY_FIELD) { + if (affixField != Field(UFIELD_CATEGORY_NUMBER, UNUM_CURRENCY_FIELD)) { return 0; } int affixCp = (affix == PREFIX) ? output.codePointBefore(index) : output.codePointAt(index); @@ -443,7 +451,7 @@ CurrencySpacingEnabledModifier::applyCurrencySpacingAffix(FormattedStringBuilder // However, the build code path is more efficient, and this is the most natural // place to put currency spacing in the non-build code path. // TODO: Should we use the CURRENCY field here? - return output.insert(index, spacingString, UNUM_FIELD_COUNT, status); + return output.insert(index, spacingString, kUndefinedField, status); } UnicodeSet diff --git a/deps/icu-small/source/i18n/number_modifiers.h b/deps/icu-small/source/i18n/number_modifiers.h index c84c6aa273ed76..375254310ca056 100644 --- a/deps/icu-small/source/i18n/number_modifiers.h +++ b/deps/icu-small/source/i18n/number_modifiers.h @@ -37,7 +37,7 @@ class U_I18N_API ConstantAffixModifier : public Modifier, public UObject { bool isStrong() const U_OVERRIDE; - bool containsField(UNumberFormatFields field) const U_OVERRIDE; + bool containsField(Field field) const U_OVERRIDE; void getParameters(Parameters& output) const U_OVERRIDE; @@ -73,7 +73,7 @@ class U_I18N_API SimpleModifier : public Modifier, public UMemory { bool isStrong() const U_OVERRIDE; - bool containsField(UNumberFormatFields field) const U_OVERRIDE; + bool containsField(Field field) const U_OVERRIDE; void getParameters(Parameters& output) const U_OVERRIDE; @@ -166,7 +166,7 @@ class U_I18N_API ConstantMultiFieldModifier : public Modifier, public UMemory { bool isStrong() const U_OVERRIDE; - bool containsField(UNumberFormatFields field) const U_OVERRIDE; + bool containsField(Field field) const U_OVERRIDE; void getParameters(Parameters& output) const U_OVERRIDE; @@ -255,7 +255,7 @@ class U_I18N_API EmptyModifier : public Modifier, public UMemory { return fStrong; } - bool containsField(UNumberFormatFields field) const U_OVERRIDE { + bool containsField(Field field) const U_OVERRIDE { (void)field; return false; } @@ -319,12 +319,12 @@ class U_I18N_API AdoptingModifierStore : public ModifierStore, public UMemory { private: // NOTE: mods is zero-initialized (to nullptr) - const Modifier *mods[3 * StandardPlural::COUNT] = {}; + const Modifier *mods[4 * StandardPlural::COUNT] = {}; inline static int32_t getModIndex(Signum signum, StandardPlural::Form plural) { - U_ASSERT(signum >= -1 && signum <= 1); + U_ASSERT(signum >= 0 && signum < SIGNUM_COUNT); U_ASSERT(plural >= 0 && plural < StandardPlural::COUNT); - return static_cast(plural) * 3 + (signum + 1); + return static_cast(plural) * SIGNUM_COUNT + signum; } }; diff --git a/deps/icu-small/source/i18n/number_output.cpp b/deps/icu-small/source/i18n/number_output.cpp index e2f069139a4b47..40192a9225b9de 100644 --- a/deps/icu-small/source/i18n/number_output.cpp +++ b/deps/icu-small/source/i18n/number_output.cpp @@ -19,16 +19,6 @@ UPRV_FORMATTED_VALUE_SUBCLASS_AUTO_IMPL(FormattedNumber) #define UPRV_NOARG -UBool FormattedNumber::nextFieldPosition(FieldPosition& fieldPosition, UErrorCode& status) const { - UPRV_FORMATTED_VALUE_METHOD_GUARD(FALSE) - return fData->nextFieldPosition(fieldPosition, status); -} - -void FormattedNumber::getAllFieldPositions(FieldPositionIterator& iterator, UErrorCode& status) const { - FieldPositionIteratorHandler fpih(&iterator, status); - getAllFieldPositionsImpl(fpih, status); -} - void FormattedNumber::toDecimalNumber(ByteSink& sink, UErrorCode& status) const { UPRV_FORMATTED_VALUE_METHOD_GUARD(UPRV_NOARG) impl::DecNum decnum; diff --git a/deps/icu-small/source/i18n/number_padding.cpp b/deps/icu-small/source/i18n/number_padding.cpp index c68a9875b2055f..c320c3ffb6fadc 100644 --- a/deps/icu-small/source/i18n/number_padding.cpp +++ b/deps/icu-small/source/i18n/number_padding.cpp @@ -21,7 +21,7 @@ addPaddingHelper(UChar32 paddingCp, int32_t requiredPadding, FormattedStringBuil UErrorCode &status) { for (int32_t i = 0; i < requiredPadding; i++) { // TODO: If appending to the end, this will cause actual insertion operations. Improve. - string.insertCodePoint(index, paddingCp, UNUM_FIELD_COUNT, status); + string.insertCodePoint(index, paddingCp, kUndefinedField, status); } return U16_LENGTH(paddingCp) * requiredPadding; } diff --git a/deps/icu-small/source/i18n/number_patternmodifier.cpp b/deps/icu-small/source/i18n/number_patternmodifier.cpp index 724f5b9741cc52..45602942aefe8e 100644 --- a/deps/icu-small/source/i18n/number_patternmodifier.cpp +++ b/deps/icu-small/source/i18n/number_patternmodifier.cpp @@ -34,11 +34,13 @@ void MutablePatternModifier::setPatternAttributes(UNumberSignDisplay signDisplay } void MutablePatternModifier::setSymbols(const DecimalFormatSymbols* symbols, - const CurrencySymbols* currencySymbols, - const UNumberUnitWidth unitWidth, const PluralRules* rules) { + const CurrencyUnit& currency, + const UNumberUnitWidth unitWidth, + const PluralRules* rules, + UErrorCode& status) { U_ASSERT((rules != nullptr) == needsPlurals()); fSymbols = symbols; - fCurrencySymbols = currencySymbols; + fCurrencySymbols = {currency, symbols->getLocale(), *symbols, status}; fUnitWidth = unitWidth; fRules = rules; } @@ -55,12 +57,6 @@ bool MutablePatternModifier::needsPlurals() const { } ImmutablePatternModifier* MutablePatternModifier::createImmutable(UErrorCode& status) { - return createImmutableAndChain(nullptr, status); -} - -ImmutablePatternModifier* -MutablePatternModifier::createImmutableAndChain(const MicroPropsGenerator* parent, UErrorCode& status) { - // TODO: Move StandardPlural VALUES to standardplural.h static const StandardPlural::Form STANDARD_PLURAL_VALUES[] = { StandardPlural::Form::ZERO, @@ -81,8 +77,10 @@ MutablePatternModifier::createImmutableAndChain(const MicroPropsGenerator* paren for (StandardPlural::Form plural : STANDARD_PLURAL_VALUES) { setNumberProperties(SIGNUM_POS, plural); pm->adoptModifier(SIGNUM_POS, plural, createConstantModifier(status)); - setNumberProperties(SIGNUM_ZERO, plural); - pm->adoptModifier(SIGNUM_ZERO, plural, createConstantModifier(status)); + setNumberProperties(SIGNUM_NEG_ZERO, plural); + pm->adoptModifier(SIGNUM_NEG_ZERO, plural, createConstantModifier(status)); + setNumberProperties(SIGNUM_POS_ZERO, plural); + pm->adoptModifier(SIGNUM_POS_ZERO, plural, createConstantModifier(status)); setNumberProperties(SIGNUM_NEG, plural); pm->adoptModifier(SIGNUM_NEG, plural, createConstantModifier(status)); } @@ -90,20 +88,22 @@ MutablePatternModifier::createImmutableAndChain(const MicroPropsGenerator* paren delete pm; return nullptr; } - return new ImmutablePatternModifier(pm, fRules, parent); // adopts pm + return new ImmutablePatternModifier(pm, fRules); // adopts pm } else { // Faster path when plural keyword is not needed. setNumberProperties(SIGNUM_POS, StandardPlural::Form::COUNT); pm->adoptModifierWithoutPlural(SIGNUM_POS, createConstantModifier(status)); - setNumberProperties(SIGNUM_ZERO, StandardPlural::Form::COUNT); - pm->adoptModifierWithoutPlural(SIGNUM_ZERO, createConstantModifier(status)); + setNumberProperties(SIGNUM_NEG_ZERO, StandardPlural::Form::COUNT); + pm->adoptModifierWithoutPlural(SIGNUM_NEG_ZERO, createConstantModifier(status)); + setNumberProperties(SIGNUM_POS_ZERO, StandardPlural::Form::COUNT); + pm->adoptModifierWithoutPlural(SIGNUM_POS_ZERO, createConstantModifier(status)); setNumberProperties(SIGNUM_NEG, StandardPlural::Form::COUNT); pm->adoptModifierWithoutPlural(SIGNUM_NEG, createConstantModifier(status)); if (U_FAILURE(status)) { delete pm; return nullptr; } - return new ImmutablePatternModifier(pm, nullptr, parent); // adopts pm + return new ImmutablePatternModifier(pm, nullptr); // adopts pm } } @@ -120,13 +120,16 @@ ConstantMultiFieldModifier* MutablePatternModifier::createConstantModifier(UErro } } -ImmutablePatternModifier::ImmutablePatternModifier(AdoptingModifierStore* pm, const PluralRules* rules, - const MicroPropsGenerator* parent) - : pm(pm), rules(rules), parent(parent) {} +ImmutablePatternModifier::ImmutablePatternModifier(AdoptingModifierStore* pm, const PluralRules* rules) + : pm(pm), rules(rules), parent(nullptr) {} void ImmutablePatternModifier::processQuantity(DecimalQuantity& quantity, MicroProps& micros, UErrorCode& status) const { parent->processQuantity(quantity, micros, status); + micros.rounder.apply(quantity, status); + if (micros.modMiddle != nullptr) { + return; + } applyToMicros(micros, quantity, status); } @@ -148,6 +151,10 @@ const Modifier* ImmutablePatternModifier::getModifier(Signum signum, StandardPlu } } +void ImmutablePatternModifier::addToChain(const MicroPropsGenerator* parent) { + this->parent = parent; +} + /** Used by the unsafe code path. */ MicroPropsGenerator& MutablePatternModifier::addToChain(const MicroPropsGenerator* parent) { @@ -158,6 +165,10 @@ MicroPropsGenerator& MutablePatternModifier::addToChain(const MicroPropsGenerato void MutablePatternModifier::processQuantity(DecimalQuantity& fq, MicroProps& micros, UErrorCode& status) const { fParent->processQuantity(fq, micros, status); + micros.rounder.apply(fq, status); + if (micros.modMiddle != nullptr) { + return; + } // The unsafe code path performs self-mutation, so we need a const_cast. // This method needs to be const because it overrides a const method in the parent class. auto nonConstThis = const_cast(this); @@ -186,7 +197,7 @@ int32_t MutablePatternModifier::apply(FormattedStringBuilder& output, int32_t le UnicodeString(), 0, 0, - UNUM_FIELD_COUNT, + kUndefinedField, status); } CurrencySpacingEnabledModifier::applyCurrencySpacing( @@ -230,7 +241,7 @@ bool MutablePatternModifier::isStrong() const { return fStrong; } -bool MutablePatternModifier::containsField(UNumberFormatFields field) const { +bool MutablePatternModifier::containsField(Field field) const { (void)field; // This method is not currently used. UPRV_UNREACHABLE; @@ -263,7 +274,12 @@ int32_t MutablePatternModifier::insertSuffix(FormattedStringBuilder& sb, int pos /** This method contains the heart of the logic for rendering LDML affix strings. */ void MutablePatternModifier::prepareAffix(bool isPrefix) { PatternStringUtils::patternInfoToStringBuilder( - *fPatternInfo, isPrefix, fSignum, fSignDisplay, fPlural, fPerMilleReplacesPercent, currentAffix); + *fPatternInfo, + isPrefix, + PatternStringUtils::resolveSignDisplay(fSignDisplay, fSignum), + fPlural, + fPerMilleReplacesPercent, + currentAffix); } UnicodeString MutablePatternModifier::getSymbol(AffixPatternType type) const { @@ -280,23 +296,23 @@ UnicodeString MutablePatternModifier::getSymbol(AffixPatternType type) const { case AffixPatternType::TYPE_CURRENCY_SINGLE: { // UnitWidth ISO and HIDDEN overrides the singular currency symbol. if (fUnitWidth == UNumberUnitWidth::UNUM_UNIT_WIDTH_ISO_CODE) { - return fCurrencySymbols->getIntlCurrencySymbol(localStatus); + return fCurrencySymbols.getIntlCurrencySymbol(localStatus); } else if (fUnitWidth == UNumberUnitWidth::UNUM_UNIT_WIDTH_HIDDEN) { return UnicodeString(); } else if (fUnitWidth == UNumberUnitWidth::UNUM_UNIT_WIDTH_NARROW) { - return fCurrencySymbols->getNarrowCurrencySymbol(localStatus); + return fCurrencySymbols.getNarrowCurrencySymbol(localStatus); } else { - return fCurrencySymbols->getCurrencySymbol(localStatus); + return fCurrencySymbols.getCurrencySymbol(localStatus); } } case AffixPatternType::TYPE_CURRENCY_DOUBLE: - return fCurrencySymbols->getIntlCurrencySymbol(localStatus); + return fCurrencySymbols.getIntlCurrencySymbol(localStatus); case AffixPatternType::TYPE_CURRENCY_TRIPLE: // NOTE: This is the code path only for patterns containing "¤¤¤". // Plural currencies set via the API are formatted in LongNameHandler. // This code path is used by DecimalFormat via CurrencyPluralInfo. U_ASSERT(fPlural != StandardPlural::Form::COUNT); - return fCurrencySymbols->getPluralName(fPlural, localStatus); + return fCurrencySymbols.getPluralName(fPlural, localStatus); case AffixPatternType::TYPE_CURRENCY_QUAD: return UnicodeString(u"\uFFFD"); case AffixPatternType::TYPE_CURRENCY_QUINT: diff --git a/deps/icu-small/source/i18n/number_patternmodifier.h b/deps/icu-small/source/i18n/number_patternmodifier.h index b2c90e0af76354..5ba842d5692460 100644 --- a/deps/icu-small/source/i18n/number_patternmodifier.h +++ b/deps/icu-small/source/i18n/number_patternmodifier.h @@ -50,9 +50,11 @@ class U_I18N_API ImmutablePatternModifier : public MicroPropsGenerator, public U const Modifier* getModifier(Signum signum, StandardPlural::Form plural) const; + // Non-const method: + void addToChain(const MicroPropsGenerator* parent); + private: - ImmutablePatternModifier(AdoptingModifierStore* pm, const PluralRules* rules, - const MicroPropsGenerator* parent); + ImmutablePatternModifier(AdoptingModifierStore* pm, const PluralRules* rules); const LocalPointer pm; const PluralRules* rules; @@ -122,16 +124,18 @@ class U_I18N_API MutablePatternModifier * * @param symbols * The desired instance of DecimalFormatSymbols. - * @param currencySymbols - * The currency symbols to be used when substituting currency values into the affixes. + * @param currency + * The currency to be used when substituting currency values into the affixes. * @param unitWidth * The width used to render currencies. * @param rules * Required if the triple currency sign, "¤¤¤", appears in the pattern, which can be determined from the * convenience method {@link #needsPlurals()}. + * @param status + * Set if an error occurs while loading currency data. */ - void setSymbols(const DecimalFormatSymbols* symbols, const CurrencySymbols* currencySymbols, - UNumberUnitWidth unitWidth, const PluralRules* rules); + void setSymbols(const DecimalFormatSymbols* symbols, const CurrencyUnit& currency, + UNumberUnitWidth unitWidth, const PluralRules* rules, UErrorCode& status); /** * Sets attributes of the current number being processed. @@ -165,21 +169,6 @@ class U_I18N_API MutablePatternModifier */ ImmutablePatternModifier *createImmutable(UErrorCode &status); - /** - * Creates a new quantity-dependent Modifier that behaves the same as the current instance, but which is immutable - * and can be saved for future use. The number properties in the current instance are mutated; all other properties - * are left untouched. - * - *

- * CREATES A NEW HEAP OBJECT; THE CALLER GETS OWNERSHIP. - * - * @param parent - * The QuantityChain to which to chain this immutable. - * @return An immutable that supports both positive and negative numbers. - */ - ImmutablePatternModifier * - createImmutableAndChain(const MicroPropsGenerator *parent, UErrorCode &status); - MicroPropsGenerator &addToChain(const MicroPropsGenerator *parent); void processQuantity(DecimalQuantity &, MicroProps µs, UErrorCode &status) const U_OVERRIDE; @@ -193,7 +182,7 @@ class U_I18N_API MutablePatternModifier bool isStrong() const U_OVERRIDE; - bool containsField(UNumberFormatFields field) const U_OVERRIDE; + bool containsField(Field field) const U_OVERRIDE; void getParameters(Parameters& output) const U_OVERRIDE; @@ -219,7 +208,7 @@ class U_I18N_API MutablePatternModifier // Symbol details (initialized in setSymbols) const DecimalFormatSymbols *fSymbols; UNumberUnitWidth fUnitWidth; - const CurrencySymbols *fCurrencySymbols; + CurrencySymbols fCurrencySymbols; const PluralRules *fRules; // Number details (initialized in setNumberProperties) diff --git a/deps/icu-small/source/i18n/number_patternstring.cpp b/deps/icu-small/source/i18n/number_patternstring.cpp index c7212c1e5c23fe..9d845056069b80 100644 --- a/deps/icu-small/source/i18n/number_patternstring.cpp +++ b/deps/icu-small/source/i18n/number_patternstring.cpp @@ -686,10 +686,10 @@ UnicodeString PatternStringUtils::propertiesToPatternString(const DecimalFormatP int32_t exponentDigits = uprv_min(properties.minimumExponentDigits, dosMax); bool exponentShowPlusSign = properties.exponentSignAlwaysShown; - PropertiesAffixPatternProvider affixes(properties, status); + AutoAffixPatternProvider affixProvider(properties, status); // Prefixes - sb.append(affixes.getString(AffixPatternProvider::AFFIX_POS_PREFIX)); + sb.append(affixProvider.get().getString(AffixPatternProvider::AFFIX_POS_PREFIX)); int32_t afterPrefixPos = sb.length(); // Figure out the grouping sizes. @@ -778,7 +778,7 @@ UnicodeString PatternStringUtils::propertiesToPatternString(const DecimalFormatP // Suffixes int32_t beforeSuffixPos = sb.length(); - sb.append(affixes.getString(AffixPatternProvider::AFFIX_POS_SUFFIX)); + sb.append(affixProvider.get().getString(AffixPatternProvider::AFFIX_POS_SUFFIX)); // Resolve Padding if (paddingWidth > 0 && !paddingLocation.isNull()) { @@ -814,16 +814,16 @@ UnicodeString PatternStringUtils::propertiesToPatternString(const DecimalFormatP // Negative affixes // Ignore if the negative prefix pattern is "-" and the negative suffix is empty - if (affixes.hasNegativeSubpattern()) { + if (affixProvider.get().hasNegativeSubpattern()) { sb.append(u';'); - sb.append(affixes.getString(AffixPatternProvider::AFFIX_NEG_PREFIX)); + sb.append(affixProvider.get().getString(AffixPatternProvider::AFFIX_NEG_PREFIX)); // Copy the positive digit format into the negative. // This is optional; the pattern is the same as if '#' were appended here instead. // NOTE: It is not safe to append the UnicodeString to itself, so we need to copy. // See http://bugs.icu-project.org/trac/ticket/13707 UnicodeString copy(sb); sb.append(copy, afterPrefixPos, beforeSuffixPos - afterPrefixPos); - sb.append(affixes.getString(AffixPatternProvider::AFFIX_NEG_SUFFIX)); + sb.append(affixProvider.get().getString(AffixPatternProvider::AFFIX_NEG_SUFFIX)); } return sb; @@ -1000,23 +1000,19 @@ PatternStringUtils::convertLocalized(const UnicodeString& input, const DecimalFo } void PatternStringUtils::patternInfoToStringBuilder(const AffixPatternProvider& patternInfo, bool isPrefix, - Signum signum, UNumberSignDisplay signDisplay, + PatternSignType patternSignType, StandardPlural::Form plural, bool perMilleReplacesPercent, UnicodeString& output) { // Should the output render '+' where '-' would normally appear in the pattern? - bool plusReplacesMinusSign = signum != -1 && ( - signDisplay == UNUM_SIGN_ALWAYS || signDisplay == UNUM_SIGN_ACCOUNTING_ALWAYS || ( - signum == 1 && ( - signDisplay == UNUM_SIGN_EXCEPT_ZERO || - signDisplay == UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO))) && - patternInfo.positiveHasPlusSign() == false; - - // Should we use the affix from the negative subpattern? (If not, we will use the positive - // subpattern.) - // TODO: Deal with signum - bool useNegativeAffixPattern = patternInfo.hasNegativeSubpattern() && ( - signum == -1 || (patternInfo.negativeHasMinusSign() && plusReplacesMinusSign)); + bool plusReplacesMinusSign = (patternSignType == PATTERN_SIGN_TYPE_POS_SIGN) + && !patternInfo.positiveHasPlusSign(); + + // Should we use the affix from the negative subpattern? + // (If not, we will use the positive subpattern.) + bool useNegativeAffixPattern = patternInfo.hasNegativeSubpattern() + && (patternSignType == PATTERN_SIGN_TYPE_NEG + || (patternInfo.negativeHasMinusSign() && plusReplacesMinusSign)); // Resolve the flags for the affix pattern. int flags = 0; @@ -1035,8 +1031,8 @@ void PatternStringUtils::patternInfoToStringBuilder(const AffixPatternProvider& bool prependSign; if (!isPrefix || useNegativeAffixPattern) { prependSign = false; - } else if (signum == -1) { - prependSign = signDisplay != UNUM_SIGN_NEVER; + } else if (patternSignType == PATTERN_SIGN_TYPE_NEG) { + prependSign = true; } else { prependSign = plusReplacesMinusSign; } @@ -1065,4 +1061,60 @@ void PatternStringUtils::patternInfoToStringBuilder(const AffixPatternProvider& } } +PatternSignType PatternStringUtils::resolveSignDisplay(UNumberSignDisplay signDisplay, Signum signum) { + switch (signDisplay) { + case UNUM_SIGN_AUTO: + case UNUM_SIGN_ACCOUNTING: + switch (signum) { + case SIGNUM_NEG: + case SIGNUM_NEG_ZERO: + return PATTERN_SIGN_TYPE_NEG; + case SIGNUM_POS_ZERO: + case SIGNUM_POS: + return PATTERN_SIGN_TYPE_POS; + default: + break; + } + break; + + case UNUM_SIGN_ALWAYS: + case UNUM_SIGN_ACCOUNTING_ALWAYS: + switch (signum) { + case SIGNUM_NEG: + case SIGNUM_NEG_ZERO: + return PATTERN_SIGN_TYPE_NEG; + case SIGNUM_POS_ZERO: + case SIGNUM_POS: + return PATTERN_SIGN_TYPE_POS_SIGN; + default: + break; + } + break; + + case UNUM_SIGN_EXCEPT_ZERO: + case UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO: + switch (signum) { + case SIGNUM_NEG: + return PATTERN_SIGN_TYPE_NEG; + case SIGNUM_NEG_ZERO: + case SIGNUM_POS_ZERO: + return PATTERN_SIGN_TYPE_POS; + case SIGNUM_POS: + return PATTERN_SIGN_TYPE_POS_SIGN; + default: + break; + } + break; + + case UNUM_SIGN_NEVER: + return PATTERN_SIGN_TYPE_POS; + + default: + break; + } + + UPRV_UNREACHABLE; + return PATTERN_SIGN_TYPE_POS; +} + #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/number_patternstring.h b/deps/icu-small/source/i18n/number_patternstring.h index 819c74d4bd886d..3e962cc134f98f 100644 --- a/deps/icu-small/source/i18n/number_patternstring.h +++ b/deps/icu-small/source/i18n/number_patternstring.h @@ -22,6 +22,18 @@ namespace impl { // Forward declaration class PatternParser; +// Note: the order of fields in this enum matters for parsing. +enum PatternSignType { + /** Render using normal positive subpattern rules */ + PATTERN_SIGN_TYPE_POS, + /** Render using rules to force the display of a plus sign */ + PATTERN_SIGN_TYPE_POS_SIGN, + /** Render using negative subpattern rules */ + PATTERN_SIGN_TYPE_NEG, + /** Count for looping over the possibilities */ + PATTERN_SIGN_TYPE_COUNT +}; + // Exported as U_I18N_API because it is a public member field of exported ParsedSubpatternInfo struct U_I18N_API Endpoints { int32_t start = 0; @@ -295,10 +307,12 @@ class U_I18N_API PatternStringUtils { * substitution, and plural forms for CurrencyPluralInfo. */ static void patternInfoToStringBuilder(const AffixPatternProvider& patternInfo, bool isPrefix, - Signum signum, UNumberSignDisplay signDisplay, + PatternSignType patternSignType, StandardPlural::Form plural, bool perMilleReplacesPercent, UnicodeString& output); + static PatternSignType resolveSignDisplay(UNumberSignDisplay signDisplay, Signum signum); + private: /** @return The number of chars inserted. */ static int escapePaddingString(UnicodeString input, UnicodeString& output, int startIndex, diff --git a/deps/icu-small/source/i18n/number_rounding.cpp b/deps/icu-small/source/i18n/number_rounding.cpp index 813d4b680d497b..3ffce673ad0885 100644 --- a/deps/icu-small/source/i18n/number_rounding.cpp +++ b/deps/icu-small/source/i18n/number_rounding.cpp @@ -294,9 +294,7 @@ RoundingImpl::RoundingImpl(const Precision& precision, UNumberFormatRoundingMode } RoundingImpl RoundingImpl::passThrough() { - RoundingImpl retval; - retval.fPassThrough = true; - return retval; + return {}; } bool RoundingImpl::isSignificantDigits() const { diff --git a/deps/icu-small/source/i18n/number_roundingutils.h b/deps/icu-small/source/i18n/number_roundingutils.h index 9c2c47b6e41b31..3e37f3195408fe 100644 --- a/deps/icu-small/source/i18n/number_roundingutils.h +++ b/deps/icu-small/source/i18n/number_roundingutils.h @@ -150,7 +150,7 @@ digits_t doubleFractionLength(double input, int8_t* singleDigit); */ class RoundingImpl { public: - RoundingImpl() = default; // default constructor: leaves object in undefined state + RoundingImpl() = default; // defaults to pass-through rounder RoundingImpl(const Precision& precision, UNumberFormatRoundingMode roundingMode, const CurrencyUnit& currency, UErrorCode& status); @@ -186,7 +186,7 @@ class RoundingImpl { private: Precision fPrecision; UNumberFormatRoundingMode fRoundingMode; - bool fPassThrough; + bool fPassThrough = true; // default value }; diff --git a/deps/icu-small/source/i18n/number_scientific.cpp b/deps/icu-small/source/i18n/number_scientific.cpp index 20aa45bff01959..33862d7a887ef4 100644 --- a/deps/icu-small/source/i18n/number_scientific.cpp +++ b/deps/icu-small/source/i18n/number_scientific.cpp @@ -44,21 +44,21 @@ int32_t ScientificModifier::apply(FormattedStringBuilder &output, int32_t /*left i += output.insert( i, fHandler->fSymbols->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kExponentialSymbol), - UNUM_EXPONENT_SYMBOL_FIELD, + {UFIELD_CATEGORY_NUMBER, UNUM_EXPONENT_SYMBOL_FIELD}, status); if (fExponent < 0 && fHandler->fSettings.fExponentSignDisplay != UNUM_SIGN_NEVER) { i += output.insert( i, fHandler->fSymbols ->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kMinusSignSymbol), - UNUM_EXPONENT_SIGN_FIELD, + {UFIELD_CATEGORY_NUMBER, UNUM_EXPONENT_SIGN_FIELD}, status); } else if (fExponent >= 0 && fHandler->fSettings.fExponentSignDisplay == UNUM_SIGN_ALWAYS) { i += output.insert( i, fHandler->fSymbols ->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kPlusSignSymbol), - UNUM_EXPONENT_SIGN_FIELD, + {UFIELD_CATEGORY_NUMBER, UNUM_EXPONENT_SIGN_FIELD}, status); } // Append the exponent digits (using a simple inline algorithm) @@ -70,7 +70,7 @@ int32_t ScientificModifier::apply(FormattedStringBuilder &output, int32_t /*left i - j, d, *fHandler->fSymbols, - UNUM_EXPONENT_FIELD, + {UFIELD_CATEGORY_NUMBER, UNUM_EXPONENT_FIELD}, status); } return i - rightIndex; @@ -93,7 +93,7 @@ bool ScientificModifier::isStrong() const { return true; } -bool ScientificModifier::containsField(UNumberFormatFields field) const { +bool ScientificModifier::containsField(Field field) const { (void)field; // This method is not used for inner modifiers. UPRV_UNREACHABLE; @@ -149,6 +149,11 @@ void ScientificHandler::processQuantity(DecimalQuantity &quantity, MicroProps &m mod.set(exponent, this); micros.modInner = &mod; + // Change the exponent only after we select appropriate plural form + // for formatting purposes so that we preserve expected formatted + // string behavior. + quantity.adjustExponent(exponent); + // We already performed rounding. Do not perform it again. micros.rounder = RoundingImpl::passThrough(); } diff --git a/deps/icu-small/source/i18n/number_scientific.h b/deps/icu-small/source/i18n/number_scientific.h index 1c9ce1efa80a3f..a55d5ed1d410de 100644 --- a/deps/icu-small/source/i18n/number_scientific.h +++ b/deps/icu-small/source/i18n/number_scientific.h @@ -30,7 +30,7 @@ class U_I18N_API ScientificModifier : public UMemory, public Modifier { bool isStrong() const U_OVERRIDE; - bool containsField(UNumberFormatFields field) const U_OVERRIDE; + bool containsField(Field field) const U_OVERRIDE; void getParameters(Parameters& output) const U_OVERRIDE; diff --git a/deps/icu-small/source/i18n/number_skeletons.cpp b/deps/icu-small/source/i18n/number_skeletons.cpp index 4025539239b786..4ba2647986c755 100644 --- a/deps/icu-small/source/i18n/number_skeletons.cpp +++ b/deps/icu-small/source/i18n/number_skeletons.cpp @@ -21,6 +21,9 @@ #include "uinvchar.h" #include "charstr.h" #include "string_segment.h" +#include "unicode/errorcode.h" +#include "util.h" +#include "measunit_impl.h" using namespace icu; using namespace icu::number; @@ -93,12 +96,29 @@ void U_CALLCONV initNumberSkeletons(UErrorCode& status) { b.add(u"precision-increment", STEM_PRECISION_INCREMENT, status); b.add(u"measure-unit", STEM_MEASURE_UNIT, status); b.add(u"per-measure-unit", STEM_PER_MEASURE_UNIT, status); + b.add(u"unit", STEM_UNIT, status); b.add(u"currency", STEM_CURRENCY, status); b.add(u"integer-width", STEM_INTEGER_WIDTH, status); b.add(u"numbering-system", STEM_NUMBERING_SYSTEM, status); b.add(u"scale", STEM_SCALE, status); if (U_FAILURE(status)) { return; } + // Section 3 (concise tokens): + b.add(u"K", STEM_COMPACT_SHORT, status); + b.add(u"KK", STEM_COMPACT_LONG, status); + b.add(u"%", STEM_PERCENT, status); + b.add(u"%x100", STEM_PERCENT_100, status); + b.add(u",_", STEM_GROUP_OFF, status); + b.add(u",?", STEM_GROUP_MIN2, status); + b.add(u",!", STEM_GROUP_ON_ALIGNED, status); + b.add(u"+!", STEM_SIGN_ALWAYS, status); + b.add(u"+_", STEM_SIGN_NEVER, status); + b.add(u"()", STEM_SIGN_ACCOUNTING, status); + b.add(u"()!", STEM_SIGN_ACCOUNTING_ALWAYS, status); + b.add(u"+?", STEM_SIGN_EXCEPT_ZERO, status); + b.add(u"()?", STEM_SIGN_ACCOUNTING_EXCEPT_ZERO, status); + if (U_FAILURE(status)) { return; } + // Build the CharsTrie // TODO: Use SLOW or FAST here? UnicodeString result; @@ -529,6 +549,7 @@ MacroProps skeleton::parseSkeleton( case STATE_INCREMENT_PRECISION: case STATE_MEASURE_UNIT: case STATE_PER_MEASURE_UNIT: + case STATE_IDENTIFIER_UNIT: case STATE_CURRENCY_UNIT: case STATE_INTEGER_WIDTH: case STATE_NUMBERING_SYSTEM: @@ -557,13 +578,21 @@ skeleton::parseStem(const StringSegment& segment, const UCharsTrie& stemTrie, Se // First check for "blueprint" stems, which start with a "signal char" switch (segment.charAt(0)) { case u'.': - CHECK_NULL(seen, precision, status); + CHECK_NULL(seen, precision, status); blueprint_helpers::parseFractionStem(segment, macros, status); return STATE_FRACTION_PRECISION; case u'@': - CHECK_NULL(seen, precision, status); + CHECK_NULL(seen, precision, status); blueprint_helpers::parseDigitsStem(segment, macros, status); return STATE_NULL; + case u'E': + CHECK_NULL(seen, notation, status); + blueprint_helpers::parseScientificStem(segment, macros, status); + return STATE_NULL; + case u'0': + CHECK_NULL(seen, integerWidth, status); + blueprint_helpers::parseIntegerStem(segment, macros, status); + return STATE_NULL; default: break; } @@ -587,7 +616,7 @@ skeleton::parseStem(const StringSegment& segment, const UCharsTrie& stemTrie, Se case STEM_SCIENTIFIC: case STEM_ENGINEERING: case STEM_NOTATION_SIMPLE: - CHECK_NULL(seen, notation, status); + CHECK_NULL(seen, notation, status); macros.notation = stem_to_object::notation(stem); switch (stem) { case STEM_SCIENTIFIC: @@ -600,15 +629,22 @@ skeleton::parseStem(const StringSegment& segment, const UCharsTrie& stemTrie, Se case STEM_BASE_UNIT: case STEM_PERCENT: case STEM_PERMILLE: - CHECK_NULL(seen, unit, status); + CHECK_NULL(seen, unit, status); macros.unit = stem_to_object::unit(stem); return STATE_NULL; + case STEM_PERCENT_100: + CHECK_NULL(seen, scale, status); + CHECK_NULL(seen, unit, status); + macros.scale = Scale::powerOfTen(2); + macros.unit = NoUnit::percent(); + return STATE_NULL; + case STEM_PRECISION_INTEGER: case STEM_PRECISION_UNLIMITED: case STEM_PRECISION_CURRENCY_STANDARD: case STEM_PRECISION_CURRENCY_CASH: - CHECK_NULL(seen, precision, status); + CHECK_NULL(seen, precision, status); macros.precision = stem_to_object::precision(stem); switch (stem) { case STEM_PRECISION_INTEGER: @@ -625,7 +661,7 @@ skeleton::parseStem(const StringSegment& segment, const UCharsTrie& stemTrie, Se case STEM_ROUNDING_MODE_HALF_DOWN: case STEM_ROUNDING_MODE_HALF_UP: case STEM_ROUNDING_MODE_UNNECESSARY: - CHECK_NULL(seen, roundingMode, status); + CHECK_NULL(seen, roundingMode, status); macros.roundingMode = stem_to_object::roundingMode(stem); return STATE_NULL; @@ -634,12 +670,12 @@ skeleton::parseStem(const StringSegment& segment, const UCharsTrie& stemTrie, Se case STEM_GROUP_AUTO: case STEM_GROUP_ON_ALIGNED: case STEM_GROUP_THOUSANDS: - CHECK_NULL(seen, grouper, status); + CHECK_NULL(seen, grouper, status); macros.grouper = Grouper::forStrategy(stem_to_object::groupingStrategy(stem)); return STATE_NULL; case STEM_LATIN: - CHECK_NULL(seen, symbols, status); + CHECK_NULL(seen, symbols, status); macros.symbols.setTo(NumberingSystem::createInstanceByName("latn", status)); return STATE_NULL; @@ -648,7 +684,7 @@ skeleton::parseStem(const StringSegment& segment, const UCharsTrie& stemTrie, Se case STEM_UNIT_WIDTH_FULL_NAME: case STEM_UNIT_WIDTH_ISO_CODE: case STEM_UNIT_WIDTH_HIDDEN: - CHECK_NULL(seen, unitWidth, status); + CHECK_NULL(seen, unitWidth, status); macros.unitWidth = stem_to_object::unitWidth(stem); return STATE_NULL; @@ -659,44 +695,49 @@ skeleton::parseStem(const StringSegment& segment, const UCharsTrie& stemTrie, Se case STEM_SIGN_ACCOUNTING_ALWAYS: case STEM_SIGN_EXCEPT_ZERO: case STEM_SIGN_ACCOUNTING_EXCEPT_ZERO: - CHECK_NULL(seen, sign, status); + CHECK_NULL(seen, sign, status); macros.sign = stem_to_object::signDisplay(stem); return STATE_NULL; case STEM_DECIMAL_AUTO: case STEM_DECIMAL_ALWAYS: - CHECK_NULL(seen, decimal, status); + CHECK_NULL(seen, decimal, status); macros.decimal = stem_to_object::decimalSeparatorDisplay(stem); return STATE_NULL; // Stems requiring an option: case STEM_PRECISION_INCREMENT: - CHECK_NULL(seen, precision, status); + CHECK_NULL(seen, precision, status); return STATE_INCREMENT_PRECISION; case STEM_MEASURE_UNIT: - CHECK_NULL(seen, unit, status); + CHECK_NULL(seen, unit, status); return STATE_MEASURE_UNIT; case STEM_PER_MEASURE_UNIT: - CHECK_NULL(seen, perUnit, status); + CHECK_NULL(seen, perUnit, status); return STATE_PER_MEASURE_UNIT; + case STEM_UNIT: + CHECK_NULL(seen, unit, status); + CHECK_NULL(seen, perUnit, status); + return STATE_IDENTIFIER_UNIT; + case STEM_CURRENCY: - CHECK_NULL(seen, unit, status); + CHECK_NULL(seen, unit, status); return STATE_CURRENCY_UNIT; case STEM_INTEGER_WIDTH: - CHECK_NULL(seen, integerWidth, status); + CHECK_NULL(seen, integerWidth, status); return STATE_INTEGER_WIDTH; case STEM_NUMBERING_SYSTEM: - CHECK_NULL(seen, symbols, status); + CHECK_NULL(seen, symbols, status); return STATE_NUMBERING_SYSTEM; case STEM_SCALE: - CHECK_NULL(seen, scale, status); + CHECK_NULL(seen, scale, status); return STATE_SCALE; default: @@ -719,6 +760,9 @@ ParseState skeleton::parseOption(ParseState stem, const StringSegment& segment, case STATE_PER_MEASURE_UNIT: blueprint_helpers::parseMeasurePerUnitOption(segment, macros, status); return STATE_NULL; + case STATE_IDENTIFIER_UNIT: + blueprint_helpers::parseIdentifierUnitOption(segment, macros, status); + return STATE_NULL; case STATE_INCREMENT_PRECISION: blueprint_helpers::parseIncrementOption(segment, macros, status); return STATE_NULL; @@ -843,10 +887,6 @@ void GeneratorHelpers::generateSkeleton(const MacroProps& macros, UnicodeString& status = U_UNSUPPORTED_ERROR; return; } - if (macros.currencySymbols != nullptr) { - status = U_UNSUPPORTED_ERROR; - return; - } // Remove the trailing space if (sb.length() > 0) { @@ -857,7 +897,7 @@ void GeneratorHelpers::generateSkeleton(const MacroProps& macros, UnicodeString& bool blueprint_helpers::parseExponentWidthOption(const StringSegment& segment, MacroProps& macros, UErrorCode&) { - if (segment.charAt(0) != u'+') { + if (!isWildcardChar(segment.charAt(0))) { return false; } int32_t offset = 1; @@ -879,7 +919,7 @@ bool blueprint_helpers::parseExponentWidthOption(const StringSegment& segment, M void blueprint_helpers::generateExponentWidthOption(int32_t minExponentDigits, UnicodeString& sb, UErrorCode&) { - sb.append(u'+'); + sb.append(kWildcardChar); appendMultiple(sb, u'e', minExponentDigits); } @@ -981,7 +1021,7 @@ void blueprint_helpers::generateMeasureUnitOption(const MeasureUnit& measureUnit void blueprint_helpers::parseMeasurePerUnitOption(const StringSegment& segment, MacroProps& macros, UErrorCode& status) { - // A little bit of a hack: safe the current unit (numerator), call the main measure unit + // A little bit of a hack: save the current unit (numerator), call the main measure unit // parsing code, put back the numerator unit, and put the new unit into per-unit. MeasureUnit numerator = macros.unit; parseMeasureUnitOption(segment, macros, status); @@ -990,6 +1030,33 @@ void blueprint_helpers::parseMeasurePerUnitOption(const StringSegment& segment, macros.unit = numerator; } +void blueprint_helpers::parseIdentifierUnitOption(const StringSegment& segment, MacroProps& macros, + UErrorCode& status) { + // Need to do char <-> UChar conversion... + U_ASSERT(U_SUCCESS(status)); + CharString buffer; + SKELETON_UCHAR_TO_CHAR(buffer, segment.toTempUnicodeString(), 0, segment.length(), status); + + ErrorCode internalStatus; + auto fullUnit = MeasureUnitImpl::forIdentifier(buffer.toStringPiece(), internalStatus); + if (internalStatus.isFailure()) { + // throw new SkeletonSyntaxException("Invalid core unit identifier", segment, e); + status = U_NUMBER_SKELETON_SYNTAX_ERROR; + return; + } + + // TODO(ICU-20941): Clean this up. + for (int32_t i = 0; i < fullUnit.units.length(); i++) { + SingleUnitImpl* subUnit = fullUnit.units[i]; + if (subUnit->dimensionality > 0) { + macros.unit = macros.unit.product(subUnit->build(status), status); + } else { + subUnit->dimensionality *= -1; + macros.perUnit = macros.perUnit.product(subUnit->build(status), status); + } + } +} + void blueprint_helpers::parseFractionStem(const StringSegment& segment, MacroProps& macros, UErrorCode& status) { U_ASSERT(segment.charAt(0) == u'.'); @@ -1004,7 +1071,7 @@ void blueprint_helpers::parseFractionStem(const StringSegment& segment, MacroPro } } if (offset < segment.length()) { - if (segment.charAt(offset) == u'+') { + if (isWildcardChar(segment.charAt(offset))) { maxFrac = -1; offset++; } else { @@ -1027,7 +1094,11 @@ void blueprint_helpers::parseFractionStem(const StringSegment& segment, MacroPro } // Use the public APIs to enforce bounds checking if (maxFrac == -1) { - macros.precision = Precision::minFraction(minFrac); + if (minFrac == 0) { + macros.precision = Precision::unlimited(); + } else { + macros.precision = Precision::minFraction(minFrac); + } } else { macros.precision = Precision::minMaxFraction(minFrac, maxFrac); } @@ -1042,7 +1113,7 @@ blueprint_helpers::generateFractionStem(int32_t minFrac, int32_t maxFrac, Unicod sb.append(u'.'); appendMultiple(sb, u'0', minFrac); if (maxFrac == -1) { - sb.append(u'+'); + sb.append(kWildcardChar); } else { appendMultiple(sb, u'#', maxFrac - minFrac); } @@ -1051,9 +1122,9 @@ blueprint_helpers::generateFractionStem(int32_t minFrac, int32_t maxFrac, Unicod void blueprint_helpers::parseDigitsStem(const StringSegment& segment, MacroProps& macros, UErrorCode& status) { U_ASSERT(segment.charAt(0) == u'@'); - int offset = 0; - int minSig = 0; - int maxSig; + int32_t offset = 0; + int32_t minSig = 0; + int32_t maxSig; for (; offset < segment.length(); offset++) { if (segment.charAt(offset) == u'@') { minSig++; @@ -1062,7 +1133,7 @@ blueprint_helpers::parseDigitsStem(const StringSegment& segment, MacroProps& mac } } if (offset < segment.length()) { - if (segment.charAt(offset) == u'+') { + if (isWildcardChar(segment.charAt(offset))) { maxSig = -1; offset++; } else { @@ -1095,12 +1166,81 @@ void blueprint_helpers::generateDigitsStem(int32_t minSig, int32_t maxSig, UnicodeString& sb, UErrorCode&) { appendMultiple(sb, u'@', minSig); if (maxSig == -1) { - sb.append(u'+'); + sb.append(kWildcardChar); } else { appendMultiple(sb, u'#', maxSig - minSig); } } +void blueprint_helpers::parseScientificStem(const StringSegment& segment, MacroProps& macros, UErrorCode& status) { + U_ASSERT(segment.charAt(0) == u'E'); + { + int32_t offset = 1; + if (segment.length() == offset) { + goto fail; + } + bool isEngineering = false; + if (segment.charAt(offset) == u'E') { + isEngineering = true; + offset++; + if (segment.length() == offset) { + goto fail; + } + } + UNumberSignDisplay signDisplay = UNUM_SIGN_AUTO; + if (segment.charAt(offset) == u'+') { + offset++; + if (segment.length() == offset) { + goto fail; + } + if (segment.charAt(offset) == u'!') { + signDisplay = UNUM_SIGN_ALWAYS; + } else if (segment.charAt(offset) == u'?') { + signDisplay = UNUM_SIGN_EXCEPT_ZERO; + } else { + goto fail; + } + offset++; + if (segment.length() == offset) { + goto fail; + } + } + int32_t minDigits = 0; + for (; offset < segment.length(); offset++) { + if (segment.charAt(offset) != u'0') { + goto fail; + } + minDigits++; + } + macros.notation = (isEngineering ? Notation::engineering() : Notation::scientific()) + .withExponentSignDisplay(signDisplay) + .withMinExponentDigits(minDigits); + return; + } + fail: void(); + // throw new SkeletonSyntaxException("Invalid scientific stem", segment); + status = U_NUMBER_SKELETON_SYNTAX_ERROR; + return; +} + +void blueprint_helpers::parseIntegerStem(const StringSegment& segment, MacroProps& macros, UErrorCode& status) { + U_ASSERT(segment.charAt(0) == u'0'); + int32_t offset = 1; + for (; offset < segment.length(); offset++) { + if (segment.charAt(offset) != u'0') { + offset--; + break; + } + } + if (offset < segment.length()) { + // throw new SkeletonSyntaxException("Invalid integer stem", segment); + status = U_NUMBER_SKELETON_SYNTAX_ERROR; + return; + } + macros.integerWidth = IntegerWidth::zeroFillTo(offset); + return; +} + bool blueprint_helpers::parseFracSigOption(const StringSegment& segment, MacroProps& macros, UErrorCode& status) { if (segment.charAt(0) != u'@') { @@ -1122,7 +1262,7 @@ bool blueprint_helpers::parseFracSigOption(const StringSegment& segment, MacroPr // Invalid: @, @@, @@@ // Invalid: @@#, @@##, @@@# if (offset < segment.length()) { - if (segment.charAt(offset) == u'+') { + if (isWildcardChar(segment.charAt(offset))) { maxSig = -1; offset++; } else if (minSig > 1) { @@ -1211,7 +1351,7 @@ void blueprint_helpers::parseIntegerWidthOption(const StringSegment& segment, Ma int32_t offset = 0; int32_t minInt = 0; int32_t maxInt; - if (segment.charAt(0) == u'+') { + if (isWildcardChar(segment.charAt(0))) { maxInt = -1; offset++; } else { @@ -1252,7 +1392,7 @@ void blueprint_helpers::parseIntegerWidthOption(const StringSegment& segment, Ma void blueprint_helpers::generateIntegerWidthOption(int32_t minInt, int32_t maxInt, UnicodeString& sb, UErrorCode&) { if (maxInt == -1) { - sb.append(u'+'); + sb.append(kWildcardChar); } else { appendMultiple(sb, u'#', maxInt - minInt); } @@ -1543,4 +1683,49 @@ bool GeneratorHelpers::scale(const MacroProps& macros, UnicodeString& sb, UError } +// Definitions of public API methods (put here for dependency disentanglement) + +#if (U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN) && defined(_MSC_VER) +// Ignore MSVC warning 4661. This is generated for NumberFormatterSettings<>::toSkeleton() as this method +// is defined elsewhere (in number_skeletons.cpp). The compiler is warning that the explicit template instantiation +// inside this single translation unit (CPP file) is incomplete, and thus it isn't sure if the template class is +// fully defined. However, since each translation unit explicitly instantiates all the necessary template classes, +// they will all be passed to the linker, and the linker will still find and export all the class members. +#pragma warning(push) +#pragma warning(disable: 4661) +#endif + +template +UnicodeString NumberFormatterSettings::toSkeleton(UErrorCode& status) const { + if (U_FAILURE(status)) { + return ICU_Utility::makeBogusString(); + } + if (fMacros.copyErrorTo(status)) { + return ICU_Utility::makeBogusString(); + } + return skeleton::generate(fMacros, status); +} + +// Declare all classes that implement NumberFormatterSettings +// See https://stackoverflow.com/a/495056/1407170 +template +class icu::number::NumberFormatterSettings; +template +class icu::number::NumberFormatterSettings; + +UnlocalizedNumberFormatter +NumberFormatter::forSkeleton(const UnicodeString& skeleton, UErrorCode& status) { + return skeleton::create(skeleton, nullptr, status); +} + +UnlocalizedNumberFormatter +NumberFormatter::forSkeleton(const UnicodeString& skeleton, UParseError& perror, UErrorCode& status) { + return skeleton::create(skeleton, &perror, status); +} + +#if (U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN) && defined(_MSC_VER) +// Warning 4661. +#pragma warning(pop) +#endif + #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/number_skeletons.h b/deps/icu-small/source/i18n/number_skeletons.h index 59af771928fbd0..d9b2c0ee0b19ab 100644 --- a/deps/icu-small/source/i18n/number_skeletons.h +++ b/deps/icu-small/source/i18n/number_skeletons.h @@ -46,6 +46,7 @@ enum ParseState { STATE_INCREMENT_PRECISION, STATE_MEASURE_UNIT, STATE_PER_MEASURE_UNIT, + STATE_IDENTIFIER_UNIT, STATE_CURRENCY_UNIT, STATE_INTEGER_WIDTH, STATE_NUMBERING_SYSTEM, @@ -71,6 +72,7 @@ enum StemEnum { STEM_BASE_UNIT, STEM_PERCENT, STEM_PERMILLE, + STEM_PERCENT_100, // concise-only STEM_PRECISION_INTEGER, STEM_PRECISION_UNLIMITED, STEM_PRECISION_CURRENCY_STANDARD, @@ -109,12 +111,24 @@ enum StemEnum { STEM_PRECISION_INCREMENT, STEM_MEASURE_UNIT, STEM_PER_MEASURE_UNIT, + STEM_UNIT, STEM_CURRENCY, STEM_INTEGER_WIDTH, STEM_NUMBERING_SYSTEM, STEM_SCALE, }; +/** Default wildcard char, accepted on input and printed in output */ +constexpr char16_t kWildcardChar = u'*'; + +/** Alternative wildcard char, accept on input but not printed in output */ +constexpr char16_t kAltWildcardChar = u'+'; + +/** Checks whether the char is a wildcard on input */ +inline bool isWildcardChar(char16_t c) { + return c == kWildcardChar || c == kAltWildcardChar; +} + /** * Creates a NumberFormatter corresponding to the given skeleton string. * @@ -226,6 +240,8 @@ void generateMeasureUnitOption(const MeasureUnit& measureUnit, UnicodeString& sb void parseMeasurePerUnitOption(const StringSegment& segment, MacroProps& macros, UErrorCode& status); +void parseIdentifierUnitOption(const StringSegment& segment, MacroProps& macros, UErrorCode& status); + void parseFractionStem(const StringSegment& segment, MacroProps& macros, UErrorCode& status); void generateFractionStem(int32_t minFrac, int32_t maxFrac, UnicodeString& sb, UErrorCode& status); @@ -234,6 +250,14 @@ void parseDigitsStem(const StringSegment& segment, MacroProps& macros, UErrorCod void generateDigitsStem(int32_t minSig, int32_t maxSig, UnicodeString& sb, UErrorCode& status); +void parseScientificStem(const StringSegment& segment, MacroProps& macros, UErrorCode& status); + +// Note: no generateScientificStem since this syntax was added later in ICU 67 + +void parseIntegerStem(const StringSegment& segment, MacroProps& macros, UErrorCode& status); + +// Note: no generateIntegerStem since this syntax was added later in ICU 67 + /** @return Whether we successfully found and parsed a frac-sig option. */ bool parseFracSigOption(const StringSegment& segment, MacroProps& macros, UErrorCode& status); diff --git a/deps/icu-small/source/i18n/number_types.h b/deps/icu-small/source/i18n/number_types.h index d62aa6a66b30d3..5c2b8cf8b5d19c 100644 --- a/deps/icu-small/source/i18n/number_types.h +++ b/deps/icu-small/source/i18n/number_types.h @@ -92,9 +92,11 @@ enum CompactType { }; enum Signum { - SIGNUM_NEG = -1, - SIGNUM_ZERO = 0, - SIGNUM_POS = 1 + SIGNUM_NEG = 0, + SIGNUM_NEG_ZERO = 1, + SIGNUM_POS_ZERO = 2, + SIGNUM_POS = 3, + SIGNUM_COUNT = 4, }; @@ -192,7 +194,7 @@ class U_I18N_API Modifier { /** * Whether the modifier contains at least one occurrence of the given field. */ - virtual bool containsField(UNumberFormatFields field) const = 0; + virtual bool containsField(Field field) const = 0; /** * A fill-in for getParameters(). obj will always be set; if non-null, the other diff --git a/deps/icu-small/source/i18n/number_utypes.h b/deps/icu-small/source/i18n/number_utypes.h index 6dbe5bee68fb71..7a1b7a4e80ac31 100644 --- a/deps/icu-small/source/i18n/number_utypes.h +++ b/deps/icu-small/source/i18n/number_utypes.h @@ -30,10 +30,12 @@ const DecimalQuantity* validateUFormattedNumberToDecimalQuantity( * * The DecimalQuantity is not currently being used by FormattedNumber, but at some point it could be used * to add a toDecNumber() or similar method. + * + * Exported as U_I18N_API for tests */ -class UFormattedNumberData : public FormattedValueStringBuilderImpl { +class U_I18N_API UFormattedNumberData : public FormattedValueStringBuilderImpl { public: - UFormattedNumberData() : FormattedValueStringBuilderImpl(0) {} + UFormattedNumberData() : FormattedValueStringBuilderImpl(kUndefinedField) {} virtual ~UFormattedNumberData(); DecimalQuantity quantity; diff --git a/deps/icu-small/source/i18n/numparse_affixes.cpp b/deps/icu-small/source/i18n/numparse_affixes.cpp index 4f83e0dd4076c3..187830fb6fc0df 100644 --- a/deps/icu-small/source/i18n/numparse_affixes.cpp +++ b/deps/icu-small/source/i18n/numparse_affixes.cpp @@ -271,8 +271,6 @@ void AffixMatcherWarehouse::createAffixMatchers(const AffixPatternProvider& patt // Use initial capacity of 6, the highest possible number of AffixMatchers. UnicodeString sb; bool includeUnpaired = 0 != (parseFlags & PARSE_FLAG_INCLUDE_UNPAIRED_AFFIXES); - UNumberSignDisplay signDisplay = (0 != (parseFlags & PARSE_FLAG_PLUS_SIGN_ALLOWED)) ? UNUM_SIGN_ALWAYS - : UNUM_SIGN_AUTO; int32_t numAffixMatchers = 0; int32_t numAffixPatternMatchers = 0; @@ -281,13 +279,23 @@ void AffixMatcherWarehouse::createAffixMatchers(const AffixPatternProvider& patt AffixPatternMatcher* posSuffix = nullptr; // Pre-process the affix strings to resolve LDML rules like sign display. - for (int8_t signumInt = 1; signumInt >= -1; signumInt--) { - auto signum = static_cast(signumInt); + for (int8_t typeInt = 0; typeInt < PATTERN_SIGN_TYPE_COUNT; typeInt++) { + auto type = static_cast(typeInt); + + // Skip affixes in some cases + if (type == PATTERN_SIGN_TYPE_POS + && 0 != (parseFlags & PARSE_FLAG_PLUS_SIGN_ALLOWED)) { + continue; + } + if (type == PATTERN_SIGN_TYPE_POS_SIGN + && 0 == (parseFlags & PARSE_FLAG_PLUS_SIGN_ALLOWED)) { + continue; + } // Generate Prefix bool hasPrefix = false; PatternStringUtils::patternInfoToStringBuilder( - patternInfo, true, signum, signDisplay, StandardPlural::OTHER, false, sb); + patternInfo, true, type, StandardPlural::OTHER, false, sb); fAffixPatternMatchers[numAffixPatternMatchers] = AffixPatternMatcher::fromAffixPattern( sb, *fTokenWarehouse, parseFlags, &hasPrefix, status); AffixPatternMatcher* prefix = hasPrefix ? &fAffixPatternMatchers[numAffixPatternMatchers++] @@ -296,13 +304,13 @@ void AffixMatcherWarehouse::createAffixMatchers(const AffixPatternProvider& patt // Generate Suffix bool hasSuffix = false; PatternStringUtils::patternInfoToStringBuilder( - patternInfo, false, signum, signDisplay, StandardPlural::OTHER, false, sb); + patternInfo, false, type, StandardPlural::OTHER, false, sb); fAffixPatternMatchers[numAffixPatternMatchers] = AffixPatternMatcher::fromAffixPattern( sb, *fTokenWarehouse, parseFlags, &hasSuffix, status); AffixPatternMatcher* suffix = hasSuffix ? &fAffixPatternMatchers[numAffixPatternMatchers++] : nullptr; - if (signum == 1) { + if (type == PATTERN_SIGN_TYPE_POS) { posPrefix = prefix; posSuffix = suffix; } else if (equals(prefix, posPrefix) && equals(suffix, posSuffix)) { @@ -311,17 +319,17 @@ void AffixMatcherWarehouse::createAffixMatchers(const AffixPatternProvider& patt } // Flags for setting in the ParsedNumber; the token matchers may add more. - int flags = (signum == -1) ? FLAG_NEGATIVE : 0; + int flags = (type == PATTERN_SIGN_TYPE_NEG) ? FLAG_NEGATIVE : 0; // Note: it is indeed possible for posPrefix and posSuffix to both be null. // We still need to add that matcher for strict mode to work. fAffixMatchers[numAffixMatchers++] = {prefix, suffix, flags}; if (includeUnpaired && prefix != nullptr && suffix != nullptr) { // The following if statements are designed to prevent adding two identical matchers. - if (signum == 1 || !equals(prefix, posPrefix)) { + if (type == PATTERN_SIGN_TYPE_POS || !equals(prefix, posPrefix)) { fAffixMatchers[numAffixMatchers++] = {prefix, nullptr, flags}; } - if (signum == 1 || !equals(suffix, posSuffix)) { + if (type == PATTERN_SIGN_TYPE_POS || !equals(suffix, posSuffix)) { fAffixMatchers[numAffixMatchers++] = {nullptr, suffix, flags}; } } diff --git a/deps/icu-small/source/i18n/numparse_affixes.h b/deps/icu-small/source/i18n/numparse_affixes.h index e498483fbca8cf..2ac69df109519e 100644 --- a/deps/icu-small/source/i18n/numparse_affixes.h +++ b/deps/icu-small/source/i18n/numparse_affixes.h @@ -28,7 +28,7 @@ using ::icu::number::impl::TokenConsumer; using ::icu::number::impl::CurrencySymbols; -class CodePointMatcher : public NumberParseMatcher, public UMemory { +class U_I18N_API CodePointMatcher : public NumberParseMatcher, public UMemory { public: CodePointMatcher() = default; // WARNING: Leaves the object in an unusable state diff --git a/deps/icu-small/source/i18n/numparse_impl.cpp b/deps/icu-small/source/i18n/numparse_impl.cpp index bf5829061a1511..4b76da1c149a74 100644 --- a/deps/icu-small/source/i18n/numparse_impl.cpp +++ b/deps/icu-small/source/i18n/numparse_impl.cpp @@ -83,23 +83,14 @@ NumberParserImpl::createParserFromProperties(const number::impl::DecimalFormatPr const DecimalFormatSymbols& symbols, bool parseCurrency, UErrorCode& status) { Locale locale = symbols.getLocale(); - PropertiesAffixPatternProvider localPAPP; - CurrencyPluralInfoAffixProvider localCPIAP; - AffixPatternProvider* affixProvider; - if (properties.currencyPluralInfo.fPtr.isNull()) { - localPAPP.setTo(properties, status); - affixProvider = &localPAPP; - } else { - localCPIAP.setTo(*properties.currencyPluralInfo.fPtr, properties, status); - affixProvider = &localCPIAP; - } - if (affixProvider == nullptr || U_FAILURE(status)) { return nullptr; } + AutoAffixPatternProvider affixProvider(properties, status); + if (U_FAILURE(status)) { return nullptr; } CurrencyUnit currency = resolveCurrency(properties, locale, status); CurrencySymbols currencySymbols(currency, locale, symbols, status); bool isStrict = properties.parseMode.getOrDefault(PARSE_MODE_STRICT) == PARSE_MODE_STRICT; Grouper grouper = Grouper::forProperties(properties); int parseFlags = 0; - if (affixProvider == nullptr || U_FAILURE(status)) { return nullptr; } + if (U_FAILURE(status)) { return nullptr; } if (!properties.parseCaseSensitive) { parseFlags |= PARSE_FLAG_IGNORE_CASE; } @@ -121,7 +112,7 @@ NumberParserImpl::createParserFromProperties(const number::impl::DecimalFormatPr if (grouper.getPrimary() <= 0) { parseFlags |= PARSE_FLAG_GROUPING_DISABLED; } - if (parseCurrency || affixProvider->hasCurrencySign()) { + if (parseCurrency || affixProvider.get().hasCurrencySign()) { parseFlags |= PARSE_FLAG_MONETARY_SEPARATORS; } if (!parseCurrency) { @@ -143,13 +134,13 @@ NumberParserImpl::createParserFromProperties(const number::impl::DecimalFormatPr parser->fLocalMatchers.affixTokenMatcherWarehouse = {&affixSetupData}; parser->fLocalMatchers.affixMatcherWarehouse = {&parser->fLocalMatchers.affixTokenMatcherWarehouse}; parser->fLocalMatchers.affixMatcherWarehouse.createAffixMatchers( - *affixProvider, *parser, ignorables, parseFlags, status); + affixProvider.get(), *parser, ignorables, parseFlags, status); //////////////////////// /// CURRENCY MATCHER /// //////////////////////// - if (parseCurrency || affixProvider->hasCurrencySign()) { + if (parseCurrency || affixProvider.get().hasCurrencySign()) { parser->addMatcher(parser->fLocalMatchers.currency = {currencySymbols, symbols, parseFlags, status}); } @@ -159,10 +150,10 @@ NumberParserImpl::createParserFromProperties(const number::impl::DecimalFormatPr // ICU-TC meeting, April 11, 2018: accept percent/permille only if it is in the pattern, // and to maintain regressive behavior, divide by 100 even if no percent sign is present. - if (!isStrict && affixProvider->containsSymbolType(AffixPatternType::TYPE_PERCENT, status)) { + if (!isStrict && affixProvider.get().containsSymbolType(AffixPatternType::TYPE_PERCENT, status)) { parser->addMatcher(parser->fLocalMatchers.percent = {symbols}); } - if (!isStrict && affixProvider->containsSymbolType(AffixPatternType::TYPE_PERMILLE, status)) { + if (!isStrict && affixProvider.get().containsSymbolType(AffixPatternType::TYPE_PERMILLE, status)) { parser->addMatcher(parser->fLocalMatchers.permille = {symbols}); } diff --git a/deps/icu-small/source/i18n/numrange_fluent.cpp b/deps/icu-small/source/i18n/numrange_fluent.cpp index 654cafaf00bc82..33179026f8d2b5 100644 --- a/deps/icu-small/source/i18n/numrange_fluent.cpp +++ b/deps/icu-small/source/i18n/numrange_fluent.cpp @@ -379,23 +379,6 @@ UPRV_FORMATTED_VALUE_SUBCLASS_AUTO_IMPL(FormattedNumberRange) #define UPRV_NOARG -UBool FormattedNumberRange::nextFieldPosition(FieldPosition& fieldPosition, UErrorCode& status) const { - UPRV_FORMATTED_VALUE_METHOD_GUARD(FALSE) - // NOTE: MSVC sometimes complains when implicitly converting between bool and UBool - return fData->nextFieldPosition(fieldPosition, status); -} - -void FormattedNumberRange::getAllFieldPositions(FieldPositionIterator& iterator, UErrorCode& status) const { - FieldPositionIteratorHandler fpih(&iterator, status); - getAllFieldPositionsImpl(fpih, status); -} - -void FormattedNumberRange::getAllFieldPositionsImpl( - FieldPositionIteratorHandler& fpih, UErrorCode& status) const { - UPRV_FORMATTED_VALUE_METHOD_GUARD(UPRV_NOARG) - fData->getAllFieldPositions(fpih, status); -} - UnicodeString FormattedNumberRange::getFirstDecimal(UErrorCode& status) const { UPRV_FORMATTED_VALUE_METHOD_GUARD(ICU_Utility::makeBogusString()) return fData->quantity1.toScientificString(); diff --git a/deps/icu-small/source/i18n/numrange_impl.cpp b/deps/icu-small/source/i18n/numrange_impl.cpp index 7d732b31ec177a..9fb3dee861f1f6 100644 --- a/deps/icu-small/source/i18n/numrange_impl.cpp +++ b/deps/icu-small/source/i18n/numrange_impl.cpp @@ -210,7 +210,7 @@ NumberRangeFormatterImpl::NumberRangeFormatterImpl(const RangeMacroProps& macros getNumberRangeData(macros.locale.getName(), nsName, data, status); if (U_FAILURE(status)) { return; } fRangeFormatter = data.rangePattern; - fApproximatelyModifier = {data.approximatelyPattern, UNUM_FIELD_COUNT, false}; + fApproximatelyModifier = {data.approximatelyPattern, kUndefinedField, false}; // TODO: Get locale from PluralRules instead? fPluralRanges.initialize(macros.locale, status); @@ -368,7 +368,8 @@ void NumberRangeFormatterImpl::formatRange(UFormattedNumberRangeData& data, // Only collapse if the modifier is a unit. // TODO: Make a better way to check for a unit? // TODO: Handle case where the modifier has both notation and unit (compact currency)? - if (!mm->containsField(UNUM_CURRENCY_FIELD) && !mm->containsField(UNUM_PERCENT_FIELD)) { + if (!mm->containsField({UFIELD_CATEGORY_NUMBER, UNUM_CURRENCY_FIELD}) + && !mm->containsField({UFIELD_CATEGORY_NUMBER, UNUM_PERCENT_FIELD})) { collapseMiddle = false; } } else if (fCollapse == UNUM_RANGE_COLLAPSE_AUTO) { @@ -416,7 +417,7 @@ void NumberRangeFormatterImpl::formatRange(UFormattedNumberRangeData& data, 0, &lengthPrefix, &lengthSuffix, - UNUM_FIELD_COUNT, + kUndefinedField, status); if (U_FAILURE(status)) { return; } lengthInfix = lengthRange - lengthPrefix - lengthSuffix; @@ -434,10 +435,10 @@ void NumberRangeFormatterImpl::formatRange(UFormattedNumberRangeData& data, if (repeatInner || repeatMiddle || repeatOuter) { // Add spacing if there is not already spacing if (!PatternProps::isWhiteSpace(string.charAt(UPRV_INDEX_1))) { - lengthInfix += string.insertCodePoint(UPRV_INDEX_1, u'\u0020', UNUM_FIELD_COUNT, status); + lengthInfix += string.insertCodePoint(UPRV_INDEX_1, u'\u0020', kUndefinedField, status); } if (!PatternProps::isWhiteSpace(string.charAt(UPRV_INDEX_2 - 1))) { - lengthInfix += string.insertCodePoint(UPRV_INDEX_2, u'\u0020', UNUM_FIELD_COUNT, status); + lengthInfix += string.insertCodePoint(UPRV_INDEX_2, u'\u0020', kUndefinedField, status); } } } diff --git a/deps/icu-small/source/i18n/numrange_impl.h b/deps/icu-small/source/i18n/numrange_impl.h index f88e300913642d..8f4c8a40ba2fdc 100644 --- a/deps/icu-small/source/i18n/numrange_impl.h +++ b/deps/icu-small/source/i18n/numrange_impl.h @@ -31,7 +31,7 @@ namespace impl { */ class UFormattedNumberRangeData : public FormattedValueStringBuilderImpl { public: - UFormattedNumberRangeData() : FormattedValueStringBuilderImpl(0) {} + UFormattedNumberRangeData() : FormattedValueStringBuilderImpl(kUndefinedField) {} virtual ~UFormattedNumberRangeData(); DecimalQuantity quantity1; diff --git a/deps/icu-small/source/i18n/numsys.cpp b/deps/icu-small/source/i18n/numsys.cpp index e3fe54bc1b3f7e..d8b901c0d74b68 100644 --- a/deps/icu-small/source/i18n/numsys.cpp +++ b/deps/icu-small/source/i18n/numsys.cpp @@ -118,7 +118,7 @@ NumberingSystem::createInstance(const Locale & inLocale, UErrorCode& status) { UBool nsResolved = TRUE; UBool usingFallback = FALSE; - char buffer[ULOC_KEYWORDS_CAPACITY]; + char buffer[ULOC_KEYWORDS_CAPACITY] = ""; int32_t count = inLocale.getKeywordValue("numbers", buffer, sizeof(buffer), status); if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING) { // the "numbers" keyword exceeds ULOC_KEYWORDS_CAPACITY; ignore and use default. diff --git a/deps/icu-small/source/i18n/plurrule.cpp b/deps/icu-small/source/i18n/plurrule.cpp index aa950a51f0f0c6..54e3b2cd86c960 100644 --- a/deps/icu-small/source/i18n/plurrule.cpp +++ b/deps/icu-small/source/i18n/plurrule.cpp @@ -1693,6 +1693,7 @@ double FixedDecimal::getPluralOperand(PluralOperand operand) const { case PLURAL_OPERAND_F: return static_cast(decimalDigits); case PLURAL_OPERAND_T: return static_cast(decimalDigitsWithoutTrailingZeros); case PLURAL_OPERAND_V: return visibleDecimalDigitCount; + case PLURAL_OPERAND_E: return 0; default: UPRV_UNREACHABLE; // unexpected. } diff --git a/deps/icu-small/source/i18n/plurrule_impl.h b/deps/icu-small/source/i18n/plurrule_impl.h index f23ae168569d66..a18cb0847a840e 100644 --- a/deps/icu-small/source/i18n/plurrule_impl.h +++ b/deps/icu-small/source/i18n/plurrule_impl.h @@ -214,6 +214,12 @@ enum PluralOperand { */ PLURAL_OPERAND_W, + /** + * Suppressed exponent for compact notation (exponent needed in + * scientific notation with compact notation to approximate i). + */ + PLURAL_OPERAND_E, + /** * THIS OPERAND IS DEPRECATED AND HAS BEEN REMOVED FROM THE SPEC. * diff --git a/deps/icu-small/source/i18n/quantityformatter.cpp b/deps/icu-small/source/i18n/quantityformatter.cpp index e88b70fbd71795..9c9aa99b670944 100644 --- a/deps/icu-small/source/i18n/quantityformatter.cpp +++ b/deps/icu-small/source/i18n/quantityformatter.cpp @@ -204,7 +204,8 @@ void QuantityFormatter::formatAndSelect( if (U_FAILURE(status)) { return; } - output.append(result, UNUM_FIELD_COUNT, status); + // This code path is probably RBNF. Use the generic numeric field. + output.append(result, kGeneralNumericField, status); if (U_FAILURE(status)) { return; } diff --git a/deps/icu-small/source/i18n/regexcmp.cpp b/deps/icu-small/source/i18n/regexcmp.cpp index a360dcf72f3f6c..7b67ce82b5db12 100644 --- a/deps/icu-small/source/i18n/regexcmp.cpp +++ b/deps/icu-small/source/i18n/regexcmp.cpp @@ -148,9 +148,6 @@ void RegexCompile::compile( if (U_FAILURE(*fStatus)) { return; } - fRXPat->fStaticSets = RegexStaticSets::gStaticSets->fPropSets; - fRXPat->fStaticSets8 = RegexStaticSets::gStaticSets->fPropSets8; - // Initialize the pattern scanning state machine fPatternLength = utext_nativeLength(pat); @@ -1257,11 +1254,14 @@ UBool RegexCompile::doParseActions(int32_t action) break; case doBackslashX: + #if UCONFIG_NO_BREAK_ITERATION==1 + // Grapheme Cluster Boundary requires ICU break iteration. + error(U_UNSUPPORTED_ERROR); + #endif fixLiterals(FALSE); appendOp(URX_BACKSLASH_X, 0); break; - case doBackslashZ: fixLiterals(FALSE); appendOp(URX_DOLLAR, 0); @@ -1565,15 +1565,15 @@ UBool RegexCompile::doParseActions(int32_t action) case doSetBackslash_s: { UnicodeSet *set = (UnicodeSet *)fSetStack.peek(); - set->addAll(*RegexStaticSets::gStaticSets->fPropSets[URX_ISSPACE_SET]); + set->addAll(RegexStaticSets::gStaticSets->fPropSets[URX_ISSPACE_SET]); break; } case doSetBackslash_S: { UnicodeSet *set = (UnicodeSet *)fSetStack.peek(); - UnicodeSet SSet(*RegexStaticSets::gStaticSets->fPropSets[URX_ISSPACE_SET]); - SSet.complement(); + UnicodeSet SSet; + SSet.addAll(RegexStaticSets::gStaticSets->fPropSets[URX_ISSPACE_SET]).complement(); set->addAll(SSet); break; } @@ -1642,15 +1642,15 @@ UBool RegexCompile::doParseActions(int32_t action) case doSetBackslash_w: { UnicodeSet *set = (UnicodeSet *)fSetStack.peek(); - set->addAll(*RegexStaticSets::gStaticSets->fPropSets[URX_ISWORD_SET]); + set->addAll(RegexStaticSets::gStaticSets->fPropSets[URX_ISWORD_SET]); break; } case doSetBackslash_W: { UnicodeSet *set = (UnicodeSet *)fSetStack.peek(); - UnicodeSet SSet(*RegexStaticSets::gStaticSets->fPropSets[URX_ISWORD_SET]); - SSet.complement(); + UnicodeSet SSet; + SSet.addAll(RegexStaticSets::gStaticSets->fPropSets[URX_ISWORD_SET]).complement(); set->addAll(SSet); break; } @@ -2425,6 +2425,7 @@ void RegexCompile::compileSet(UnicodeSet *theSet) { // The set contains two or more chars. (the normal case) // Put it into the compiled pattern as a set. + theSet->freeze(); int32_t setNumber = fRXPat->fSets->size(); fRXPat->fSets->addElement(theSet, *fStatus); appendOp(URX_SETREF, setNumber); @@ -2818,8 +2819,8 @@ void RegexCompile::matchStartType() { if (currentLen == 0) { int32_t sn = URX_VAL(op); U_ASSERT(sn>0 && snfStaticSets[sn]; - fRXPat->fInitialChars->addAll(*s); + const UnicodeSet &s = RegexStaticSets::gStaticSets->fPropSets[sn]; + fRXPat->fInitialChars->addAll(s); numInitialStrings += 2; } currentLen = safeIncrement(currentLen, 1); @@ -2831,9 +2832,8 @@ void RegexCompile::matchStartType() { case URX_STAT_SETREF_N: if (currentLen == 0) { int32_t sn = URX_VAL(op); - const UnicodeSet *s = fRXPat->fStaticSets[sn]; - UnicodeSet sc(*s); - sc.complement(); + UnicodeSet sc; + sc.addAll(RegexStaticSets::gStaticSets->fPropSets[sn]).complement(); fRXPat->fInitialChars->addAll(sc); numInitialStrings += 2; } @@ -4420,7 +4420,8 @@ UnicodeSet *RegexCompile::createSetForProperty(const UnicodeString &propName, UB status = U_ZERO_ERROR; if (propName.caseCompare(u"word", -1, 0) == 0) { - set.adoptInsteadAndCheckErrorCode(new UnicodeSet(*(fRXPat->fStaticSets[URX_ISWORD_SET])), status); + set.adoptInsteadAndCheckErrorCode( + RegexStaticSets::gStaticSets->fPropSets[URX_ISWORD_SET].cloneAsThawed(), status); break; } if (propName.compare(u"all", -1) == 0) { diff --git a/deps/icu-small/source/i18n/regexcst.h b/deps/icu-small/source/i18n/regexcst.h index a07d85a277c3dd..526c253e3bcb8d 100644 --- a/deps/icu-small/source/i18n/regexcst.h +++ b/deps/icu-small/source/i18n/regexcst.h @@ -20,117 +20,117 @@ U_NAMESPACE_BEGIN // // Character classes for regex pattern scanning. // - static const uint8_t kRuleSet_ascii_letter = 128; - static const uint8_t kRuleSet_digit_char = 129; + static const uint8_t kRuleSet_digit_char = 128; + static const uint8_t kRuleSet_ascii_letter = 129; static const uint8_t kRuleSet_rule_char = 130; - + constexpr uint32_t kRuleSet_count = 131-128; enum Regex_PatternParseAction { - doSetBackslash_V, - doSetBackslash_h, - doBeginNamedBackRef, - doSetMatchMode, - doEnterQuoteMode, - doOpenCaptureParen, - doContinueNamedCapture, - doSetBackslash_d, - doBeginMatchMode, - doBackslashX, - doSetPosixProp, - doIntervalError, + doSetBackslash_D, + doBackslashh, + doBackslashH, doSetLiteralEscaped, - doSetBackslash_s, - doNOP, - doBackslashv, - doOpenLookBehind, - doPatStart, - doPossessiveInterval, - doOpenAtomicParen, doOpenLookAheadNeg, - doBackslashd, + doCompleteNamedBackRef, + doPatStart, + doBackslashS, + doBackslashD, + doNGStar, + doNOP, + doBackslashX, + doSetLiteral, + doContinueNamedCapture, + doBackslashG, + doBackslashR, + doSetBegin, + doSetBackslash_v, + doPossessivePlus, + doPerlInline, doBackslashZ, - doIntervalUpperDigit, - doBadNamedCapture, - doSetDifference2, doSetAddAmp, - doSetNamedChar, - doNamedChar, - doSetBackslash_H, - doBackslashb, - doBackslashz, doSetBeginDifference1, - doOpenLookAhead, - doMatchModeParen, - doBackslashV, - doIntevalLowerDigit, - doCaret, - doSetEnd, + doIntervalError, doSetNegate, - doBackslashS, - doOrOperator, - doBackslashB, - doBackslashw, - doBackslashR, + doIntervalInit, + doSetIntersection2, + doPossessiveInterval, doRuleError, - doDotAny, - doMatchMode, - doSetBackslash_W, - doNGPlus, - doSetBackslash_D, - doPossessiveOpt, - doSetNamedRange, + doBackslashW, + doContinueNamedBackRef, + doOpenNonCaptureParen, + doExit, + doSetNamedChar, + doSetBackslash_V, doConditionalExpr, - doBackslashs, + doEscapeError, + doBadOpenParenType, doPossessiveStar, + doSetAddDash, + doEscapedLiteralChar, + doSetBackslash_w, + doIntervalUpperDigit, + doBackslashv, + doSetBackslash_S, + doSetNoCloseError, + doSetProp, + doBackslashB, + doSetEnd, + doSetRange, + doMatchModeParen, doPlus, - doBadOpenParenType, + doBackslashV, + doSetMatchMode, + doBackslashz, + doSetNamedRange, + doOpenLookBehindNeg, + doInterval, + doBadNamedCapture, + doBeginMatchMode, + doBackslashd, + doPatFinish, + doNamedChar, + doNGPlus, + doSetDifference2, + doSetBackslash_H, doCloseParen, - doNGInterval, - doSetProp, + doDotAny, + doOpenCaptureParen, + doEnterQuoteMode, + doOpenAtomicParen, + doBadModeFlag, + doSetBackslash_d, + doSetFinish, + doProperty, + doBeginNamedBackRef, doBackRef, - doSetBeginUnion, - doEscapeError, doOpt, - doSetBeginIntersection1, - doPossessivePlus, - doBackslashD, - doOpenLookBehindNeg, - doSetBegin, - doSetIntersection2, - doCompleteNamedBackRef, - doSetRange, doDollar, - doBackslashH, - doExit, - doNGOpt, - doOpenNonCaptureParen, - doBackslashA, - doSetBackslash_v, - doBackslashh, - doBadModeFlag, - doSetNoCloseError, - doIntervalSame, - doSetAddDash, - doBackslashW, - doPerlInline, - doSetOpError, - doSetLiteral, - doPatFinish, doBeginNamedCapture, - doEscapedLiteralChar, + doNGInterval, + doSetOpError, + doSetPosixProp, + doSetBeginIntersection1, + doBackslashb, + doSetBeginUnion, + doIntevalLowerDigit, + doSetBackslash_h, + doStar, + doMatchMode, + doBackslashA, + doOpenLookBehind, + doPossessiveOpt, + doOrOperator, + doBackslashw, + doBackslashs, doLiteralChar, doSuppressComments, + doCaret, + doIntervalSame, + doNGOpt, + doOpenLookAhead, + doSetBackslash_W, doMismatchedParenErr, - doNGStar, - doSetFinish, - doInterval, - doBackslashG, - doStar, - doSetBackslash_w, - doSetBackslash_S, - doProperty, - doContinueNamedBackRef, - doIntervalInit, + doSetBackslash_s, rbbiLastAction}; //------------------------------------------------------------------------------- @@ -197,7 +197,7 @@ static const struct RegexTableEl gRuleParseStateTable[] = { , {doBadOpenParenType, 255, 206,0, FALSE} // 45 , {doOpenLookBehind, 61 /* = */, 2, 20, TRUE} // 46 open-paren-lookbehind , {doOpenLookBehindNeg, 33 /* ! */, 2, 20, TRUE} // 47 - , {doBeginNamedCapture, 128, 64,0, FALSE} // 48 + , {doBeginNamedCapture, 129, 64,0, FALSE} // 48 , {doBadOpenParenType, 255, 206,0, FALSE} // 49 , {doNOP, 41 /* ) */, 255,0, TRUE} // 50 paren-comment , {doMismatchedParenErr, 253, 206,0, FALSE} // 51 @@ -213,8 +213,8 @@ static const struct RegexTableEl gRuleParseStateTable[] = { , {doSetMatchMode, 41 /* ) */, 2,0, TRUE} // 61 , {doMatchModeParen, 58 /* : */, 2, 14, TRUE} // 62 , {doBadModeFlag, 255, 206,0, FALSE} // 63 - , {doContinueNamedCapture, 128, 64,0, TRUE} // 64 named-capture - , {doContinueNamedCapture, 129, 64,0, TRUE} // 65 + , {doContinueNamedCapture, 129, 64,0, TRUE} // 64 named-capture + , {doContinueNamedCapture, 128, 64,0, TRUE} // 65 , {doOpenCaptureParen, 62 /* > */, 2, 14, TRUE} // 66 , {doBadNamedCapture, 255, 206,0, FALSE} // 67 , {doNGStar, 63 /* ? */, 20,0, TRUE} // 68 quant-star @@ -226,13 +226,13 @@ static const struct RegexTableEl gRuleParseStateTable[] = { , {doNGOpt, 63 /* ? */, 20,0, TRUE} // 74 quant-opt , {doPossessiveOpt, 43 /* + */, 20,0, TRUE} // 75 , {doOpt, 255, 20,0, FALSE} // 76 - , {doNOP, 129, 79,0, FALSE} // 77 interval-open + , {doNOP, 128, 79,0, FALSE} // 77 interval-open , {doIntervalError, 255, 206,0, FALSE} // 78 - , {doIntevalLowerDigit, 129, 79,0, TRUE} // 79 interval-lower + , {doIntevalLowerDigit, 128, 79,0, TRUE} // 79 interval-lower , {doNOP, 44 /* , */, 83,0, TRUE} // 80 , {doIntervalSame, 125 /* } */, 86,0, TRUE} // 81 , {doIntervalError, 255, 206,0, FALSE} // 82 - , {doIntervalUpperDigit, 129, 83,0, TRUE} // 83 interval-upper + , {doIntervalUpperDigit, 128, 83,0, TRUE} // 83 interval-upper , {doNOP, 125 /* } */, 86,0, TRUE} // 84 , {doIntervalError, 255, 206,0, FALSE} // 85 , {doNGInterval, 63 /* ? */, 20,0, TRUE} // 86 interval-type @@ -261,15 +261,15 @@ static const struct RegexTableEl gRuleParseStateTable[] = { , {doBackslashX, 88 /* X */, 14,0, TRUE} // 109 , {doBackslashZ, 90 /* Z */, 2,0, TRUE} // 110 , {doBackslashz, 122 /* z */, 2,0, TRUE} // 111 - , {doBackRef, 129, 14,0, TRUE} // 112 + , {doBackRef, 128, 14,0, TRUE} // 112 , {doEscapeError, 253, 206,0, FALSE} // 113 , {doEscapedLiteralChar, 255, 14,0, TRUE} // 114 , {doBeginNamedBackRef, 60 /* < */, 117,0, TRUE} // 115 named-backref , {doBadNamedCapture, 255, 206,0, FALSE} // 116 - , {doContinueNamedBackRef, 128, 119,0, TRUE} // 117 named-backref-2 + , {doContinueNamedBackRef, 129, 119,0, TRUE} // 117 named-backref-2 , {doBadNamedCapture, 255, 206,0, FALSE} // 118 - , {doContinueNamedBackRef, 128, 119,0, TRUE} // 119 named-backref-3 - , {doContinueNamedBackRef, 129, 119,0, TRUE} // 120 + , {doContinueNamedBackRef, 129, 119,0, TRUE} // 119 named-backref-3 + , {doContinueNamedBackRef, 128, 119,0, TRUE} // 120 , {doCompleteNamedBackRef, 62 /* > */, 14,0, TRUE} // 121 , {doBadNamedCapture, 255, 206,0, FALSE} // 122 , {doSetNegate, 94 /* ^ */, 126,0, TRUE} // 123 set-open diff --git a/deps/icu-small/source/i18n/regexcst.pl b/deps/icu-small/source/i18n/regexcst.pl index 6c06b4eb5fc56a..3ae259048aec43 100755 --- a/deps/icu-small/source/i18n/regexcst.pl +++ b/deps/icu-small/source/i18n/regexcst.pl @@ -10,13 +10,13 @@ # regexcst.pl # Compile the regular expression paser state table data into initialized C data. # Usage: -# cd icu/source/i18n +# cd icu4c/source/i18n # perl regexcst.pl < regexcst.txt > regexcst.h # # The output file, regexcst.h, is included by some of the .cpp regex # implementation files. This perl script is NOT run as part # of a normal ICU build. It is run by hand when needed, and the -# regexcst.h generated file is put back into cvs. +# regexcst.h generated file is put back into the source code repository. # # See regexcst.txt for a description of the input format for this script. # @@ -201,6 +201,8 @@ die if ($errors>0); +print "// © 2016 and later: Unicode, Inc. and others.\n"; +print "// License & terms of use: http://www.unicode.org/copyright.html\n"; print "//---------------------------------------------------------------------------------\n"; print "//\n"; print "// Generated Header File. Do not edit by hand.\n"; @@ -246,6 +248,7 @@ $i++; } } +print " constexpr uint32_t kRuleSet_count = $i-128;"; print "\n\n"; # diff --git a/deps/icu-small/source/i18n/regexst.cpp b/deps/icu-small/source/i18n/regexst.cpp index ad74ee508e7133..7e3992fc80339d 100644 --- a/deps/icu-small/source/i18n/regexst.cpp +++ b/deps/icu-small/source/i18n/regexst.cpp @@ -35,216 +35,101 @@ // generated by a Perl script. #include "regexst.h" - - U_NAMESPACE_BEGIN +// "Rule Char" Characters are those with special meaning, and therefore +// need to be escaped to appear as literals in a regexp. +constexpr char16_t const *gRuleSet_rule_chars = u"*?+[(){}^$|\\."; -//------------------------------------------------------------------------------ // -// Unicode Set pattern strings for all of the required constant sets. -// Initialized with hex values for portability to EBCDIC based machines. -// Really ugly, but there's no good way to avoid it. +// The backslash escape characters that ICU's unescape() function will handle. // -//------------------------------------------------------------------------------ - -// "Rule Char" Characters are those with no special meaning, and therefore do not -// need to be escaped to appear as literals in a regexp. Expressed -// as the inverse of those needing escaping -- [^\*\?\+\[\(\)\{\}\^\$\|\\\.] -static const UChar gRuleSet_rule_char_pattern[] = { - // [ ^ \ * \ ? \ + \ [ \ ( / ) - 0x5b, 0x5e, 0x5c, 0x2a, 0x5c, 0x3f, 0x5c, 0x2b, 0x5c, 0x5b, 0x5c, 0x28, 0x5c, 0x29, - // \ { \ } \ ^ \ $ \ | \ \ \ . ] - 0x5c, 0x7b,0x5c, 0x7d, 0x5c, 0x5e, 0x5c, 0x24, 0x5c, 0x7c, 0x5c, 0x5c, 0x5c, 0x2e, 0x5d, 0}; +constexpr char16_t const *gUnescapeChars = u"acefnrtuUx"; // -// Here are the backslash escape characters that ICU's unescape() function -// will handle. +// Unicode Set pattern for Regular Expression \w // -static const UChar gUnescapeCharPattern[] = { -// [ a c e f n r t u U x ] - 0x5b, 0x61, 0x63, 0x65, 0x66, 0x6e, 0x72, 0x74, 0x75, 0x55, 0x78, 0x5d, 0}; - - -// -// Unicode Set Definitions for Regular Expression \w -// -static const UChar gIsWordPattern[] = { -// [ \ p { A l p h a b e t i c } - 0x5b, 0x5c, 0x70, 0x7b, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x62, 0x65, 0x74, 0x69, 0x63, 0x7d, -// \ p { M } Mark - 0x5c, 0x70, 0x7b, 0x4d, 0x7d, -// \ p { N d } Digit_Numeric - 0x5c, 0x70, 0x7b, 0x4e, 0x64, 0x7d, -// \ p { P c } Connector_Punctuation - 0x5c, 0x70, 0x7b, 0x50, 0x63, 0x7d, -// \ u 2 0 0 c \ u 2 0 0 d ] - 0x5c, 0x75, 0x32, 0x30, 0x30, 0x63, 0x5c, 0x75, 0x32, 0x30, 0x30, 0x64, 0x5d, 0}; - +constexpr char16_t const *gIsWordPattern = u"[\\p{Alphabetic}\\p{M}\\p{Nd}\\p{Pc}\\u200c\\u200d]"; // // Unicode Set Definitions for Regular Expression \s // -static const UChar gIsSpacePattern[] = { -// [ \ p { W h i t e S p a c e } ] - 0x5b, 0x5c, 0x70, 0x7b, 0x57, 0x68, 0x69, 0x74, 0x65, 0x53, 0x70, 0x61, 0x63, 0x65, 0x7d, 0x5d, 0}; - +constexpr char16_t const *gIsSpacePattern = u"[\\p{WhiteSpace}]"; // // UnicodeSets used in implementation of Grapheme Cluster detection, \X // -static const UChar gGC_ControlPattern[] = { -// [ [ : Z l : ] [ : Z p : ] - 0x5b, 0x5b, 0x3a, 0x5A, 0x6c, 0x3a, 0x5d, 0x5b, 0x3a, 0x5A, 0x70, 0x3a, 0x5d, -// [ : C c : ] [ : C f : ] - - 0x5b, 0x3a, 0x43, 0x63, 0x3a, 0x5d, 0x5b, 0x3a, 0x43, 0x66, 0x3a, 0x5d, 0x2d, -// [ : G r a p h e m e _ - 0x5b, 0x3a, 0x47, 0x72, 0x61, 0x70, 0x68, 0x65, 0x6d, 0x65, 0x5f, -// E x t e n d : ] ] - 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x3a, 0x5d, 0x5d, 0}; +constexpr char16_t const *gGC_ControlPattern = u"[[:Zl:][:Zp:][:Cc:][:Cf:]-[:Grapheme_Extend:]]"; +constexpr char16_t const *gGC_ExtendPattern = u"[\\p{Grapheme_Extend}]"; +constexpr char16_t const *gGC_LPattern = u"[\\p{Hangul_Syllable_Type=L}]"; +constexpr char16_t const *gGC_VPattern = u"[\\p{Hangul_Syllable_Type=V}]"; +constexpr char16_t const *gGC_TPattern = u"[\\p{Hangul_Syllable_Type=T}]"; +constexpr char16_t const *gGC_LVPattern = u"[\\p{Hangul_Syllable_Type=LV}]"; +constexpr char16_t const *gGC_LVTPattern = u"[\\p{Hangul_Syllable_Type=LVT}]"; -static const UChar gGC_ExtendPattern[] = { -// [ \ p { G r a p h e m e _ - 0x5b, 0x5c, 0x70, 0x7b, 0x47, 0x72, 0x61, 0x70, 0x68, 0x65, 0x6d, 0x65, 0x5f, -// E x t e n d } ] - 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x7d, 0x5d, 0}; -static const UChar gGC_LPattern[] = { -// [ \ p { H a n g u l _ S y l - 0x5b, 0x5c, 0x70, 0x7b, 0x48, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x5f, 0x53, 0x79, 0x6c, -// l a b l e _ T y p e = L } ] - 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x54, 0x79, 0x70, 0x65, 0x3d, 0x4c, 0x7d, 0x5d, 0}; - -static const UChar gGC_VPattern[] = { -// [ \ p { H a n g u l _ S y l - 0x5b, 0x5c, 0x70, 0x7b, 0x48, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x5f, 0x53, 0x79, 0x6c, -// l a b l e _ T y p e = V } ] - 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x54, 0x79, 0x70, 0x65, 0x3d, 0x56, 0x7d, 0x5d, 0}; - -static const UChar gGC_TPattern[] = { -// [ \ p { H a n g u l _ S y l - 0x5b, 0x5c, 0x70, 0x7b, 0x48, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x5f, 0x53, 0x79, 0x6c, -// l a b l e _ T y p e = T } ] - 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x54, 0x79, 0x70, 0x65, 0x3d, 0x54, 0x7d, 0x5d, 0}; - -static const UChar gGC_LVPattern[] = { -// [ \ p { H a n g u l _ S y l - 0x5b, 0x5c, 0x70, 0x7b, 0x48, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x5f, 0x53, 0x79, 0x6c, -// l a b l e _ T y p e = L V } ] - 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x54, 0x79, 0x70, 0x65, 0x3d, 0x4c, 0x56, 0x7d, 0x5d, 0}; - -static const UChar gGC_LVTPattern[] = { -// [ \ p { H a n g u l _ S y l - 0x5b, 0x5c, 0x70, 0x7b, 0x48, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x5f, 0x53, 0x79, 0x6c, -// l a b l e _ T y p e = L V T } ] - 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x54, 0x79, 0x70, 0x65, 0x3d, 0x4c, 0x56, 0x54, 0x7d, 0x5d, 0}; - - -RegexStaticSets *RegexStaticSets::gStaticSets = NULL; +RegexStaticSets *RegexStaticSets::gStaticSets = nullptr; UInitOnce gStaticSetsInitOnce = U_INITONCE_INITIALIZER; -RegexStaticSets::RegexStaticSets(UErrorCode *status) -: -fUnescapeCharSet(UnicodeString(TRUE, gUnescapeCharPattern, -1), *status), -fRuleDigitsAlias(NULL), -fEmptyText(NULL) -{ - // First zero out everything - int i; - for (i=0; iremove(0xac00, 0xd7a4); - fPropSets[URX_GC_NORMAL]->removeAll(*fPropSets[URX_GC_CONTROL]); - fPropSets[URX_GC_NORMAL]->removeAll(*fPropSets[URX_GC_L]); - fPropSets[URX_GC_NORMAL]->removeAll(*fPropSets[URX_GC_V]); - fPropSets[URX_GC_NORMAL]->removeAll(*fPropSets[URX_GC_T]); + fPropSets[URX_GC_NORMAL].complement(); + fPropSets[URX_GC_NORMAL].remove(0xac00, 0xd7a4); + fPropSets[URX_GC_NORMAL].removeAll(fPropSets[URX_GC_CONTROL]); + fPropSets[URX_GC_NORMAL].removeAll(fPropSets[URX_GC_L]); + fPropSets[URX_GC_NORMAL].removeAll(fPropSets[URX_GC_V]); + fPropSets[URX_GC_NORMAL].removeAll(fPropSets[URX_GC_T]); + fPropSets[URX_GC_NORMAL].freeze(); // Initialize the 8-bit fast bit sets from the parallel full // UnicodeSets. - for (i=0; icompact(); - fPropSets8[i].init(fPropSets[i]); - } + // + // TODO: 25 Oct 2019 are these fast 8-bit sets worth keeping? + // Measured 3.5% gain on (non) matching with the pattern "x(?:\\S+)+x" + // This runs in exponential time, making it easy to adjust the time for + // convenient measuring. + // + // This 8 bit optimization dates from the early days of ICU, + // with a less optimized UnicodeSet. At the time, the difference + // was substantial. + + for (int32_t i=0; i::crea -static constexpr number::impl::Field kRDTNumericField - = StringBuilderFieldUtils::compress(); +static constexpr FormattedStringBuilder::Field kRDTNumericField + = {UFIELD_CATEGORY_RELATIVE_DATETIME, UDAT_REL_NUMERIC_FIELD}; -static constexpr number::impl::Field kRDTLiteralField - = StringBuilderFieldUtils::compress(); +static constexpr FormattedStringBuilder::Field kRDTLiteralField + = {UFIELD_CATEGORY_RELATIVE_DATETIME, UDAT_REL_LITERAL_FIELD}; class FormattedRelativeDateTimeData : public FormattedValueStringBuilderImpl { public: diff --git a/deps/icu-small/source/i18n/rematch.cpp b/deps/icu-small/source/i18n/rematch.cpp index 258cdab8c830b1..123aa8602ba474 100644 --- a/deps/icu-small/source/i18n/rematch.cpp +++ b/deps/icu-small/source/i18n/rematch.cpp @@ -177,6 +177,7 @@ RegexMatcher::~RegexMatcher() { #if UCONFIG_NO_BREAK_ITERATION==0 delete fWordBreakItr; + delete fGCBreakItr; #endif } @@ -222,6 +223,7 @@ void RegexMatcher::init(UErrorCode &status) { fDeferredStatus = status; fData = fSmallData; fWordBreakItr = NULL; + fGCBreakItr = NULL; fStack = NULL; fInputText = NULL; @@ -1854,12 +1856,15 @@ RegexMatcher &RegexMatcher::reset(const UnicodeString &input) { // This is for compatibility for those clients who modify the input string "live" during regex operations. fInputUniStrMaybeMutable = TRUE; - if (fWordBreakItr != NULL) { #if UCONFIG_NO_BREAK_ITERATION==0 - UErrorCode status = U_ZERO_ERROR; - fWordBreakItr->setText(fInputText, status); -#endif + if (fWordBreakItr) { + fWordBreakItr->setText(fInputText, fDeferredStatus); } + if (fGCBreakItr) { + fGCBreakItr->setText(fInputText, fDeferredStatus); + } +#endif + return *this; } @@ -1876,12 +1881,14 @@ RegexMatcher &RegexMatcher::reset(UText *input) { delete fInput; fInput = NULL; - if (fWordBreakItr != NULL) { #if UCONFIG_NO_BREAK_ITERATION==0 - UErrorCode status = U_ZERO_ERROR; - fWordBreakItr->setText(input, status); -#endif + if (fWordBreakItr) { + fWordBreakItr->setText(input, fDeferredStatus); + } + if (fGCBreakItr) { + fGCBreakItr->setText(fInputText, fDeferredStatus); } +#endif } reset(); fInputUniStrMaybeMutable = FALSE; @@ -2542,7 +2549,7 @@ UBool RegexMatcher::isWordBoundary(int64_t pos) { // Current char is a combining one. Not a boundary. return FALSE; } - cIsWord = fPattern->fStaticSets[URX_ISWORD_SET]->contains(c); + cIsWord = RegexStaticSets::gStaticSets->fPropSets[URX_ISWORD_SET].contains(c); } // Back up until we come to a non-combining char, determine whether @@ -2555,7 +2562,7 @@ UBool RegexMatcher::isWordBoundary(int64_t pos) { UChar32 prevChar = UTEXT_PREVIOUS32(fInputText); if (!(u_hasBinaryProperty(prevChar, UCHAR_GRAPHEME_EXTEND) || u_charType(prevChar) == U_FORMAT_CHAR)) { - prevCIsWord = fPattern->fStaticSets[URX_ISWORD_SET]->contains(prevChar); + prevCIsWord = RegexStaticSets::gStaticSets->fPropSets[URX_ISWORD_SET].contains(prevChar); break; } } @@ -2580,7 +2587,7 @@ UBool RegexMatcher::isChunkWordBoundary(int32_t pos) { // Current char is a combining one. Not a boundary. return FALSE; } - cIsWord = fPattern->fStaticSets[URX_ISWORD_SET]->contains(c); + cIsWord = RegexStaticSets::gStaticSets->fPropSets[URX_ISWORD_SET].contains(c); } // Back up until we come to a non-combining char, determine whether @@ -2594,7 +2601,7 @@ UBool RegexMatcher::isChunkWordBoundary(int32_t pos) { U16_PREV(inputBuf, fLookStart, pos, prevChar); if (!(u_hasBinaryProperty(prevChar, UCHAR_GRAPHEME_EXTEND) || u_charType(prevChar) == U_FORMAT_CHAR)) { - prevCIsWord = fPattern->fStaticSets[URX_ISWORD_SET]->contains(prevChar); + prevCIsWord = RegexStaticSets::gStaticSets->fPropSets[URX_ISWORD_SET].contains(prevChar); break; } } @@ -2611,37 +2618,60 @@ UBool RegexMatcher::isChunkWordBoundary(int32_t pos) { // parameters: pos - the current position in the input buffer // //-------------------------------------------------------------------------------- -UBool RegexMatcher::isUWordBoundary(int64_t pos) { +UBool RegexMatcher::isUWordBoundary(int64_t pos, UErrorCode &status) { UBool returnVal = FALSE; + #if UCONFIG_NO_BREAK_ITERATION==0 + // Note: this point will never be reached if break iteration is configured out. + // Regex patterns that would require this function will fail to compile. // If we haven't yet created a break iterator for this matcher, do it now. - if (fWordBreakItr == NULL) { - fWordBreakItr = - (RuleBasedBreakIterator *)BreakIterator::createWordInstance(Locale::getEnglish(), fDeferredStatus); - if (U_FAILURE(fDeferredStatus)) { + if (fWordBreakItr == nullptr) { + fWordBreakItr = BreakIterator::createWordInstance(Locale::getEnglish(), status); + if (U_FAILURE(status)) { return FALSE; } - fWordBreakItr->setText(fInputText, fDeferredStatus); + fWordBreakItr->setText(fInputText, status); } + // Note: zero width boundary tests like \b see through transparent region bounds, + // which is why fLookLimit is used here, rather than fActiveLimit. if (pos >= fLookLimit) { fHitEnd = TRUE; returnVal = TRUE; // With Unicode word rules, only positions within the interior of "real" // words are not boundaries. All non-word chars stand by themselves, // with word boundaries on both sides. } else { - if (!UTEXT_USES_U16(fInputText)) { - // !!!: Would like a better way to do this! - UErrorCode status = U_ZERO_ERROR; - pos = utext_extract(fInputText, 0, pos, NULL, 0, &status); - } returnVal = fWordBreakItr->isBoundary((int32_t)pos); } #endif return returnVal; } + +int64_t RegexMatcher::followingGCBoundary(int64_t pos, UErrorCode &status) { + int64_t result = pos; + +#if UCONFIG_NO_BREAK_ITERATION==0 + // Note: this point will never be reached if break iteration is configured out. + // Regex patterns that would require this function will fail to compile. + + // If we haven't yet created a break iterator for this matcher, do it now. + if (fGCBreakItr == nullptr) { + fGCBreakItr = BreakIterator::createCharacterInstance(Locale::getEnglish(), status); + if (U_FAILURE(status)) { + return pos; + } + fGCBreakItr->setText(fInputText, status); + } + result = fGCBreakItr->following(pos); + if (result == BreakIterator::DONE) { + result = pos; + } +#endif + return result; +} + //-------------------------------------------------------------------------------- // // IncrementTime This function is called once each TIMER_INITIAL_VALUE state @@ -3082,7 +3112,7 @@ void RegexMatcher::MatchAt(int64_t startIdx, UBool toEnd, UErrorCode &status) { case URX_BACKSLASH_BU: // Test for word boundaries, Unicode-style { - UBool success = isUWordBoundary(fp->fInputIdx); + UBool success = isUWordBoundary(fp->fInputIdx, status); success ^= (UBool)(opValue != 0); // flip sense for \B if (!success) { fp = (REStackFrame *)fStack->popFrame(fFrameSize); @@ -3184,99 +3214,21 @@ void RegexMatcher::MatchAt(int64_t startIdx, UBool toEnd, UErrorCode &status) { case URX_BACKSLASH_X: - // Match a Grapheme, as defined by Unicode TR 29. - // Differs slightly from Perl, which consumes combining marks independently - // of context. - { - - // Fail if at end of input - if (fp->fInputIdx >= fActiveLimit) { - fHitEnd = TRUE; - fp = (REStackFrame *)fStack->popFrame(fFrameSize); - break; - } - - UTEXT_SETNATIVEINDEX(fInputText, fp->fInputIdx); + // Match a Grapheme, as defined by Unicode UAX 29. - // Examine (and consume) the current char. - // Dispatch into a little state machine, based on the char. - UChar32 c; - c = UTEXT_NEXT32(fInputText); - fp->fInputIdx = UTEXT_GETNATIVEINDEX(fInputText); - UnicodeSet **sets = fPattern->fStaticSets; - if (sets[URX_GC_NORMAL]->contains(c)) goto GC_Extend; - if (sets[URX_GC_CONTROL]->contains(c)) goto GC_Control; - if (sets[URX_GC_L]->contains(c)) goto GC_L; - if (sets[URX_GC_LV]->contains(c)) goto GC_V; - if (sets[URX_GC_LVT]->contains(c)) goto GC_T; - if (sets[URX_GC_V]->contains(c)) goto GC_V; - if (sets[URX_GC_T]->contains(c)) goto GC_T; - goto GC_Extend; - - - -GC_L: - if (fp->fInputIdx >= fActiveLimit) goto GC_Done; - c = UTEXT_NEXT32(fInputText); - fp->fInputIdx = UTEXT_GETNATIVEINDEX(fInputText); - if (sets[URX_GC_L]->contains(c)) goto GC_L; - if (sets[URX_GC_LV]->contains(c)) goto GC_V; - if (sets[URX_GC_LVT]->contains(c)) goto GC_T; - if (sets[URX_GC_V]->contains(c)) goto GC_V; - (void)UTEXT_PREVIOUS32(fInputText); - fp->fInputIdx = UTEXT_GETNATIVEINDEX(fInputText); - goto GC_Extend; - -GC_V: - if (fp->fInputIdx >= fActiveLimit) goto GC_Done; - c = UTEXT_NEXT32(fInputText); - fp->fInputIdx = UTEXT_GETNATIVEINDEX(fInputText); - if (sets[URX_GC_V]->contains(c)) goto GC_V; - if (sets[URX_GC_T]->contains(c)) goto GC_T; - (void)UTEXT_PREVIOUS32(fInputText); - fp->fInputIdx = UTEXT_GETNATIVEINDEX(fInputText); - goto GC_Extend; - -GC_T: - if (fp->fInputIdx >= fActiveLimit) goto GC_Done; - c = UTEXT_NEXT32(fInputText); - fp->fInputIdx = UTEXT_GETNATIVEINDEX(fInputText); - if (sets[URX_GC_T]->contains(c)) goto GC_T; - (void)UTEXT_PREVIOUS32(fInputText); - fp->fInputIdx = UTEXT_GETNATIVEINDEX(fInputText); - goto GC_Extend; - -GC_Extend: - // Combining characters are consumed here - for (;;) { - if (fp->fInputIdx >= fActiveLimit) { - break; - } - c = UTEXT_CURRENT32(fInputText); - if (sets[URX_GC_EXTEND]->contains(c) == FALSE) { - break; - } - (void)UTEXT_NEXT32(fInputText); - fp->fInputIdx = UTEXT_GETNATIVEINDEX(fInputText); - } - goto GC_Done; - -GC_Control: - // Most control chars stand alone (don't combine with combining chars), - // except for that CR/LF sequence is a single grapheme cluster. - if (c == 0x0d && fp->fInputIdx < fActiveLimit && UTEXT_CURRENT32(fInputText) == 0x0a) { - c = UTEXT_NEXT32(fInputText); - fp->fInputIdx = UTEXT_GETNATIVEINDEX(fInputText); - } - -GC_Done: - if (fp->fInputIdx >= fActiveLimit) { - fHitEnd = TRUE; - } + // Fail if at end of input + if (fp->fInputIdx >= fActiveLimit) { + fHitEnd = TRUE; + fp = (REStackFrame *)fStack->popFrame(fFrameSize); break; } - + fp->fInputIdx = followingGCBoundary(fp->fInputIdx, status); + if (fp->fInputIdx >= fActiveLimit) { + fHitEnd = TRUE; + fp->fInputIdx = fActiveLimit; + } + break; case URX_BACKSLASH_Z: // Test for end of Input @@ -3310,13 +3262,13 @@ void RegexMatcher::MatchAt(int64_t startIdx, UBool toEnd, UErrorCode &status) { UTEXT_SETNATIVEINDEX(fInputText, fp->fInputIdx); UChar32 c = UTEXT_NEXT32(fInputText); if (c < 256) { - Regex8BitSet *s8 = &fPattern->fStaticSets8[opValue]; - if (s8->contains(c)) { + Regex8BitSet &s8 = RegexStaticSets::gStaticSets->fPropSets8[opValue]; + if (s8.contains(c)) { success = !success; } } else { - const UnicodeSet *s = fPattern->fStaticSets[opValue]; - if (s->contains(c)) { + const UnicodeSet &s = RegexStaticSets::gStaticSets->fPropSets[opValue]; + if (s.contains(c)) { success = !success; } } @@ -3346,14 +3298,14 @@ void RegexMatcher::MatchAt(int64_t startIdx, UBool toEnd, UErrorCode &status) { UChar32 c = UTEXT_NEXT32(fInputText); if (c < 256) { - Regex8BitSet *s8 = &fPattern->fStaticSets8[opValue]; - if (s8->contains(c) == FALSE) { + Regex8BitSet &s8 = RegexStaticSets::gStaticSets->fPropSets8[opValue]; + if (s8.contains(c) == FALSE) { fp->fInputIdx = UTEXT_GETNATIVEINDEX(fInputText); break; } } else { - const UnicodeSet *s = fPattern->fStaticSets[opValue]; - if (s->contains(c) == FALSE) { + const UnicodeSet &s = RegexStaticSets::gStaticSets->fPropSets[opValue]; + if (s.contains(c) == FALSE) { fp->fInputIdx = UTEXT_GETNATIVEINDEX(fInputText); break; } @@ -4662,7 +4614,7 @@ void RegexMatcher::MatchChunkAt(int32_t startIdx, UBool toEnd, UErrorCode &statu case URX_BACKSLASH_BU: // Test for word boundaries, Unicode-style { - UBool success = isUWordBoundary(fp->fInputIdx); + UBool success = isUWordBoundary(fp->fInputIdx, status); success ^= (UBool)(opValue != 0); // flip sense for \B if (!success) { fp = (REStackFrame *)fStack->popFrame(fFrameSize); @@ -4760,12 +4712,8 @@ void RegexMatcher::MatchChunkAt(int32_t startIdx, UBool toEnd, UErrorCode &statu break; - case URX_BACKSLASH_X: - // Match a Grapheme, as defined by Unicode TR 29. - // Differs slightly from Perl, which consumes combining marks independently - // of context. - { + // Match a Grapheme, as defined by Unicode UAX 29. // Fail if at end of input if (fp->fInputIdx >= fActiveLimit) { @@ -4774,76 +4722,12 @@ void RegexMatcher::MatchChunkAt(int32_t startIdx, UBool toEnd, UErrorCode &statu break; } - // Examine (and consume) the current char. - // Dispatch into a little state machine, based on the char. - UChar32 c; - U16_NEXT(inputBuf, fp->fInputIdx, fActiveLimit, c); - UnicodeSet **sets = fPattern->fStaticSets; - if (sets[URX_GC_NORMAL]->contains(c)) goto GC_Extend; - if (sets[URX_GC_CONTROL]->contains(c)) goto GC_Control; - if (sets[URX_GC_L]->contains(c)) goto GC_L; - if (sets[URX_GC_LV]->contains(c)) goto GC_V; - if (sets[URX_GC_LVT]->contains(c)) goto GC_T; - if (sets[URX_GC_V]->contains(c)) goto GC_V; - if (sets[URX_GC_T]->contains(c)) goto GC_T; - goto GC_Extend; - - - -GC_L: - if (fp->fInputIdx >= fActiveLimit) goto GC_Done; - U16_NEXT(inputBuf, fp->fInputIdx, fActiveLimit, c); - if (sets[URX_GC_L]->contains(c)) goto GC_L; - if (sets[URX_GC_LV]->contains(c)) goto GC_V; - if (sets[URX_GC_LVT]->contains(c)) goto GC_T; - if (sets[URX_GC_V]->contains(c)) goto GC_V; - U16_PREV(inputBuf, 0, fp->fInputIdx, c); - goto GC_Extend; - -GC_V: - if (fp->fInputIdx >= fActiveLimit) goto GC_Done; - U16_NEXT(inputBuf, fp->fInputIdx, fActiveLimit, c); - if (sets[URX_GC_V]->contains(c)) goto GC_V; - if (sets[URX_GC_T]->contains(c)) goto GC_T; - U16_PREV(inputBuf, 0, fp->fInputIdx, c); - goto GC_Extend; - -GC_T: - if (fp->fInputIdx >= fActiveLimit) goto GC_Done; - U16_NEXT(inputBuf, fp->fInputIdx, fActiveLimit, c); - if (sets[URX_GC_T]->contains(c)) goto GC_T; - U16_PREV(inputBuf, 0, fp->fInputIdx, c); - goto GC_Extend; - -GC_Extend: - // Combining characters are consumed here - for (;;) { - if (fp->fInputIdx >= fActiveLimit) { - break; - } - U16_NEXT(inputBuf, fp->fInputIdx, fActiveLimit, c); - if (sets[URX_GC_EXTEND]->contains(c) == FALSE) { - U16_BACK_1(inputBuf, 0, fp->fInputIdx); - break; - } - } - goto GC_Done; - -GC_Control: - // Most control chars stand alone (don't combine with combining chars), - // except for that CR/LF sequence is a single grapheme cluster. - if (c == 0x0d && fp->fInputIdx < fActiveLimit && inputBuf[fp->fInputIdx] == 0x0a) { - fp->fInputIdx++; - } - -GC_Done: + fp->fInputIdx = followingGCBoundary(fp->fInputIdx, status); if (fp->fInputIdx >= fActiveLimit) { fHitEnd = TRUE; + fp->fInputIdx = fActiveLimit; } break; - } - - case URX_BACKSLASH_Z: // Test for end of Input @@ -4877,13 +4761,13 @@ void RegexMatcher::MatchChunkAt(int32_t startIdx, UBool toEnd, UErrorCode &statu UChar32 c; U16_NEXT(inputBuf, fp->fInputIdx, fActiveLimit, c); if (c < 256) { - Regex8BitSet *s8 = &fPattern->fStaticSets8[opValue]; - if (s8->contains(c)) { + Regex8BitSet &s8 = RegexStaticSets::gStaticSets->fPropSets8[opValue]; + if (s8.contains(c)) { success = !success; } } else { - const UnicodeSet *s = fPattern->fStaticSets[opValue]; - if (s->contains(c)) { + const UnicodeSet &s = RegexStaticSets::gStaticSets->fPropSets[opValue]; + if (s.contains(c)) { success = !success; } } @@ -4909,13 +4793,13 @@ void RegexMatcher::MatchChunkAt(int32_t startIdx, UBool toEnd, UErrorCode &statu UChar32 c; U16_NEXT(inputBuf, fp->fInputIdx, fActiveLimit, c); if (c < 256) { - Regex8BitSet *s8 = &fPattern->fStaticSets8[opValue]; - if (s8->contains(c) == FALSE) { + Regex8BitSet &s8 = RegexStaticSets::gStaticSets->fPropSets8[opValue]; + if (s8.contains(c) == FALSE) { break; } } else { - const UnicodeSet *s = fPattern->fStaticSets[opValue]; - if (s->contains(c) == FALSE) { + const UnicodeSet &s = RegexStaticSets::gStaticSets->fPropSets[opValue]; + if (s.contains(c) == FALSE) { break; } } diff --git a/deps/icu-small/source/i18n/repattrn.cpp b/deps/icu-small/source/i18n/repattrn.cpp index 50e0f600d3bc75..34886624891f49 100644 --- a/deps/icu-small/source/i18n/repattrn.cpp +++ b/deps/icu-small/source/i18n/repattrn.cpp @@ -97,8 +97,6 @@ RegexPattern &RegexPattern::operator = (const RegexPattern &other) { fMinMatchLen = other.fMinMatchLen; fFrameSize = other.fFrameSize; fDataSize = other.fDataSize; - fStaticSets = other.fStaticSets; - fStaticSets8 = other.fStaticSets8; fStartType = other.fStartType; fInitialStringIdx = other.fInitialStringIdx; @@ -175,8 +173,6 @@ void RegexPattern::init() { fFrameSize = 0; fDataSize = 0; fGroupMap = NULL; - fStaticSets = NULL; - fStaticSets8 = NULL; fStartType = START_NO_INFO; fInitialStringIdx = 0; fInitialStringLen = 0; @@ -805,8 +801,8 @@ void RegexPattern::dumpOp(int32_t index) const { printf("NOT "); val &= ~URX_NEG_SET; } - UnicodeSet *set = fStaticSets[val]; - set->toPattern(s, TRUE); + UnicodeSet &set = RegexStaticSets::gStaticSets->fPropSets[val]; + set.toPattern(s, TRUE); printf("%s", CStr(s)()); } break; diff --git a/deps/icu-small/source/i18n/smpdtfmt.cpp b/deps/icu-small/source/i18n/smpdtfmt.cpp index 5fcbb5875b2bfb..d704642b0536a4 100644 --- a/deps/icu-small/source/i18n/smpdtfmt.cpp +++ b/deps/icu-small/source/i18n/smpdtfmt.cpp @@ -583,11 +583,14 @@ SimpleDateFormat& SimpleDateFormat::operator=(const SimpleDateFormat& other) fHasMinute = other.fHasMinute; fHasSecond = other.fHasSecond; - // TimeZoneFormat in ICU4C only depends on a locale for now - if (fLocale != other.fLocale) { - delete fTimeZoneFormat; - fTimeZoneFormat = NULL; // forces lazy instantiation with the other locale - fLocale = other.fLocale; + fLocale = other.fLocale; + + // TimeZoneFormat can now be set independently via setter. + // If it is NULL, it will be lazily initialized from locale + delete fTimeZoneFormat; + fTimeZoneFormat = NULL; + if (other.fTimeZoneFormat) { + fTimeZoneFormat = new TimeZoneFormat(*other.fTimeZoneFormat); } #if !UCONFIG_NO_BREAK_ITERATION @@ -996,7 +999,8 @@ SimpleDateFormat::_format(Calendar& cal, UnicodeString& appendTo, // Use subFormat() to format a repeated pattern character // when a different pattern or non-pattern character is seen if (ch != prevCh && count > 0) { - subFormat(appendTo, prevCh, count, capitalizationContext, fieldNum++, handler, *workCal, status); + subFormat(appendTo, prevCh, count, capitalizationContext, fieldNum++, + prevCh, handler, *workCal, status); count = 0; } if (ch == QUOTE) { @@ -1023,7 +1027,8 @@ SimpleDateFormat::_format(Calendar& cal, UnicodeString& appendTo, // Format the last item in the pattern, if any if (count > 0) { - subFormat(appendTo, prevCh, count, capitalizationContext, fieldNum++, handler, *workCal, status); + subFormat(appendTo, prevCh, count, capitalizationContext, fieldNum++, + prevCh, handler, *workCal, status); } if (calClone != NULL) { @@ -1402,10 +1407,11 @@ SimpleDateFormat::processOverrideString(const Locale &locale, const UnicodeStrin //--------------------------------------------------------------------- void SimpleDateFormat::subFormat(UnicodeString &appendTo, - UChar ch, + char16_t ch, int32_t count, UDisplayContext capitalizationContext, int32_t fieldNum, + char16_t fieldToOutput, FieldPositionHandler& handler, Calendar& cal, UErrorCode& status) const @@ -1853,8 +1859,11 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo, // In either case, fall back to am/pm. if (toAppend == NULL || toAppend->isBogus()) { // Reformat with identical arguments except ch, now changed to 'a'. - subFormat(appendTo, 0x61, count, capitalizationContext, fieldNum, - handler, cal, status); + // We are passing a different fieldToOutput because we want to add + // 'b' to field position. This makes this fallback stable when + // there is a data change on locales. + subFormat(appendTo, u'a', count, capitalizationContext, fieldNum, u'b', handler, cal, status); + return; } else { appendTo += *toAppend; } @@ -1874,9 +1883,11 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo, if (ruleSet == NULL) { // Data doesn't exist for the locale we're looking for. // Falling back to am/pm. - subFormat(appendTo, 0x61, count, capitalizationContext, fieldNum, - handler, cal, status); - break; + // We are passing a different fieldToOutput because we want to add + // 'B' to field position. This makes this fallback stable when + // there is a data change on locales. + subFormat(appendTo, u'a', count, capitalizationContext, fieldNum, u'B', handler, cal, status); + return; } // Get current display time. @@ -1945,8 +1956,11 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo, if (periodType == DayPeriodRules::DAYPERIOD_AM || periodType == DayPeriodRules::DAYPERIOD_PM || toAppend->isBogus()) { - subFormat(appendTo, 0x61, count, capitalizationContext, fieldNum, - handler, cal, status); + // We are passing a different fieldToOutput because we want to add + // 'B' to field position iterator. This makes this fallback stable when + // there is a data change on locales. + subFormat(appendTo, u'a', count, capitalizationContext, fieldNum, u'B', handler, cal, status); + return; } else { appendTo += *toAppend; @@ -1990,7 +2004,7 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo, } #endif - handler.addAttribute(fgPatternIndexToDateFormatField[patternCharIndex], beginOffset, appendTo.length()); + handler.addAttribute(DateFormatSymbols::getPatternCharIndex(fieldToOutput), beginOffset, appendTo.length()); } //---------------------------------------------------------------------- diff --git a/deps/icu-small/source/i18n/translit.cpp b/deps/icu-small/source/i18n/translit.cpp index 039acaf157cc93..a2ade1b4fe8578 100644 --- a/deps/icu-small/source/i18n/translit.cpp +++ b/deps/icu-small/source/i18n/translit.cpp @@ -1508,28 +1508,35 @@ UBool Transliterator::initializeRegistry(UErrorCode &status) { */ //static const char translit_index[] = "translit_index"; + UErrorCode lstatus = U_ZERO_ERROR; UResourceBundle *bundle, *transIDs, *colBund; - bundle = ures_open(U_ICUDATA_TRANSLIT, NULL/*open default locale*/, &status); - transIDs = ures_getByKey(bundle, RB_RULE_BASED_IDS, 0, &status); + bundle = ures_open(U_ICUDATA_TRANSLIT, NULL/*open default locale*/, &lstatus); + transIDs = ures_getByKey(bundle, RB_RULE_BASED_IDS, 0, &lstatus); const UnicodeString T_PART = UNICODE_STRING_SIMPLE("-t-"); int32_t row, maxRows; - if (U_SUCCESS(status)) { + if (lstatus == U_MEMORY_ALLOCATION_ERROR) { + delete registry; + registry = nullptr; + status = U_MEMORY_ALLOCATION_ERROR; + return FALSE; + } + if (U_SUCCESS(lstatus)) { maxRows = ures_getSize(transIDs); for (row = 0; row < maxRows; row++) { - colBund = ures_getByIndex(transIDs, row, 0, &status); - if (U_SUCCESS(status)) { + colBund = ures_getByIndex(transIDs, row, 0, &lstatus); + if (U_SUCCESS(lstatus)) { UnicodeString id(ures_getKey(colBund), -1, US_INV); if(id.indexOf(T_PART) != -1) { ures_close(colBund); continue; } - UResourceBundle* res = ures_getNextResource(colBund, NULL, &status); + UResourceBundle* res = ures_getNextResource(colBund, NULL, &lstatus); const char* typeStr = ures_getKey(res); UChar type; u_charsToUChars(typeStr, &type, 1); - if (U_SUCCESS(status)) { + if (U_SUCCESS(lstatus)) { int32_t len = 0; const UChar *resString; switch (type) { @@ -1539,19 +1546,19 @@ UBool Transliterator::initializeRegistry(UErrorCode &status) { // row[2]=resource, row[3]=direction { - resString = ures_getStringByKey(res, "resource", &len, &status); + resString = ures_getStringByKey(res, "resource", &len, &lstatus); UBool visible = (type == 0x0066 /*f*/); UTransDirection dir = - (ures_getUnicodeStringByKey(res, "direction", &status).charAt(0) == + (ures_getUnicodeStringByKey(res, "direction", &lstatus).charAt(0) == 0x0046 /*F*/) ? UTRANS_FORWARD : UTRANS_REVERSE; - registry->put(id, UnicodeString(TRUE, resString, len), dir, TRUE, visible, status); + registry->put(id, UnicodeString(TRUE, resString, len), dir, TRUE, visible, lstatus); } break; case 0x61: // 'a' // 'alias'; row[2]=createInstance argument - resString = ures_getString(res, &len, &status); - registry->put(id, UnicodeString(TRUE, resString, len), TRUE, TRUE, status); + resString = ures_getString(res, &len, &lstatus); + registry->put(id, UnicodeString(TRUE, resString, len), TRUE, TRUE, lstatus); break; } } diff --git a/deps/icu-small/source/i18n/ucal.cpp b/deps/icu-small/source/i18n/ucal.cpp index cca1f70cf54584..8ea7fbf4f56939 100644 --- a/deps/icu-small/source/i18n/ucal.cpp +++ b/deps/icu-small/source/i18n/ucal.cpp @@ -154,25 +154,31 @@ ucal_open( const UChar* zoneID, UCalendarType caltype, UErrorCode* status) { + if (U_FAILURE(*status)) { + return nullptr; + } - if(U_FAILURE(*status)) return 0; - - LocalPointer zone( (zoneID==NULL) ? TimeZone::createDefault() + LocalPointer zone( (zoneID==nullptr) ? TimeZone::createDefault() : _createTimeZone(zoneID, len, status), *status); if (U_FAILURE(*status)) { - return NULL; + return nullptr; } if ( caltype == UCAL_GREGORIAN ) { - char localeBuf[ULOC_LOCALE_IDENTIFIER_CAPACITY]; - if ( locale == NULL ) { + char localeBuf[ULOC_LOCALE_IDENTIFIER_CAPACITY]; + if ( locale == nullptr ) { locale = uloc_getDefault(); } - uprv_strncpy(localeBuf, locale, ULOC_LOCALE_IDENTIFIER_CAPACITY); + int32_t localeLength = static_cast(uprv_strlen(locale)); + if (localeLength >= ULOC_LOCALE_IDENTIFIER_CAPACITY) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return nullptr; + } + uprv_strcpy(localeBuf, locale); uloc_setKeywordValue("calendar", "gregorian", localeBuf, ULOC_LOCALE_IDENTIFIER_CAPACITY, status); if (U_FAILURE(*status)) { - return NULL; + return nullptr; } return (UCalendar*)Calendar::createInstance(zone.orphan(), Locale(localeBuf), *status); } @@ -182,8 +188,9 @@ ucal_open( const UChar* zoneID, U_CAPI void U_EXPORT2 ucal_close(UCalendar *cal) { - - delete (Calendar*) cal; + if (cal != nullptr) { + delete (Calendar*) cal; + } } U_CAPI UCalendar* U_EXPORT2 diff --git a/deps/icu-small/source/i18n/ucln_in.h b/deps/icu-small/source/i18n/ucln_in.h index 2f70a8500e1c09..765cdd559fb4e2 100644 --- a/deps/icu-small/source/i18n/ucln_in.h +++ b/deps/icu-small/source/i18n/ucln_in.h @@ -26,6 +26,7 @@ as the functions are suppose to be called. It's usually best to have child dependencies called first. */ typedef enum ECleanupI18NType { UCLN_I18N_START = -1, + UCLN_I18N_UNIT_EXTRAS, UCLN_I18N_NUMBER_SKELETONS, UCLN_I18N_CURRENCY_SPACING, UCLN_I18N_SPOOF, diff --git a/deps/icu-small/source/i18n/ucol_sit.cpp b/deps/icu-small/source/i18n/ucol_sit.cpp index 765613084f84e1..9fa7cd5fd73851 100644 --- a/deps/icu-small/source/i18n/ucol_sit.cpp +++ b/deps/icu-small/source/i18n/ucol_sit.cpp @@ -24,6 +24,10 @@ #include "cstring.h" #include "uresimp.h" #include "unicode/coll.h" +#include "unicode/stringpiece.h" +#include "charstr.h" + +U_NAMESPACE_USE #ifdef UCOL_TRACE_SIT # include @@ -82,7 +86,6 @@ static const char providerKeyword[] = "@sp="; static const int32_t locElementCount = UCOL_SIT_LOCELEMENT_MAX+1; static const int32_t locElementCapacity = 32; static const int32_t loc3066Capacity = 256; -static const int32_t locProviderCapacity = 10; static const int32_t internalBufferSize = 512; /* structure containing specification of a collator. Initialized @@ -90,20 +93,30 @@ static const int32_t internalBufferSize = 512; * collator instance */ struct CollatorSpec { - char locElements[locElementCount][locElementCapacity]; - char locale[loc3066Capacity]; - char provider[locProviderCapacity]; + inline CollatorSpec(); + + CharString locElements[locElementCount]; + CharString locale; UColAttributeValue options[UCOL_ATTRIBUTE_COUNT]; uint32_t variableTopValue; UChar variableTopString[locElementCapacity]; int32_t variableTopStringLen; UBool variableTopSet; - struct { - const char *start; - int32_t len; - } entries[UCOL_SIT_ITEMS_COUNT]; + CharString entries[UCOL_SIT_ITEMS_COUNT]; }; +CollatorSpec::CollatorSpec() : +locale(), +variableTopValue(0), +variableTopString(), +variableTopSet(FALSE) + { + // set collation options to default + for(int32_t i = 0; i < UCOL_ATTRIBUTE_COUNT; i++) { + options[i] = UCOL_DEFAULT; + } +} + /* structure for converting between character attribute * representation and real collation attribute value. @@ -156,18 +169,13 @@ static const char* U_CALLCONV _processLocaleElement(CollatorSpec *spec, uint32_t value, const char* string, UErrorCode *status) { - int32_t len = 0; do { if(value == UCOL_SIT_LANGUAGE || value == UCOL_SIT_KEYWORD || value == UCOL_SIT_PROVIDER) { - spec->locElements[value][len++] = uprv_tolower(*string); + spec->locElements[value].append(uprv_tolower(*string), *status); } else { - spec->locElements[value][len++] = *string; + spec->locElements[value].append(*string, *status); } - } while(*(++string) != '_' && *string && len < locElementCapacity); - if(len >= locElementCapacity) { - *status = U_BUFFER_OVERFLOW_ERROR; - return string; - } + } while(*(++string) != '_' && *string && U_SUCCESS(*status)); // don't skip the underscore at the end return string; } @@ -185,7 +193,7 @@ _processRFC3066Locale(CollatorSpec *spec, uint32_t, const char* string, *status = U_BUFFER_OVERFLOW_ERROR; return string; } else { - uprv_strncpy(spec->locale, string, end-string); + spec->locale.copyFrom(CharString(string, static_cast(end-string), *status), *status); return end+1; } } @@ -306,9 +314,12 @@ const char* ucol_sit_readOption(const char *start, CollatorSpec *spec, for(i = 0; i < UCOL_SIT_ITEMS_COUNT; i++) { if(*start == options[i].optionStart) { - spec->entries[i].start = start; const char* end = options[i].action(spec, options[i].attr, start+1, status); - spec->entries[i].len = (int32_t)(end - start); +#ifdef UCOL_TRACE_SIT + fprintf(stderr, "***Set %d to %s...\n", i, start); +#endif + // assume 'start' does not go away through all this + spec->entries[i].copyFrom(CharString(start, (int32_t)(end - start), *status), *status); return end; } } @@ -319,18 +330,6 @@ const char* ucol_sit_readOption(const char *start, CollatorSpec *spec, return start; } -static -void ucol_sit_initCollatorSpecs(CollatorSpec *spec) -{ - // reset everything - uprv_memset(spec, 0, sizeof(CollatorSpec)); - // set collation options to default - int32_t i = 0; - for(i = 0; i < UCOL_ATTRIBUTE_COUNT; i++) { - spec->options[i] = UCOL_DEFAULT; - } -} - static const char* ucol_sit_readSpecs(CollatorSpec *s, const char *string, UParseError *parseError, UErrorCode *status) @@ -357,25 +356,25 @@ int32_t ucol_sit_dumpSpecs(CollatorSpec *s, char *destination, int32_t capacity, char optName; if(U_SUCCESS(*status)) { for(i = 0; i < UCOL_SIT_ITEMS_COUNT; i++) { - if(s->entries[i].start) { + if(!s->entries[i].isEmpty()) { if(len) { if(len < capacity) { uprv_strcat(destination, "_"); } len++; } - optName = *(s->entries[i].start); + optName = s->entries[i][0]; if(optName == languageArg || optName == regionArg || optName == variantArg || optName == keywordArg) { - for(j = 0; j < s->entries[i].len; j++) { + for(j = 0; j < s->entries[i].length(); j++) { if(len + j < capacity) { - destination[len+j] = uprv_toupper(*(s->entries[i].start+j)); + destination[len+j] = uprv_toupper(s->entries[i][j]); } } - len += s->entries[i].len; + len += s->entries[i].length(); } else { - len += s->entries[i].len; + len += s->entries[i].length(); if(len < capacity) { - uprv_strncat(destination,s->entries[i].start, s->entries[i].len); + uprv_strncat(destination,s->entries[i].data(), s->entries[i].length()); } } } @@ -387,40 +386,40 @@ int32_t ucol_sit_dumpSpecs(CollatorSpec *s, char *destination, int32_t capacity, } static void -ucol_sit_calculateWholeLocale(CollatorSpec *s) { +ucol_sit_calculateWholeLocale(CollatorSpec *s, UErrorCode &status) { // put the locale together, unless we have a done // locale - if(s->locale[0] == 0) { + if(s->locale.isEmpty()) { // first the language - uprv_strcat(s->locale, s->locElements[UCOL_SIT_LANGUAGE]); + s->locale.append(s->locElements[UCOL_SIT_LANGUAGE], status); // then the script, if present - if(*(s->locElements[UCOL_SIT_SCRIPT])) { - uprv_strcat(s->locale, "_"); - uprv_strcat(s->locale, s->locElements[UCOL_SIT_SCRIPT]); + if(!s->locElements[UCOL_SIT_SCRIPT].isEmpty()) { + s->locale.append("_", status); + s->locale.append(s->locElements[UCOL_SIT_SCRIPT], status); } // then the region, if present - if(*(s->locElements[UCOL_SIT_REGION])) { - uprv_strcat(s->locale, "_"); - uprv_strcat(s->locale, s->locElements[UCOL_SIT_REGION]); - } else if(*(s->locElements[UCOL_SIT_VARIANT])) { // if there is a variant, we need an underscore - uprv_strcat(s->locale, "_"); + if(!s->locElements[UCOL_SIT_REGION].isEmpty()) { + s->locale.append("_", status); + s->locale.append(s->locElements[UCOL_SIT_REGION], status); + } else if(!s->locElements[UCOL_SIT_VARIANT].isEmpty()) { // if there is a variant, we need an underscore + s->locale.append("_", status); } // add variant, if there - if(*(s->locElements[UCOL_SIT_VARIANT])) { - uprv_strcat(s->locale, "_"); - uprv_strcat(s->locale, s->locElements[UCOL_SIT_VARIANT]); + if(!s->locElements[UCOL_SIT_VARIANT].isEmpty()) { + s->locale.append("_", status); + s->locale.append(s->locElements[UCOL_SIT_VARIANT], status); } // if there is a collation keyword, add that too - if(*(s->locElements[UCOL_SIT_KEYWORD])) { - uprv_strcat(s->locale, collationKeyword); - uprv_strcat(s->locale, s->locElements[UCOL_SIT_KEYWORD]); + if(!s->locElements[UCOL_SIT_KEYWORD].isEmpty()) { + s->locale.append(collationKeyword, status); + s->locale.append(s->locElements[UCOL_SIT_KEYWORD], status); } // if there is a provider keyword, add that too - if(*(s->locElements[UCOL_SIT_PROVIDER])) { - uprv_strcat(s->locale, providerKeyword); - uprv_strcat(s->locale, s->locElements[UCOL_SIT_PROVIDER]); + if(!s->locElements[UCOL_SIT_PROVIDER].isEmpty()) { + s->locale.append(providerKeyword, status); + s->locale.append(s->locElements[UCOL_SIT_PROVIDER], status); } } } @@ -451,13 +450,12 @@ ucol_prepareShortStringOpen( const char *definition, // analyse the string in order to get everything we need. CollatorSpec s; - ucol_sit_initCollatorSpecs(&s); ucol_sit_readSpecs(&s, definition, parseError, status); - ucol_sit_calculateWholeLocale(&s); + ucol_sit_calculateWholeLocale(&s, *status); char buffer[internalBufferSize]; uprv_memset(buffer, 0, internalBufferSize); - uloc_canonicalize(s.locale, buffer, internalBufferSize, status); + uloc_canonicalize(s.locale.data(), buffer, internalBufferSize, status); UResourceBundle *b = ures_open(U_ICUDATA_COLL, buffer, status); /* we try to find stuff from keyword */ @@ -522,13 +520,15 @@ ucol_openFromShortString( const char *definition, // analyse the string in order to get everything we need. const char *string = definition; CollatorSpec s; - ucol_sit_initCollatorSpecs(&s); string = ucol_sit_readSpecs(&s, definition, parseError, status); - ucol_sit_calculateWholeLocale(&s); + ucol_sit_calculateWholeLocale(&s, *status); char buffer[internalBufferSize]; uprv_memset(buffer, 0, internalBufferSize); - uloc_canonicalize(s.locale, buffer, internalBufferSize, status); +#ifdef UCOL_TRACE_SIT + fprintf(stderr, "DEF %s, DATA %s, ERR %s\n", definition, s.locale.data(), u_errorName(*status)); +#endif + uloc_canonicalize(s.locale.data(), buffer, internalBufferSize, status); UCollator *result = ucol_open(buffer, status); int32_t i = 0; @@ -604,7 +604,6 @@ ucol_normalizeShortDefinitionString(const char *definition, // validate CollatorSpec s; - ucol_sit_initCollatorSpecs(&s); ucol_sit_readSpecs(&s, definition, parseError, status); return ucol_sit_dumpSpecs(&s, destination, capacity, status); } diff --git a/deps/icu-small/source/i18n/udateintervalformat.cpp b/deps/icu-small/source/i18n/udateintervalformat.cpp index d9eaae4d3e23cf..388960384b563f 100644 --- a/deps/icu-small/source/i18n/udateintervalformat.cpp +++ b/deps/icu-small/source/i18n/udateintervalformat.cpp @@ -119,17 +119,36 @@ udtitvfmt_format(const UDateIntervalFormat* formatter, U_DRAFT void U_EXPORT2 udtitvfmt_formatToResult( const UDateIntervalFormat* formatter, - UFormattedDateInterval* result, UDate fromDate, UDate toDate, + UFormattedDateInterval* result, UErrorCode* status) { if (U_FAILURE(*status)) { return; } auto* resultImpl = UFormattedDateIntervalApiHelper::validate(result, *status); DateInterval interval = DateInterval(fromDate,toDate); - resultImpl->fImpl = reinterpret_cast(formatter) - ->formatToValue(interval, *status); + if (resultImpl != nullptr) { + resultImpl->fImpl = reinterpret_cast(formatter) + ->formatToValue(interval, *status); + } +} + +U_DRAFT void U_EXPORT2 +udtitvfmt_formatCalendarToResult( + const UDateIntervalFormat* formatter, + UCalendar* fromCalendar, + UCalendar* toCalendar, + UFormattedDateInterval* result, + UErrorCode* status) { + if (U_FAILURE(*status)) { + return; + } + auto* resultImpl = UFormattedDateIntervalApiHelper::validate(result, *status); + if (resultImpl != nullptr) { + resultImpl->fImpl = reinterpret_cast(formatter) + ->formatToValue(*(Calendar *)fromCalendar, *(Calendar *)toCalendar, *status); + } } diff --git a/deps/icu-small/source/i18n/udatpg.cpp b/deps/icu-small/source/i18n/udatpg.cpp index febf73b3ce499f..332636a93889f1 100644 --- a/deps/icu-small/source/i18n/udatpg.cpp +++ b/deps/icu-small/source/i18n/udatpg.cpp @@ -291,4 +291,9 @@ udatpg_getPatternForSkeleton(const UDateTimePatternGenerator *dtpg, return result.getBuffer(); } +U_CAPI UDateFormatHourCycle U_EXPORT2 +udatpg_getDefaultHourCycle(const UDateTimePatternGenerator *dtpg, UErrorCode* pErrorCode) { + return ((const DateTimePatternGenerator *)dtpg)->getDefaultHourCycle(*pErrorCode); +} + #endif diff --git a/deps/icu-small/source/i18n/ulistformatter.cpp b/deps/icu-small/source/i18n/ulistformatter.cpp index f7ad6751d338c0..bfb7cf96bd4d93 100644 --- a/deps/icu-small/source/i18n/ulistformatter.cpp +++ b/deps/icu-small/source/i18n/ulistformatter.cpp @@ -34,6 +34,21 @@ ulistfmt_open(const char* locale, } +U_CAPI UListFormatter* U_EXPORT2 +ulistfmt_openForType(const char* locale, UListFormatterType type, + UListFormatterWidth width, UErrorCode* status) +{ + if (U_FAILURE(*status)) { + return NULL; + } + LocalPointer listfmt(ListFormatter::createInstance(Locale(locale), type, width, *status)); + if (U_FAILURE(*status)) { + return NULL; + } + return (UListFormatter*)listfmt.orphan(); +} + + U_CAPI void U_EXPORT2 ulistfmt_close(UListFormatter *listfmt) { diff --git a/deps/icu-small/source/i18n/unicode/basictz.h b/deps/icu-small/source/i18n/unicode/basictz.h index e1db2a8223adde..cc8059709f49b0 100644 --- a/deps/icu-small/source/i18n/unicode/basictz.h +++ b/deps/icu-small/source/i18n/unicode/basictz.h @@ -206,6 +206,12 @@ class U_I18N_API BasicTimeZone: public TimeZone { */ BasicTimeZone(const BasicTimeZone& source); + /** + * Copy assignment. + * @stable ICU 3.8 + */ + BasicTimeZone& operator=(const BasicTimeZone&) = default; + /** * Gets the set of TimeZoneRule instances applicable to the specified time and after. * @param start The start date used for extracting time zone rules diff --git a/deps/icu-small/source/i18n/unicode/currunit.h b/deps/icu-small/source/i18n/unicode/currunit.h index 0446154e328f8f..090b964a0decee 100644 --- a/deps/icu-small/source/i18n/unicode/currunit.h +++ b/deps/icu-small/source/i18n/unicode/currunit.h @@ -56,7 +56,6 @@ class U_I18N_API CurrencyUnit: public MeasureUnit { */ CurrencyUnit(ConstChar16Ptr isoCode, UErrorCode &ec); -#ifndef U_HIDE_DRAFT_API /** * Construct an object with the given ISO currency code. * @@ -64,10 +63,9 @@ class U_I18N_API CurrencyUnit: public MeasureUnit { * length 3. If invalid, the currency is initialized to XXX. * @param ec input-output error code. If the isoCode is invalid, * then this will be set to a failing value. - * @draft ICU 64 + * @stable ICU 64 */ CurrencyUnit(StringPiece isoCode, UErrorCode &ec); -#endif /* U_HIDE_DRAFT_API */ /** * Copy constructor diff --git a/deps/icu-small/source/i18n/unicode/dcfmtsym.h b/deps/icu-small/source/i18n/unicode/dcfmtsym.h index e1e0ab6b08c523..582e7533a4aceb 100644 --- a/deps/icu-small/source/i18n/unicode/dcfmtsym.h +++ b/deps/icu-small/source/i18n/unicode/dcfmtsym.h @@ -291,6 +291,17 @@ class U_I18N_API DecimalFormatSymbols : public UObject { */ void setSymbol(ENumberFormatSymbol symbol, const UnicodeString &value, const UBool propogateDigits); +#ifndef U_HIDE_INTERNAL_API + /** + * Loads symbols for the specified currency into this instance. + * + * This method is internal. If you think it should be public, file a ticket. + * + * @internal + */ + void setCurrency(const UChar* currency, UErrorCode& status); +#endif // U_HIDE_INTERNAL_API + /** * Returns the locale for which this object was constructed. * @stable ICU 2.6 @@ -374,8 +385,6 @@ class U_I18N_API DecimalFormatSymbols : public UObject { */ void initialize(); - void setCurrencyForSymbols(); - public: #ifndef U_HIDE_INTERNAL_API diff --git a/deps/icu-small/source/i18n/unicode/decimfmt.h b/deps/icu-small/source/i18n/unicode/decimfmt.h index e539b9af233ccb..b176ee78faca49 100644 --- a/deps/icu-small/source/i18n/unicode/decimfmt.h +++ b/deps/icu-small/source/i18n/unicode/decimfmt.h @@ -53,10 +53,10 @@ class CompactDecimalFormat; namespace number { class LocalizedNumberFormatter; -class FormattedNumber; namespace impl { class DecimalQuantity; struct DecimalFormatFields; +class UFormattedNumberData; } } @@ -1283,14 +1283,13 @@ class U_I18N_API DecimalFormat : public NumberFormat { */ virtual void setNegativeSuffix(const UnicodeString& newValue); -#ifndef U_HIDE_DRAFT_API /** * Whether to show the plus sign on positive (non-negative) numbers; for example, "+12" * * For more control over sign display, use NumberFormatter. * * @return Whether the sign is shown on positive numbers and zero. - * @draft ICU 64 + * @stable ICU 64 */ UBool isSignAlwaysShown() const; @@ -1300,10 +1299,9 @@ class U_I18N_API DecimalFormat : public NumberFormat { * For more control over sign display, use NumberFormatter. * * @param value true to always show a sign; false to hide the sign on positive numbers and zero. - * @draft ICU 64 + * @stable ICU 64 */ void setSignAlwaysShown(UBool value); -#endif /* U_HIDE_DRAFT_API */ /** * Get the multiplier for use in percent, permill, etc. @@ -1650,7 +1648,6 @@ class U_I18N_API DecimalFormat : public NumberFormat { */ virtual void setSecondaryGroupingSize(int32_t newValue); -#ifndef U_HIDE_DRAFT_API /** * Returns the minimum number of grouping digits. * Grouping separators are output if there are at least this many @@ -1672,7 +1669,7 @@ class U_I18N_API DecimalFormat : public NumberFormat { * * @see setMinimumGroupingDigits * @see getGroupingSize - * @draft ICU 64 + * @stable ICU 64 */ int32_t getMinimumGroupingDigits() const; @@ -1684,11 +1681,9 @@ class U_I18N_API DecimalFormat : public NumberFormat { * * @param newValue the new value of minimum grouping digits. * @see getMinimumGroupingDigits - * @draft ICU 64 + * @stable ICU 64 */ void setMinimumGroupingDigits(int32_t newValue); -#endif /* U_HIDE_DRAFT_API */ - /** * Allows you to get the behavior of the decimal separator with integers. @@ -1729,13 +1724,12 @@ class U_I18N_API DecimalFormat : public NumberFormat { */ virtual void setDecimalPatternMatchRequired(UBool newValue); -#ifndef U_HIDE_DRAFT_API /** * Returns whether to ignore exponents when parsing. * * @return Whether to ignore exponents when parsing. * @see #setParseNoExponent - * @draft ICU 64 + * @stable ICU 64 */ UBool isParseNoExponent() const; @@ -1745,7 +1739,7 @@ class U_I18N_API DecimalFormat : public NumberFormat { * 5). * * @param value true to prevent exponents from being parsed; false to allow them to be parsed. - * @draft ICU 64 + * @stable ICU 64 */ void setParseNoExponent(UBool value); @@ -1754,7 +1748,7 @@ class U_I18N_API DecimalFormat : public NumberFormat { * * @return Whether parsing is case-sensitive. * @see #setParseCaseSensitive - * @draft ICU 64 + * @stable ICU 64 */ UBool isParseCaseSensitive() const; @@ -1767,7 +1761,7 @@ class U_I18N_API DecimalFormat : public NumberFormat { * * @param value true to enable case-sensitive parsing (the default); false to force * case-sensitive parsing behavior. - * @draft ICU 64 + * @stable ICU 64 */ void setParseCaseSensitive(UBool value); @@ -1777,7 +1771,7 @@ class U_I18N_API DecimalFormat : public NumberFormat { * * @return Whether an error code is set if high-order digits are truncated. * @see setFormatFailIfMoreThanMaxDigits - * @draft ICU 64 + * @stable ICU 64 */ UBool isFormatFailIfMoreThanMaxDigits() const; @@ -1786,11 +1780,9 @@ class U_I18N_API DecimalFormat : public NumberFormat { * By default, setMaximumIntegerDigits truncates high-order digits silently. * * @param value Whether to set an error code if high-order digits are truncated. - * @draft ICU 64 + * @stable ICU 64 */ void setFormatFailIfMoreThanMaxDigits(UBool value); -#endif /* U_HIDE_DRAFT_API */ - /** * Synthesizes a pattern string that represents the current state @@ -2067,7 +2059,6 @@ class U_I18N_API DecimalFormat : public NumberFormat { #endif /* U_HIDE_INTERNAL_API */ -#ifndef U_HIDE_DRAFT_API /** * Converts this DecimalFormat to a (Localized)NumberFormatter. Starting * in ICU 60, NumberFormatter is the recommended way to format numbers. @@ -2111,10 +2102,9 @@ class U_I18N_API DecimalFormat : public NumberFormat { * @param status Set on failure, like U_MEMORY_ALLOCATION_ERROR. * @return A pointer to an internal object, or nullptr on failure. * Do not delete the return value! - * @draft ICU 64 + * @stable ICU 64 */ const number::LocalizedNumberFormatter* toNumberFormatter(UErrorCode& status) const; -#endif /* U_HIDE_DRAFT_API */ /** * Return the class ID for this class. This is useful only for @@ -2168,11 +2158,17 @@ class U_I18N_API DecimalFormat : public NumberFormat { const numparse::impl::NumberParserImpl* getCurrencyParser(UErrorCode& status) const; - static void fieldPositionHelper(const number::FormattedNumber& formatted, FieldPosition& fieldPosition, - int32_t offset, UErrorCode& status); - - static void fieldPositionIteratorHelper(const number::FormattedNumber& formatted, - FieldPositionIterator* fpi, int32_t offset, UErrorCode& status); + static void fieldPositionHelper( + const number::impl::UFormattedNumberData& formatted, + FieldPosition& fieldPosition, + int32_t offset, + UErrorCode& status); + + static void fieldPositionIteratorHelper( + const number::impl::UFormattedNumberData& formatted, + FieldPositionIterator* fpi, + int32_t offset, + UErrorCode& status); void setupFastFormat(); diff --git a/deps/icu-small/source/i18n/unicode/dtitvfmt.h b/deps/icu-small/source/i18n/unicode/dtitvfmt.h index 23fc02e2a7b16b..4e4d712b4f5b5c 100644 --- a/deps/icu-small/source/i18n/unicode/dtitvfmt.h +++ b/deps/icu-small/source/i18n/unicode/dtitvfmt.h @@ -38,7 +38,6 @@ U_NAMESPACE_BEGIN class FormattedDateIntervalData; class DateIntervalFormat; -#ifndef U_HIDE_DRAFT_API /** * An immutable class containing the result of a date interval formatting operation. * @@ -54,25 +53,25 @@ class DateIntervalFormat; * * Not intended for public subclassing. * - * @draft ICU 64 + * @stable ICU 64 */ class U_I18N_API FormattedDateInterval : public UMemory, public FormattedValue { public: /** * Default constructor; makes an empty FormattedDateInterval. - * @draft ICU 64 + * @stable ICU 64 */ FormattedDateInterval() : fData(nullptr), fErrorCode(U_INVALID_STATE_ERROR) {} /** * Move constructor: Leaves the source FormattedDateInterval in an undefined state. - * @draft ICU 64 + * @stable ICU 64 */ FormattedDateInterval(FormattedDateInterval&& src) U_NOEXCEPT; /** * Destruct an instance of FormattedDateInterval. - * @draft ICU 64 + * @stable ICU 64 */ virtual ~FormattedDateInterval() U_OVERRIDE; @@ -84,7 +83,7 @@ class U_I18N_API FormattedDateInterval : public UMemory, public FormattedValue { /** * Move assignment: Leaves the source FormattedDateInterval in an undefined state. - * @draft ICU 64 + * @stable ICU 64 */ FormattedDateInterval& operator=(FormattedDateInterval&& src) U_NOEXCEPT; @@ -109,7 +108,6 @@ class U_I18N_API FormattedDateInterval : public UMemory, public FormattedValue { : fData(nullptr), fErrorCode(errorCode) {} friend class DateIntervalFormat; }; -#endif /* U_HIDE_DRAFT_API */ /** @@ -174,11 +172,12 @@ class U_I18N_API FormattedDateInterval : public UMemory, public FormattedValue { * *

* The calendar fields we support for interval formatting are: - * year, month, date, day-of-week, am-pm, hour, hour-of-day, minute, and second + * year, month, date, day-of-week, am-pm, hour, hour-of-day, minute, second, + * and millisecond. * (though we do not currently have specific intervalFormat date for skeletons - * with seconds). + * with seconds and millisecond). * Those calendar fields can be defined in the following order: - * year > month > date > hour (in day) > minute > second + * year > month > date > hour (in day) > minute > second > millisecond * * The largest different calendar fields between 2 calendars is the * first different calendar field in above order. @@ -503,7 +502,6 @@ class U_I18N_API DateIntervalFormat : public Format { FieldPosition& fieldPosition, UErrorCode& status) const ; -#ifndef U_HIDE_DRAFT_API /** * Format a DateInterval to produce a FormattedDateInterval. * @@ -512,12 +510,11 @@ class U_I18N_API DateIntervalFormat : public Format { * @param dtInterval DateInterval to be formatted. * @param status Set if an error occurs. * @return A FormattedDateInterval containing the format result. - * @draft ICU 64 + * @stable ICU 64 */ FormattedDateInterval formatToValue( const DateInterval& dtInterval, UErrorCode& status) const; -#endif /* U_HIDE_DRAFT_API */ /** * Format 2 Calendars to produce a string. @@ -548,7 +545,6 @@ class U_I18N_API DateIntervalFormat : public Format { FieldPosition& fieldPosition, UErrorCode& status) const ; -#ifndef U_HIDE_DRAFT_API /** * Format 2 Calendars to produce a FormattedDateInterval. * @@ -563,13 +559,12 @@ class U_I18N_API DateIntervalFormat : public Format { * to be formatted into date interval string * @param status Set if an error occurs. * @return A FormattedDateInterval containing the format result. - * @draft ICU 64 + * @stable ICU 64 */ FormattedDateInterval formatToValue( Calendar& fromCalendar, Calendar& toCalendar, UErrorCode& status) const; -#endif /* U_HIDE_DRAFT_API */ /** * Date interval parsing is not supported. Please do not use. diff --git a/deps/icu-small/source/i18n/unicode/dtitvinf.h b/deps/icu-small/source/i18n/unicode/dtitvinf.h index 3c666231abd060..50e19abb4ce2cb 100644 --- a/deps/icu-small/source/i18n/unicode/dtitvinf.h +++ b/deps/icu-small/source/i18n/unicode/dtitvinf.h @@ -137,8 +137,8 @@ U_NAMESPACE_BEGIN * After a DateIntervalInfo object is created, clients may modify * the interval patterns using setIntervalPattern function as so desired. * Currently, users can only set interval patterns when the following - * calendar fields are different: ERA, YEAR, MONTH, DATE, DAY_OF_MONTH, - * DAY_OF_WEEK, AM_PM, HOUR, HOUR_OF_DAY, and MINUTE. + * calendar fields are different: ERA, YEAR, MONTH, DATE, DAY_OF_MONTH, + * DAY_OF_WEEK, AM_PM, HOUR, HOUR_OF_DAY, MINUTE, SECOND, and MILLISECOND. * Interval patterns when other calendar fields are different is not supported. *

* DateIntervalInfo objects are cloneable. @@ -245,7 +245,7 @@ class U_I18N_API DateIntervalInfo U_FINAL : public UObject { * Restriction: * Currently, users can only set interval patterns when the following * calendar fields are different: ERA, YEAR, MONTH, DATE, DAY_OF_MONTH, - * DAY_OF_WEEK, AM_PM, HOUR, HOUR_OF_DAY, and MINUTE. + * DAY_OF_WEEK, AM_PM, HOUR, HOUR_OF_DAY, MINUTE, SECOND and MILLISECOND. * Interval patterns when other calendar fields are different are * not supported. * @@ -348,7 +348,7 @@ class U_I18N_API DateIntervalInfo U_FINAL : public UObject { /** * Following is for saving the interval patterns. * We only support interval patterns on - * ERA, YEAR, MONTH, DAY, AM_PM, HOUR, and MINUTE + * ERA, YEAR, MONTH, DAY, AM_PM, HOUR, MINUTE, SECOND and MILLISECOND. */ enum IntervalPatternIndex { @@ -360,6 +360,7 @@ class U_I18N_API DateIntervalInfo U_FINAL : public UObject { kIPI_HOUR, kIPI_MINUTE, kIPI_SECOND, + kIPI_MILLISECOND, kIPI_MAX_INDEX }; public: @@ -453,8 +454,8 @@ class U_I18N_API DateIntervalInfo U_FINAL : public UObject { * hash table. * * Since we only support the following calendar fields: - * ERA, YEAR, MONTH, DATE, DAY_OF_MONTH, DAY_OF_WEEK, - * AM_PM, HOUR, HOUR_OF_DAY, and MINUTE, + * ERA, YEAR, MONTH, DATE, DAY_OF_MONTH, DAY_OF_WEEK, + * AM_PM, HOUR, HOUR_OF_DAY, MINUTE, SECOND, and MILLISECOND. * We reserve only 4 interval patterns for a skeleton. * * @param field calendar field diff --git a/deps/icu-small/source/i18n/unicode/dtptngen.h b/deps/icu-small/source/i18n/unicode/dtptngen.h index a71938b31cf5d8..f79c6d45dc6b29 100644 --- a/deps/icu-small/source/i18n/unicode/dtptngen.h +++ b/deps/icu-small/source/i18n/unicode/dtptngen.h @@ -483,6 +483,26 @@ class U_I18N_API DateTimePatternGenerator : public UObject { */ const UnicodeString& getDecimal() const; +#if !UCONFIG_NO_FORMATTING + +#ifndef U_HIDE_DRAFT_API + /** + * Get the default hour cycle for a locale. Uses the locale that the + * DateTimePatternGenerator was initially created with. + * + * Cannot be used on an empty DateTimePatternGenerator instance. + * + * @param status Output param set to success/failure code on exit, which + * which must not indicate a failure before the function call. + * Set to U_UNSUPPORTED_ERROR if used on an empty instance. + * @return the default hour cycle. + * @draft ICU 67 + */ + UDateFormatHourCycle getDefaultHourCycle(UErrorCode& status) const; +#endif /* U_HIDE_DRAFT_API */ + +#endif /* #if !UCONFIG_NO_FORMATTING */ + /** * ICU "poor man's RTTI", returns a UClassID for the actual class. * diff --git a/deps/icu-small/source/i18n/unicode/formattedvalue.h b/deps/icu-small/source/i18n/unicode/formattedvalue.h index 1b130bbdd9d44c..4469b6328e7cb9 100644 --- a/deps/icu-small/source/i18n/unicode/formattedvalue.h +++ b/deps/icu-small/source/i18n/unicode/formattedvalue.h @@ -25,11 +25,6 @@ U_NAMESPACE_BEGIN * of APIs throughout ICU use these classes for expressing their localized output. */ - -// The following cannot have #ifndef U_HIDE_DRAFT_API because -// class FormattedValue depends on it, and FormattedValue cannot be -// hidden becauseclass FormattedNumber (stable ICU 60) depends on it. -#ifndef U_FORCE_HIDE_DRAFT_API /** * Represents a span of a string containing a given field. * @@ -41,7 +36,7 @@ U_NAMESPACE_BEGIN * * This class is not intended for public subclassing. * - * @draft ICU 64 + * @stable ICU 64 */ class U_I18N_API ConstrainedFieldPosition : public UMemory { public: @@ -51,21 +46,20 @@ class U_I18N_API ConstrainedFieldPosition : public UMemory { * * By default, the ConstrainedFieldPosition has no iteration constraints. * - * @draft ICU 64 + * @stable ICU 64 */ ConstrainedFieldPosition(); - /** @draft ICU 64 */ + /** @stable ICU 64 */ ~ConstrainedFieldPosition(); -#ifndef U_HIDE_DRAFT_API /** * Resets this ConstrainedFieldPosition to its initial state, as if it were newly created: * * - Removes any constraints that may have been set on the instance. * - Resets the iteration position. * - * @draft ICU 64 + * @stable ICU 64 */ void reset(); @@ -89,7 +83,7 @@ class U_I18N_API ConstrainedFieldPosition : public UMemory { * does not generally have well-defined behavior. * * @param category The field category to fix when iterating. - * @draft ICU 64 + * @stable ICU 64 */ void constrainCategory(int32_t category); @@ -114,7 +108,7 @@ class U_I18N_API ConstrainedFieldPosition : public UMemory { * * @param category The field category to fix when iterating. * @param field The field to fix when iterating. - * @draft ICU 64 + * @stable ICU 64 */ void constrainField(int32_t category, int32_t field); @@ -125,7 +119,7 @@ class U_I18N_API ConstrainedFieldPosition : public UMemory { * FormattedValue#nextPosition returns TRUE. * * @return The field category saved in the instance. - * @draft ICU 64 + * @stable ICU 64 */ inline int32_t getCategory() const { return fCategory; @@ -138,7 +132,7 @@ class U_I18N_API ConstrainedFieldPosition : public UMemory { * FormattedValue#nextPosition returns TRUE. * * @return The field saved in the instance. - * @draft ICU 64 + * @stable ICU 64 */ inline int32_t getField() const { return fField; @@ -150,7 +144,7 @@ class U_I18N_API ConstrainedFieldPosition : public UMemory { * The return value is well-defined only after FormattedValue#nextPosition returns TRUE. * * @return The start index saved in the instance. - * @draft ICU 64 + * @stable ICU 64 */ inline int32_t getStart() const { return fStart; @@ -162,7 +156,7 @@ class U_I18N_API ConstrainedFieldPosition : public UMemory { * The return value is well-defined only after FormattedValue#nextPosition returns TRUE. * * @return The end index saved in the instance. - * @draft ICU 64 + * @stable ICU 64 */ inline int32_t getLimit() const { return fLimit; @@ -181,7 +175,7 @@ class U_I18N_API ConstrainedFieldPosition : public UMemory { * Users of FormattedValue should not need to call this method. * * @return The current iteration context from {@link #setInt64IterationContext}. - * @draft ICU 64 + * @stable ICU 64 */ inline int64_t getInt64IterationContext() const { return fContext; @@ -193,7 +187,7 @@ class U_I18N_API ConstrainedFieldPosition : public UMemory { * Intended to be used by FormattedValue implementations. * * @param context The new iteration context. - * @draft ICU 64 + * @stable ICU 64 */ void setInt64IterationContext(int64_t context); @@ -205,7 +199,7 @@ class U_I18N_API ConstrainedFieldPosition : public UMemory { * * @param category The category to test. * @param field The field to test. - * @draft ICU 64 + * @stable ICU 64 */ UBool matchesField(int32_t category, int32_t field) const; @@ -221,39 +215,32 @@ class U_I18N_API ConstrainedFieldPosition : public UMemory { * @param field The new field. * @param start The new inclusive start index. * @param limit The new exclusive end index. - * @draft ICU 64 + * @stable ICU 64 */ void setState( int32_t category, int32_t field, int32_t start, int32_t limit); -#endif /* U_HIDE_DRAFT_API */ private: int64_t fContext = 0LL; int32_t fField = 0; int32_t fStart = 0; int32_t fLimit = 0; -#ifndef U_HIDE_DRAFT_API int32_t fCategory = UFIELD_CATEGORY_UNDEFINED; -#else /* U_HIDE_DRAFT_API */ - int32_t fCategory = 0; -#endif /* U_HIDE_DRAFT_API */ int8_t fConstraint = 0; }; -// The following cannot have #ifndef U_HIDE_DRAFT_API because -// class FormattedNumber (stable ICU 60) depends on it. /** * An abstract formatted value: a string with associated field attributes. * Many formatters format to classes implementing FormattedValue. * - * @draft ICU 64 + * @stable ICU 64 */ class U_I18N_API FormattedValue /* not : public UObject because this is an interface/mixin class */ { public: - /** @draft ICU 64 */ + /** @stable ICU 64 */ virtual ~FormattedValue(); /** @@ -264,7 +251,7 @@ class U_I18N_API FormattedValue /* not : public UObject because this is an inter * @param status Set if an error occurs. * @return a UnicodeString containing the formatted string. * - * @draft ICU 64 + * @stable ICU 64 */ virtual UnicodeString toString(UErrorCode& status) const = 0; @@ -280,7 +267,7 @@ class U_I18N_API FormattedValue /* not : public UObject because this is an inter * @param status Set if an error occurs. * @return a temporary UnicodeString containing the formatted string. * - * @draft ICU 64 + * @stable ICU 64 */ virtual UnicodeString toTempString(UErrorCode& status) const = 0; @@ -292,7 +279,7 @@ class U_I18N_API FormattedValue /* not : public UObject because this is an inter * @param status Set if an error occurs. * @return The same Appendable, for chaining. * - * @draft ICU 64 + * @stable ICU 64 * @see Appendable */ virtual Appendable& appendTo(Appendable& appendable, UErrorCode& status) const = 0; @@ -317,11 +304,10 @@ class U_I18N_API FormattedValue /* not : public UObject because this is an inter * @return TRUE if a new occurrence of the field was found; * FALSE otherwise or if an error was set. * - * @draft ICU 64 + * @stable ICU 64 */ virtual UBool nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const = 0; }; -#endif // U_FORCE_HIDE_DRAFT_API U_NAMESPACE_END diff --git a/deps/icu-small/source/i18n/unicode/listformatter.h b/deps/icu-small/source/i18n/unicode/listformatter.h index 88fc46cf37b2a3..a969a8744dcf58 100644 --- a/deps/icu-small/source/i18n/unicode/listformatter.h +++ b/deps/icu-small/source/i18n/unicode/listformatter.h @@ -26,10 +26,10 @@ #include "unicode/unistr.h" #include "unicode/locid.h" #include "unicode/formattedvalue.h" +#include "unicode/ulistformatter.h" U_NAMESPACE_BEGIN -class FieldPositionIterator; class FieldPositionHandler; class FormattedListData; class ListFormatter; @@ -50,9 +50,11 @@ struct ListFormatData : public UMemory { UnicodeString startPattern; UnicodeString middlePattern; UnicodeString endPattern; + Locale locale; - ListFormatData(const UnicodeString& two, const UnicodeString& start, const UnicodeString& middle, const UnicodeString& end) : - twoPattern(two), startPattern(start), middlePattern(middle), endPattern(end) {} + ListFormatData(const UnicodeString& two, const UnicodeString& start, const UnicodeString& middle, const UnicodeString& end, + const Locale& loc) : + twoPattern(two), startPattern(start), middlePattern(middle), endPattern(end), locale(loc) {} }; /** \endcond */ @@ -64,7 +66,6 @@ struct ListFormatData : public UMemory { #if !UCONFIG_NO_FORMATTING -#ifndef U_HIDE_DRAFT_API /** * An immutable class containing the result of a list formatting operation. * @@ -79,25 +80,25 @@ struct ListFormatData : public UMemory { * * Not intended for public subclassing. * - * @draft ICU 64 + * @stable ICU 64 */ class U_I18N_API FormattedList : public UMemory, public FormattedValue { public: /** * Default constructor; makes an empty FormattedList. - * @draft ICU 64 + * @stable ICU 64 */ FormattedList() : fData(nullptr), fErrorCode(U_INVALID_STATE_ERROR) {} /** * Move constructor: Leaves the source FormattedList in an undefined state. - * @draft ICU 64 + * @stable ICU 64 */ FormattedList(FormattedList&& src) U_NOEXCEPT; /** * Destruct an instance of FormattedList. - * @draft ICU 64 + * @stable ICU 64 */ virtual ~FormattedList() U_OVERRIDE; @@ -109,7 +110,7 @@ class U_I18N_API FormattedList : public UMemory, public FormattedValue { /** * Move assignment: Leaves the source FormattedList in an undefined state. - * @draft ICU 64 + * @stable ICU 64 */ FormattedList& operator=(FormattedList&& src) U_NOEXCEPT; @@ -134,7 +135,6 @@ class U_I18N_API FormattedList : public UMemory, public FormattedValue { : fData(nullptr), fErrorCode(errorCode) {} friend class ListFormatter; }; -#endif /* U_HIDE_DRAFT_API */ #endif // !UCONFIG_NO_FORMATTING @@ -185,10 +185,29 @@ class U_I18N_API ListFormatter : public UObject{ */ static ListFormatter* createInstance(const Locale& locale, UErrorCode& errorCode); +#ifndef U_HIDE_DRAFT_API +#if !UCONFIG_NO_FORMATTING + /** + * Creates a ListFormatter for the given locale, list type, and style. + * + * @param locale The locale. + * @param type The type of list formatting to use. + * @param width The width of formatting to use. + * @param errorCode ICU error code, set if no data available for the given locale. + * @return A ListFormatter object created from internal data derived from CLDR data. + * @draft ICU 67 + */ + static ListFormatter* createInstance( + const Locale& locale, UListFormatterType type, UListFormatterWidth width, UErrorCode& errorCode); +#endif /* !UCONFIG_NO_FORMATTING */ +#endif /* U_HIDE_DRAFT_API */ + #ifndef U_HIDE_INTERNAL_API /** * Creates a ListFormatter appropriate for a locale and style. * + * TODO(ICU-20888): Remove this in ICU 68. + * * @param locale The locale. * @param style the style, either "standard", "or", "unit", "unit-narrow", or "unit-short" * @param errorCode ICU error code, set if no data available for the given locale. @@ -220,29 +239,7 @@ class U_I18N_API ListFormatter : public UObject{ UnicodeString& format(const UnicodeString items[], int32_t n_items, UnicodeString& appendTo, UErrorCode& errorCode) const; -#ifndef U_HIDE_DRAFT_API - /** - * Format a list of strings. - * - * @param items An array of strings to be combined and formatted. - * @param n_items Length of the array items. - * @param appendTo The string to which the formatted result will be - * appended. - * @param posIter On return, can be used to iterate over positions of - * fields generated by this format call. Field values are - * defined in UListFormatterField. Can be NULL. - * @param errorCode ICU error code returned here. - * @return Formatted string combining the elements of items, - * appended to appendTo. - * @draft ICU 63 - */ - UnicodeString& format(const UnicodeString items[], int32_t n_items, - UnicodeString & appendTo, FieldPositionIterator* posIter, - UErrorCode& errorCode) const; -#endif // U_HIDE_DRAFT_API - #if !UCONFIG_NO_FORMATTING -#ifndef U_HIDE_DRAFT_API /** * Formats a list of strings to a FormattedList, which exposes field * position information. The FormattedList contains more information than @@ -252,13 +249,12 @@ class U_I18N_API ListFormatter : public UObject{ * @param n_items Length of the array items. * @param errorCode ICU error code returned here. * @return A FormattedList containing field information. - * @draft ICU 64 + * @stable ICU 64 */ FormattedList formatStringsToValue( const UnicodeString items[], int32_t n_items, UErrorCode& errorCode) const; -#endif /* U_HIDE_DRAFT_API */ #endif // !UCONFIG_NO_FORMATTING #ifndef U_HIDE_INTERNAL_API diff --git a/deps/icu-small/source/i18n/unicode/measunit.h b/deps/icu-small/source/i18n/unicode/measunit.h index 08f337cb5bb630..8b65497e12eb63 100644 --- a/deps/icu-small/source/i18n/unicode/measunit.h +++ b/deps/icu-small/source/i18n/unicode/measunit.h @@ -20,6 +20,7 @@ #if !UCONFIG_NO_FORMATTING #include "unicode/unistr.h" +#include "unicode/localpointer.h" /** * \file @@ -29,6 +30,202 @@ U_NAMESPACE_BEGIN class StringEnumeration; +struct MeasureUnitImpl; + +#ifndef U_HIDE_DRAFT_API +/** + * Enumeration for unit complexity. There are three levels: + * + * - SINGLE: A single unit, optionally with a power and/or SI prefix. Examples: hectare, + * square-kilometer, kilojoule, per-second. + * - COMPOUND: A unit composed of the product of multiple single units. Examples: + * meter-per-second, kilowatt-hour, kilogram-meter-per-square-second. + * - MIXED: A unit composed of the sum of multiple single units. Examples: foot+inch, + * hour+minute+second, degree+arcminute+arcsecond. + * + * The complexity determines which operations are available. For example, you cannot set the power + * or SI prefix of a compound unit. + * + * @draft ICU 67 + */ +enum UMeasureUnitComplexity { + /** + * A single unit, like kilojoule. + * + * @draft ICU 67 + */ + UMEASURE_UNIT_SINGLE, + + /** + * A compound unit, like meter-per-second. + * + * @draft ICU 67 + */ + UMEASURE_UNIT_COMPOUND, + + /** + * A mixed unit, like hour+minute. + * + * @draft ICU 67 + */ + UMEASURE_UNIT_MIXED +}; + +/** + * Enumeration for SI prefixes, such as "kilo". + * + * @draft ICU 67 + */ +typedef enum UMeasureSIPrefix { + + /** + * SI prefix: yotta, 10^24. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_YOTTA = 24, + + /** + * SI prefix: zetta, 10^21. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_ZETTA = 21, + + /** + * SI prefix: exa, 10^18. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_EXA = 18, + + /** + * SI prefix: peta, 10^15. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_PETA = 15, + + /** + * SI prefix: tera, 10^12. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_TERA = 12, + + /** + * SI prefix: giga, 10^9. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_GIGA = 9, + + /** + * SI prefix: mega, 10^6. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_MEGA = 6, + + /** + * SI prefix: kilo, 10^3. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_KILO = 3, + + /** + * SI prefix: hecto, 10^2. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_HECTO = 2, + + /** + * SI prefix: deka, 10^1. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_DEKA = 1, + + /** + * The absence of an SI prefix. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_ONE = 0, + + /** + * SI prefix: deci, 10^-1. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_DECI = -1, + + /** + * SI prefix: centi, 10^-2. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_CENTI = -2, + + /** + * SI prefix: milli, 10^-3. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_MILLI = -3, + + /** + * SI prefix: micro, 10^-6. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_MICRO = -6, + + /** + * SI prefix: nano, 10^-9. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_NANO = -9, + + /** + * SI prefix: pico, 10^-12. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_PICO = -12, + + /** + * SI prefix: femto, 10^-15. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_FEMTO = -15, + + /** + * SI prefix: atto, 10^-18. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_ATTO = -18, + + /** + * SI prefix: zepto, 10^-21. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_ZEPTO = -21, + + /** + * SI prefix: yocto, 10^-24. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_YOCTO = -24 +} UMeasureSIPrefix; +#endif // U_HIDE_DRAFT_API /** * A unit such as length, mass, volume, currency, etc. A unit is @@ -53,12 +250,42 @@ class U_I18N_API MeasureUnit: public UObject { */ MeasureUnit(const MeasureUnit &other); +#ifndef U_HIDE_DRAFT_API + /** + * Move constructor. + * @draft ICU 67 + */ + MeasureUnit(MeasureUnit &&other) noexcept; + + /** + * Construct a MeasureUnit from a CLDR Unit Identifier, defined in UTS 35. + * Validates and canonicalizes the identifier. + * + *

+     * MeasureUnit example = MeasureUnit::forIdentifier("furlong-per-nanosecond")
+     * 
+ * + * @param identifier The CLDR Unit Identifier + * @param status Set if the identifier is invalid. + * @draft ICU 67 + */ + static MeasureUnit forIdentifier(StringPiece identifier, UErrorCode& status); +#endif // U_HIDE_DRAFT_API + /** - * Assignment operator. + * Copy assignment operator. * @stable ICU 3.0 */ MeasureUnit &operator=(const MeasureUnit &other); +#ifndef U_HIDE_DRAFT_API + /** + * Move assignment operator. + * @draft ICU 67 + */ + MeasureUnit &operator=(MeasureUnit &&other) noexcept; +#endif // U_HIDE_DRAFT_API + /** * Returns a polymorphic clone of this object. The result will * have the same class as returned by getDynamicClassID(). @@ -90,16 +317,156 @@ class U_I18N_API MeasureUnit: public UObject { /** * Get the type. + * + * If the unit does not have a type, the empty string is returned. + * * @stable ICU 53 */ const char *getType() const; /** * Get the sub type. + * + * If the unit does not have a subtype, the empty string is returned. + * * @stable ICU 53 */ const char *getSubtype() const; +#ifndef U_HIDE_DRAFT_API + /** + * Get the CLDR Unit Identifier for this MeasureUnit, as defined in UTS 35. + * + * @return The string form of this unit, owned by this MeasureUnit. + * @draft ICU 67 + */ + const char* getIdentifier() const; + + /** + * Compute the complexity of the unit. See UMeasureUnitComplexity for more information. + * + * @param status Set if an error occurs. + * @return The unit complexity. + * @draft ICU 67 + */ + UMeasureUnitComplexity getComplexity(UErrorCode& status) const; + + /** + * Creates a MeasureUnit which is this SINGLE unit augmented with the specified SI prefix. + * For example, UMEASURE_SI_PREFIX_KILO for "kilo". + * + * There is sufficient locale data to format all standard SI prefixes. + * + * NOTE: Only works on SINGLE units. If this is a COMPOUND or MIXED unit, an error will + * occur. For more information, see UMeasureUnitComplexity. + * + * @param prefix The SI prefix, from UMeasureSIPrefix. + * @param status Set if this is not a SINGLE unit or if another error occurs. + * @return A new SINGLE unit. + * @draft ICU 67 + */ + MeasureUnit withSIPrefix(UMeasureSIPrefix prefix, UErrorCode& status) const; + + /** + * Gets the current SI prefix of this SINGLE unit. For example, if the unit has the SI prefix + * "kilo", then UMEASURE_SI_PREFIX_KILO is returned. + * + * NOTE: Only works on SINGLE units. If this is a COMPOUND or MIXED unit, an error will + * occur. For more information, see UMeasureUnitComplexity. + * + * @param status Set if this is not a SINGLE unit or if another error occurs. + * @return The SI prefix of this SINGLE unit, from UMeasureSIPrefix. + * @draft ICU 67 + */ + UMeasureSIPrefix getSIPrefix(UErrorCode& status) const; + + /** + * Creates a MeasureUnit which is this SINGLE unit augmented with the specified dimensionality + * (power). For example, if dimensionality is 2, the unit will be squared. + * + * NOTE: Only works on SINGLE units. If this is a COMPOUND or MIXED unit, an error will + * occur. For more information, see UMeasureUnitComplexity. + * + * For the base dimensionless unit, withDimensionality does nothing. + * + * @param dimensionality The dimensionality (power). + * @param status Set if this is not a SINGLE unit or if another error occurs. + * @return A new SINGLE unit. + * @draft ICU 67 + */ + MeasureUnit withDimensionality(int32_t dimensionality, UErrorCode& status) const; + + /** + * Gets the dimensionality (power) of this MeasureUnit. For example, if the unit is square, + * then 2 is returned. + * + * NOTE: Only works on SINGLE units. If this is a COMPOUND or MIXED unit, an error will + * occur. For more information, see UMeasureUnitComplexity. + * + * For the base dimensionless unit, getDimensionality returns 0. + * + * @param status Set if this is not a SINGLE unit or if another error occurs. + * @return The dimensionality (power) of this simple unit. + * @draft ICU 67 + */ + int32_t getDimensionality(UErrorCode& status) const; + + /** + * Gets the reciprocal of this MeasureUnit, with the numerator and denominator flipped. + * + * For example, if the receiver is "meter-per-second", the unit "second-per-meter" is returned. + * + * NOTE: Only works on SINGLE and COMPOUND units. If this is a MIXED unit, an error will + * occur. For more information, see UMeasureUnitComplexity. + * + * @param status Set if this is a MIXED unit or if another error occurs. + * @return The reciprocal of the target unit. + * @draft ICU 67 + */ + MeasureUnit reciprocal(UErrorCode& status) const; + + /** + * Gets the product of this unit with another unit. This is a way to build units from + * constituent parts. + * + * The numerator and denominator are preserved through this operation. + * + * For example, if the receiver is "kilowatt" and the argument is "hour-per-day", then the + * unit "kilowatt-hour-per-day" is returned. + * + * NOTE: Only works on SINGLE and COMPOUND units. If either unit (receivee and argument) is a + * MIXED unit, an error will occur. For more information, see UMeasureUnitComplexity. + * + * @param other The MeasureUnit to multiply with the target. + * @param status Set if this or other is a MIXED unit or if another error occurs. + * @return The product of the target unit with the provided unit. + * @draft ICU 67 + */ + MeasureUnit product(const MeasureUnit& other, UErrorCode& status) const; +#endif // U_HIDE_DRAFT_API + +#ifndef U_HIDE_INTERNAL_API + /** + * Gets the list of SINGLE units contained within a MIXED of COMPOUND unit. + * + * Examples: + * - Given "meter-kilogram-per-second", three units will be returned: "meter", + * "kilogram", and "per-second". + * - Given "hour+minute+second", three units will be returned: "hour", "minute", + * and "second". + * + * If this is a SINGLE unit, an array of length 1 will be returned. + * + * TODO(ICU-21021): Finalize this API and propose it as draft. + * + * @param outCount The number of elements in the return array. + * @param status Set if an error occurs. + * @return An array of single units, owned by the caller. + * @internal ICU 67 Technical Preview + */ + LocalArray splitToSingleUnits(int32_t& outCount, UErrorCode& status) const; +#endif // U_HIDE_INTERNAL_API + /** * getAvailable gets all of the available units. * If there are too many units to fit into destCapacity then the @@ -219,17 +586,15 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createGForce(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of acceleration: g-force. * Also see {@link #createGForce()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getGForce(); -#endif /* U_HIDE_DRAFT_API */ /** - * Returns by pointer, unit of acceleration: meter-per-second-squared. + * Returns by pointer, unit of acceleration: meter-per-square-second. * Caller owns returned value and must free it. * Also see {@link #getMeterPerSecondSquared()}. * @param status ICU error code. @@ -237,14 +602,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMeterPerSecondSquared(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** - * Returns by value, unit of acceleration: meter-per-second-squared. + * Returns by value, unit of acceleration: meter-per-square-second. * Also see {@link #createMeterPerSecondSquared()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMeterPerSecondSquared(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of angle: arc-minute. @@ -255,14 +618,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createArcMinute(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of angle: arc-minute. * Also see {@link #createArcMinute()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getArcMinute(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of angle: arc-second. @@ -273,14 +634,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createArcSecond(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of angle: arc-second. * Also see {@link #createArcSecond()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getArcSecond(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of angle: degree. @@ -291,14 +650,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createDegree(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of angle: degree. * Also see {@link #createDegree()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getDegree(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of angle: radian. @@ -309,14 +666,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createRadian(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of angle: radian. * Also see {@link #createRadian()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getRadian(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of angle: revolution. @@ -327,14 +682,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createRevolutionAngle(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of angle: revolution. * Also see {@link #createRevolutionAngle()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getRevolutionAngle(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of area: acre. @@ -345,32 +698,28 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createAcre(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of area: acre. * Also see {@link #createAcre()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getAcre(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of area: dunam. * Caller owns returned value and must free it. * Also see {@link #getDunam()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createDunam(UErrorCode &status); /** * Returns by value, unit of area: dunam. * Also see {@link #createDunam()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getDunam(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of area: hectare. @@ -381,14 +730,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createHectare(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of area: hectare. * Also see {@link #createHectare()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getHectare(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of area: square-centimeter. @@ -399,14 +746,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createSquareCentimeter(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of area: square-centimeter. * Also see {@link #createSquareCentimeter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getSquareCentimeter(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of area: square-foot. @@ -417,14 +762,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createSquareFoot(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of area: square-foot. * Also see {@link #createSquareFoot()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getSquareFoot(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of area: square-inch. @@ -435,14 +778,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createSquareInch(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of area: square-inch. * Also see {@link #createSquareInch()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getSquareInch(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of area: square-kilometer. @@ -453,14 +794,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createSquareKilometer(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of area: square-kilometer. * Also see {@link #createSquareKilometer()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getSquareKilometer(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of area: square-meter. @@ -471,14 +810,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createSquareMeter(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of area: square-meter. * Also see {@link #createSquareMeter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getSquareMeter(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of area: square-mile. @@ -489,14 +826,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createSquareMile(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of area: square-mile. * Also see {@link #createSquareMile()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getSquareMile(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of area: square-yard. @@ -507,14 +842,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createSquareYard(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of area: square-yard. * Also see {@link #createSquareYard()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getSquareYard(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of concentr: karat. @@ -525,14 +858,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createKarat(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of concentr: karat. * Also see {@link #createKarat()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getKarat(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of concentr: milligram-per-deciliter. @@ -543,14 +874,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMilligramPerDeciliter(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of concentr: milligram-per-deciliter. * Also see {@link #createMilligramPerDeciliter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMilligramPerDeciliter(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of concentr: millimole-per-liter. @@ -561,35 +890,31 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMillimolePerLiter(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of concentr: millimole-per-liter. * Also see {@link #createMillimolePerLiter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMillimolePerLiter(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of concentr: mole. * Caller owns returned value and must free it. * Also see {@link #getMole()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createMole(UErrorCode &status); /** * Returns by value, unit of concentr: mole. * Also see {@link #createMole()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMole(); -#endif /* U_HIDE_DRAFT_API */ /** - * Returns by pointer, unit of concentr: part-per-million. + * Returns by pointer, unit of concentr: permillion. * Caller owns returned value and must free it. * Also see {@link #getPartPerMillion()}. * @param status ICU error code. @@ -597,14 +922,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createPartPerMillion(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** - * Returns by value, unit of concentr: part-per-million. + * Returns by value, unit of concentr: permillion. * Also see {@link #createPartPerMillion()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getPartPerMillion(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of concentr: percent. @@ -615,14 +938,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createPercent(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of concentr: percent. * Also see {@link #createPercent()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getPercent(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of concentr: permille. @@ -633,35 +954,31 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createPermille(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of concentr: permille. * Also see {@link #createPermille()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getPermille(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of concentr: permyriad. * Caller owns returned value and must free it. * Also see {@link #getPermyriad()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createPermyriad(UErrorCode &status); /** * Returns by value, unit of concentr: permyriad. * Also see {@link #createPermyriad()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getPermyriad(); -#endif /* U_HIDE_DRAFT_API */ /** - * Returns by pointer, unit of consumption: liter-per-100kilometers. + * Returns by pointer, unit of consumption: liter-per-100-kilometer. * Caller owns returned value and must free it. * Also see {@link #getLiterPer100Kilometers()}. * @param status ICU error code. @@ -669,14 +986,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createLiterPer100Kilometers(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** - * Returns by value, unit of consumption: liter-per-100kilometers. + * Returns by value, unit of consumption: liter-per-100-kilometer. * Also see {@link #createLiterPer100Kilometers()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getLiterPer100Kilometers(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of consumption: liter-per-kilometer. @@ -687,14 +1002,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createLiterPerKilometer(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of consumption: liter-per-kilometer. * Also see {@link #createLiterPerKilometer()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getLiterPerKilometer(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of consumption: mile-per-gallon. @@ -705,14 +1018,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMilePerGallon(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of consumption: mile-per-gallon. * Also see {@link #createMilePerGallon()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMilePerGallon(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of consumption: mile-per-gallon-imperial. @@ -723,14 +1034,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMilePerGallonImperial(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of consumption: mile-per-gallon-imperial. * Also see {@link #createMilePerGallonImperial()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMilePerGallonImperial(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of digital: bit. @@ -741,14 +1050,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createBit(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of digital: bit. * Also see {@link #createBit()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getBit(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of digital: byte. @@ -759,14 +1066,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createByte(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of digital: byte. * Also see {@link #createByte()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getByte(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of digital: gigabit. @@ -777,14 +1082,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createGigabit(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of digital: gigabit. * Also see {@link #createGigabit()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getGigabit(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of digital: gigabyte. @@ -795,14 +1098,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createGigabyte(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of digital: gigabyte. * Also see {@link #createGigabyte()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getGigabyte(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of digital: kilobit. @@ -813,14 +1114,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createKilobit(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of digital: kilobit. * Also see {@link #createKilobit()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getKilobit(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of digital: kilobyte. @@ -831,14 +1130,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createKilobyte(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of digital: kilobyte. * Also see {@link #createKilobyte()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getKilobyte(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of digital: megabit. @@ -849,14 +1146,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMegabit(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of digital: megabit. * Also see {@link #createMegabit()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMegabit(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of digital: megabyte. @@ -867,14 +1162,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMegabyte(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of digital: megabyte. * Also see {@link #createMegabyte()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMegabyte(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of digital: petabyte. @@ -885,14 +1178,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createPetabyte(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of digital: petabyte. * Also see {@link #createPetabyte()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getPetabyte(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of digital: terabit. @@ -903,14 +1194,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createTerabit(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of digital: terabit. * Also see {@link #createTerabit()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getTerabit(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of digital: terabyte. @@ -921,14 +1210,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createTerabyte(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of digital: terabyte. * Also see {@link #createTerabyte()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getTerabyte(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of duration: century. @@ -939,14 +1226,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createCentury(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of duration: century. * Also see {@link #createCentury()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getCentury(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of duration: day. @@ -957,32 +1242,28 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createDay(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of duration: day. * Also see {@link #createDay()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getDay(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of duration: day-person. * Caller owns returned value and must free it. * Also see {@link #getDayPerson()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createDayPerson(UErrorCode &status); /** * Returns by value, unit of duration: day-person. * Also see {@link #createDayPerson()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getDayPerson(); -#endif /* U_HIDE_DRAFT_API */ #ifndef U_HIDE_DRAFT_API /** @@ -1011,14 +1292,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createHour(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of duration: hour. * Also see {@link #createHour()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getHour(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of duration: microsecond. @@ -1029,14 +1308,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMicrosecond(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of duration: microsecond. * Also see {@link #createMicrosecond()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMicrosecond(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of duration: millisecond. @@ -1047,14 +1324,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMillisecond(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of duration: millisecond. * Also see {@link #createMillisecond()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMillisecond(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of duration: minute. @@ -1065,14 +1340,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMinute(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of duration: minute. * Also see {@link #createMinute()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMinute(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of duration: month. @@ -1083,32 +1356,28 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMonth(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of duration: month. * Also see {@link #createMonth()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMonth(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of duration: month-person. * Caller owns returned value and must free it. * Also see {@link #getMonthPerson()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createMonthPerson(UErrorCode &status); /** * Returns by value, unit of duration: month-person. * Also see {@link #createMonthPerson()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMonthPerson(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of duration: nanosecond. @@ -1119,14 +1388,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createNanosecond(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of duration: nanosecond. * Also see {@link #createNanosecond()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getNanosecond(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of duration: second. @@ -1137,14 +1404,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createSecond(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of duration: second. * Also see {@link #createSecond()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getSecond(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of duration: week. @@ -1155,32 +1420,28 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createWeek(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of duration: week. * Also see {@link #createWeek()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getWeek(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of duration: week-person. * Caller owns returned value and must free it. * Also see {@link #getWeekPerson()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createWeekPerson(UErrorCode &status); /** * Returns by value, unit of duration: week-person. * Also see {@link #createWeekPerson()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getWeekPerson(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of duration: year. @@ -1191,32 +1452,28 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createYear(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of duration: year. * Also see {@link #createYear()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getYear(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of duration: year-person. * Caller owns returned value and must free it. * Also see {@link #getYearPerson()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createYearPerson(UErrorCode &status); /** * Returns by value, unit of duration: year-person. * Also see {@link #createYearPerson()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getYearPerson(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of electric: ampere. @@ -1227,14 +1484,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createAmpere(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of electric: ampere. * Also see {@link #createAmpere()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getAmpere(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of electric: milliampere. @@ -1245,14 +1500,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMilliampere(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of electric: milliampere. * Also see {@link #createMilliampere()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMilliampere(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of electric: ohm. @@ -1263,14 +1516,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createOhm(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of electric: ohm. * Also see {@link #createOhm()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getOhm(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of electric: volt. @@ -1281,32 +1532,28 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createVolt(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of electric: volt. * Also see {@link #createVolt()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getVolt(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of energy: british-thermal-unit. * Caller owns returned value and must free it. * Also see {@link #getBritishThermalUnit()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createBritishThermalUnit(UErrorCode &status); /** * Returns by value, unit of energy: british-thermal-unit. * Also see {@link #createBritishThermalUnit()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getBritishThermalUnit(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of energy: calorie. @@ -1317,32 +1564,28 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createCalorie(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of energy: calorie. * Also see {@link #createCalorie()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getCalorie(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of energy: electronvolt. * Caller owns returned value and must free it. * Also see {@link #getElectronvolt()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createElectronvolt(UErrorCode &status); /** * Returns by value, unit of energy: electronvolt. * Also see {@link #createElectronvolt()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getElectronvolt(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of energy: foodcalorie. @@ -1353,14 +1596,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createFoodcalorie(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of energy: foodcalorie. * Also see {@link #createFoodcalorie()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getFoodcalorie(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of energy: joule. @@ -1371,14 +1612,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createJoule(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of energy: joule. * Also see {@link #createJoule()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getJoule(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of energy: kilocalorie. @@ -1389,14 +1628,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createKilocalorie(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of energy: kilocalorie. * Also see {@link #createKilocalorie()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getKilocalorie(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of energy: kilojoule. @@ -1407,14 +1644,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createKilojoule(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of energy: kilojoule. * Also see {@link #createKilojoule()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getKilojoule(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of energy: kilowatt-hour. @@ -1425,14 +1660,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createKilowattHour(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of energy: kilowatt-hour. * Also see {@link #createKilowattHour()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getKilowattHour(); -#endif /* U_HIDE_DRAFT_API */ #ifndef U_HIDE_DRAFT_API /** @@ -1452,41 +1685,37 @@ class U_I18N_API MeasureUnit: public UObject { static MeasureUnit getThermUs(); #endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of force: newton. * Caller owns returned value and must free it. * Also see {@link #getNewton()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createNewton(UErrorCode &status); /** * Returns by value, unit of force: newton. * Also see {@link #createNewton()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getNewton(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of force: pound-force. * Caller owns returned value and must free it. * Also see {@link #getPoundForce()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createPoundForce(UErrorCode &status); /** * Returns by value, unit of force: pound-force. * Also see {@link #createPoundForce()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getPoundForce(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of frequency: gigahertz. @@ -1497,14 +1726,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createGigahertz(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of frequency: gigahertz. * Also see {@link #createGigahertz()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getGigahertz(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of frequency: hertz. @@ -1515,14 +1742,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createHertz(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of frequency: hertz. * Also see {@link #createHertz()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getHertz(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of frequency: kilohertz. @@ -1533,14 +1758,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createKilohertz(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of frequency: kilohertz. * Also see {@link #createKilohertz()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getKilohertz(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of frequency: megahertz. @@ -1551,14 +1774,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMegahertz(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of frequency: megahertz. * Also see {@link #createMegahertz()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMegahertz(); -#endif /* U_HIDE_DRAFT_API */ #ifndef U_HIDE_DRAFT_API /** @@ -1695,14 +1916,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createAstronomicalUnit(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: astronomical-unit. * Also see {@link #createAstronomicalUnit()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getAstronomicalUnit(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: centimeter. @@ -1713,14 +1932,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createCentimeter(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: centimeter. * Also see {@link #createCentimeter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getCentimeter(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: decimeter. @@ -1731,14 +1948,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createDecimeter(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: decimeter. * Also see {@link #createDecimeter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getDecimeter(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: fathom. @@ -1749,14 +1964,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createFathom(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: fathom. * Also see {@link #createFathom()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getFathom(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: foot. @@ -1767,14 +1980,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createFoot(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: foot. * Also see {@link #createFoot()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getFoot(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: furlong. @@ -1785,14 +1996,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createFurlong(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: furlong. * Also see {@link #createFurlong()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getFurlong(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: inch. @@ -1803,14 +2012,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createInch(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: inch. * Also see {@link #createInch()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getInch(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: kilometer. @@ -1821,14 +2028,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createKilometer(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: kilometer. * Also see {@link #createKilometer()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getKilometer(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: light-year. @@ -1839,14 +2044,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createLightYear(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: light-year. * Also see {@link #createLightYear()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getLightYear(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: meter. @@ -1857,14 +2060,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMeter(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: meter. * Also see {@link #createMeter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMeter(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: micrometer. @@ -1875,14 +2076,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMicrometer(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: micrometer. * Also see {@link #createMicrometer()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMicrometer(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: mile. @@ -1893,14 +2092,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMile(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: mile. * Also see {@link #createMile()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMile(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: mile-scandinavian. @@ -1911,14 +2108,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMileScandinavian(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: mile-scandinavian. * Also see {@link #createMileScandinavian()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMileScandinavian(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: millimeter. @@ -1929,14 +2124,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMillimeter(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: millimeter. * Also see {@link #createMillimeter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMillimeter(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: nanometer. @@ -1947,14 +2140,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createNanometer(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: nanometer. * Also see {@link #createNanometer()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getNanometer(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: nautical-mile. @@ -1965,14 +2156,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createNauticalMile(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: nautical-mile. * Also see {@link #createNauticalMile()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getNauticalMile(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: parsec. @@ -1983,14 +2172,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createParsec(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: parsec. * Also see {@link #createParsec()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getParsec(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: picometer. @@ -2001,14 +2188,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createPicometer(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: picometer. * Also see {@link #createPicometer()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getPicometer(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: point. @@ -2019,32 +2204,28 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createPoint(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: point. * Also see {@link #createPoint()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getPoint(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of length: solar-radius. * Caller owns returned value and must free it. * Also see {@link #getSolarRadius()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createSolarRadius(UErrorCode &status); /** * Returns by value, unit of length: solar-radius. * Also see {@link #createSolarRadius()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getSolarRadius(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: yard. @@ -2055,14 +2236,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createYard(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: yard. * Also see {@link #createYard()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getYard(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of light: lux. @@ -2073,32 +2252,28 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createLux(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of light: lux. * Also see {@link #createLux()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getLux(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of light: solar-luminosity. * Caller owns returned value and must free it. * Also see {@link #getSolarLuminosity()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createSolarLuminosity(UErrorCode &status); /** * Returns by value, unit of light: solar-luminosity. * Also see {@link #createSolarLuminosity()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getSolarLuminosity(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of mass: carat. @@ -2109,50 +2284,44 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createCarat(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of mass: carat. * Also see {@link #createCarat()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getCarat(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of mass: dalton. * Caller owns returned value and must free it. * Also see {@link #getDalton()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createDalton(UErrorCode &status); /** * Returns by value, unit of mass: dalton. * Also see {@link #createDalton()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getDalton(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of mass: earth-mass. * Caller owns returned value and must free it. * Also see {@link #getEarthMass()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createEarthMass(UErrorCode &status); /** * Returns by value, unit of mass: earth-mass. * Also see {@link #createEarthMass()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getEarthMass(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of mass: gram. @@ -2163,14 +2332,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createGram(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of mass: gram. * Also see {@link #createGram()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getGram(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of mass: kilogram. @@ -2181,14 +2348,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createKilogram(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of mass: kilogram. * Also see {@link #createKilogram()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getKilogram(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of mass: metric-ton. @@ -2199,14 +2364,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMetricTon(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of mass: metric-ton. * Also see {@link #createMetricTon()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMetricTon(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of mass: microgram. @@ -2217,14 +2380,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMicrogram(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of mass: microgram. * Also see {@link #createMicrogram()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMicrogram(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of mass: milligram. @@ -2235,14 +2396,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMilligram(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of mass: milligram. * Also see {@link #createMilligram()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMilligram(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of mass: ounce. @@ -2253,14 +2412,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createOunce(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of mass: ounce. * Also see {@link #createOunce()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getOunce(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of mass: ounce-troy. @@ -2271,14 +2428,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createOunceTroy(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of mass: ounce-troy. * Also see {@link #createOunceTroy()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getOunceTroy(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of mass: pound. @@ -2289,32 +2444,28 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createPound(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of mass: pound. * Also see {@link #createPound()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getPound(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of mass: solar-mass. * Caller owns returned value and must free it. * Also see {@link #getSolarMass()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createSolarMass(UErrorCode &status); /** * Returns by value, unit of mass: solar-mass. * Also see {@link #createSolarMass()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getSolarMass(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of mass: stone. @@ -2325,14 +2476,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createStone(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of mass: stone. * Also see {@link #createStone()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getStone(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of mass: ton. @@ -2343,14 +2492,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createTon(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of mass: ton. * Also see {@link #createTon()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getTon(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of power: gigawatt. @@ -2361,14 +2508,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createGigawatt(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of power: gigawatt. * Also see {@link #createGigawatt()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getGigawatt(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of power: horsepower. @@ -2379,14 +2524,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createHorsepower(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of power: horsepower. * Also see {@link #createHorsepower()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getHorsepower(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of power: kilowatt. @@ -2397,14 +2540,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createKilowatt(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of power: kilowatt. * Also see {@link #createKilowatt()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getKilowatt(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of power: megawatt. @@ -2415,14 +2556,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMegawatt(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of power: megawatt. * Also see {@link #createMegawatt()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMegawatt(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of power: milliwatt. @@ -2433,14 +2572,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMilliwatt(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of power: milliwatt. * Also see {@link #createMilliwatt()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMilliwatt(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of power: watt. @@ -2451,14 +2588,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createWatt(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of power: watt. * Also see {@link #createWatt()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getWatt(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of pressure: atmosphere. @@ -2469,14 +2604,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createAtmosphere(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of pressure: atmosphere. * Also see {@link #createAtmosphere()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getAtmosphere(); -#endif /* U_HIDE_DRAFT_API */ #ifndef U_HIDE_DRAFT_API /** @@ -2505,17 +2638,15 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createHectopascal(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of pressure: hectopascal. * Also see {@link #createHectopascal()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getHectopascal(); -#endif /* U_HIDE_DRAFT_API */ /** - * Returns by pointer, unit of pressure: inch-hg. + * Returns by pointer, unit of pressure: inch-ofhg. * Caller owns returned value and must free it. * Also see {@link #getInchHg()}. * @param status ICU error code. @@ -2523,50 +2654,44 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createInchHg(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** - * Returns by value, unit of pressure: inch-hg. + * Returns by value, unit of pressure: inch-ofhg. * Also see {@link #createInchHg()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getInchHg(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of pressure: kilopascal. * Caller owns returned value and must free it. * Also see {@link #getKilopascal()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createKilopascal(UErrorCode &status); /** * Returns by value, unit of pressure: kilopascal. * Also see {@link #createKilopascal()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getKilopascal(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of pressure: megapascal. * Caller owns returned value and must free it. * Also see {@link #getMegapascal()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createMegapascal(UErrorCode &status); /** * Returns by value, unit of pressure: megapascal. * Also see {@link #createMegapascal()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMegapascal(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of pressure: millibar. @@ -2577,17 +2702,15 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMillibar(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of pressure: millibar. * Also see {@link #createMillibar()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMillibar(); -#endif /* U_HIDE_DRAFT_API */ /** - * Returns by pointer, unit of pressure: millimeter-of-mercury. + * Returns by pointer, unit of pressure: millimeter-ofhg. * Caller owns returned value and must free it. * Also see {@link #getMillimeterOfMercury()}. * @param status ICU error code. @@ -2595,14 +2718,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMillimeterOfMercury(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** - * Returns by value, unit of pressure: millimeter-of-mercury. + * Returns by value, unit of pressure: millimeter-ofhg. * Also see {@link #createMillimeterOfMercury()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMillimeterOfMercury(); -#endif /* U_HIDE_DRAFT_API */ #ifndef U_HIDE_DRAFT_API /** @@ -2623,7 +2744,7 @@ class U_I18N_API MeasureUnit: public UObject { #endif /* U_HIDE_DRAFT_API */ /** - * Returns by pointer, unit of pressure: pound-per-square-inch. + * Returns by pointer, unit of pressure: pound-force-per-square-inch. * Caller owns returned value and must free it. * Also see {@link #getPoundPerSquareInch()}. * @param status ICU error code. @@ -2631,14 +2752,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createPoundPerSquareInch(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** - * Returns by value, unit of pressure: pound-per-square-inch. + * Returns by value, unit of pressure: pound-force-per-square-inch. * Also see {@link #createPoundPerSquareInch()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getPoundPerSquareInch(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of speed: kilometer-per-hour. @@ -2649,14 +2768,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createKilometerPerHour(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of speed: kilometer-per-hour. * Also see {@link #createKilometerPerHour()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getKilometerPerHour(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of speed: knot. @@ -2667,14 +2784,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createKnot(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of speed: knot. * Also see {@link #createKnot()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getKnot(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of speed: meter-per-second. @@ -2685,14 +2800,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMeterPerSecond(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of speed: meter-per-second. * Also see {@link #createMeterPerSecond()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMeterPerSecond(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of speed: mile-per-hour. @@ -2703,14 +2816,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMilePerHour(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of speed: mile-per-hour. * Also see {@link #createMilePerHour()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMilePerHour(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of temperature: celsius. @@ -2721,14 +2832,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createCelsius(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of temperature: celsius. * Also see {@link #createCelsius()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getCelsius(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of temperature: fahrenheit. @@ -2739,14 +2848,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createFahrenheit(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of temperature: fahrenheit. * Also see {@link #createFahrenheit()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getFahrenheit(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of temperature: generic. @@ -2757,14 +2864,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createGenericTemperature(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of temperature: generic. * Also see {@link #createGenericTemperature()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getGenericTemperature(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of temperature: kelvin. @@ -2775,50 +2880,44 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createKelvin(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of temperature: kelvin. * Also see {@link #createKelvin()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getKelvin(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of torque: newton-meter. * Caller owns returned value and must free it. * Also see {@link #getNewtonMeter()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createNewtonMeter(UErrorCode &status); /** * Returns by value, unit of torque: newton-meter. * Also see {@link #createNewtonMeter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getNewtonMeter(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** - * Returns by pointer, unit of torque: pound-foot. + * Returns by pointer, unit of torque: pound-force-foot. * Caller owns returned value and must free it. * Also see {@link #getPoundFoot()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createPoundFoot(UErrorCode &status); /** - * Returns by value, unit of torque: pound-foot. + * Returns by value, unit of torque: pound-force-foot. * Also see {@link #createPoundFoot()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getPoundFoot(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: acre-foot. @@ -2829,32 +2928,28 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createAcreFoot(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: acre-foot. * Also see {@link #createAcreFoot()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getAcreFoot(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of volume: barrel. * Caller owns returned value and must free it. * Also see {@link #getBarrel()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createBarrel(UErrorCode &status); /** * Returns by value, unit of volume: barrel. * Also see {@link #createBarrel()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getBarrel(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: bushel. @@ -2865,14 +2960,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createBushel(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: bushel. * Also see {@link #createBushel()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getBushel(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: centiliter. @@ -2883,14 +2976,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createCentiliter(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: centiliter. * Also see {@link #createCentiliter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getCentiliter(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: cubic-centimeter. @@ -2901,14 +2992,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createCubicCentimeter(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: cubic-centimeter. * Also see {@link #createCubicCentimeter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getCubicCentimeter(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: cubic-foot. @@ -2919,14 +3008,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createCubicFoot(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: cubic-foot. * Also see {@link #createCubicFoot()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getCubicFoot(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: cubic-inch. @@ -2937,14 +3024,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createCubicInch(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: cubic-inch. * Also see {@link #createCubicInch()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getCubicInch(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: cubic-kilometer. @@ -2955,14 +3040,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createCubicKilometer(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: cubic-kilometer. * Also see {@link #createCubicKilometer()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getCubicKilometer(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: cubic-meter. @@ -2973,14 +3056,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createCubicMeter(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: cubic-meter. * Also see {@link #createCubicMeter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getCubicMeter(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: cubic-mile. @@ -2991,14 +3072,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createCubicMile(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: cubic-mile. * Also see {@link #createCubicMile()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getCubicMile(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: cubic-yard. @@ -3009,14 +3088,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createCubicYard(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: cubic-yard. * Also see {@link #createCubicYard()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getCubicYard(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: cup. @@ -3027,14 +3104,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createCup(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: cup. * Also see {@link #createCup()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getCup(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: cup-metric. @@ -3045,14 +3120,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createCupMetric(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: cup-metric. * Also see {@link #createCupMetric()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getCupMetric(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: deciliter. @@ -3063,14 +3136,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createDeciliter(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: deciliter. * Also see {@link #createDeciliter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getDeciliter(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: fluid-ounce. @@ -3081,32 +3152,28 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createFluidOunce(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: fluid-ounce. * Also see {@link #createFluidOunce()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getFluidOunce(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of volume: fluid-ounce-imperial. * Caller owns returned value and must free it. * Also see {@link #getFluidOunceImperial()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createFluidOunceImperial(UErrorCode &status); /** * Returns by value, unit of volume: fluid-ounce-imperial. * Also see {@link #createFluidOunceImperial()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getFluidOunceImperial(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: gallon. @@ -3117,14 +3184,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createGallon(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: gallon. * Also see {@link #createGallon()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getGallon(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: gallon-imperial. @@ -3135,14 +3200,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createGallonImperial(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: gallon-imperial. * Also see {@link #createGallonImperial()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getGallonImperial(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: hectoliter. @@ -3153,14 +3216,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createHectoliter(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: hectoliter. * Also see {@link #createHectoliter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getHectoliter(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: liter. @@ -3171,14 +3232,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createLiter(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: liter. * Also see {@link #createLiter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getLiter(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: megaliter. @@ -3189,14 +3248,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMegaliter(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: megaliter. * Also see {@link #createMegaliter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMegaliter(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: milliliter. @@ -3207,14 +3264,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMilliliter(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: milliliter. * Also see {@link #createMilliliter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMilliliter(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: pint. @@ -3225,14 +3280,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createPint(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: pint. * Also see {@link #createPint()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getPint(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: pint-metric. @@ -3243,14 +3296,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createPintMetric(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: pint-metric. * Also see {@link #createPintMetric()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getPintMetric(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: quart. @@ -3261,14 +3312,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createQuart(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: quart. * Also see {@link #createQuart()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getQuart(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: tablespoon. @@ -3279,14 +3328,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createTablespoon(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: tablespoon. * Also see {@link #createTablespoon()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getTablespoon(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: teaspoon. @@ -3297,14 +3344,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createTeaspoon(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: teaspoon. * Also see {@link #createTeaspoon()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getTeaspoon(); -#endif /* U_HIDE_DRAFT_API */ // End generated createXXX methods @@ -3322,7 +3367,7 @@ class U_I18N_API MeasureUnit: public UObject { * For ICU use only. * @internal */ - void initCurrency(const char *isoCurrency); + void initCurrency(StringPiece isoCurrency); /** * For ICU use only. @@ -3333,16 +3378,34 @@ class U_I18N_API MeasureUnit: public UObject { #endif /* U_HIDE_INTERNAL_API */ private: - int32_t fTypeId; - int32_t fSubTypeId; - char fCurrency[4]; - MeasureUnit(int32_t typeId, int32_t subTypeId) : fTypeId(typeId), fSubTypeId(subTypeId) { - fCurrency[0] = 0; - } + // Used by new draft APIs in ICU 67. If non-null, fImpl is owned by the + // MeasureUnit. + MeasureUnitImpl* fImpl; + + // An index into a static string list in measunit.cpp. If set to -1, fImpl + // is in use instead of fTypeId and fSubTypeId. + int16_t fSubTypeId; + // An index into a static string list in measunit.cpp. If set to -1, fImpl + // is in use instead of fTypeId and fSubTypeId. + int8_t fTypeId; + + MeasureUnit(int32_t typeId, int32_t subTypeId); + MeasureUnit(MeasureUnitImpl&& impl); void setTo(int32_t typeId, int32_t subTypeId); int32_t getOffset() const; static MeasureUnit *create(int typeId, int subTypeId, UErrorCode &status); + + /** + * Sets output's typeId and subTypeId according to subType, if subType is a + * valid/known identifier. + * + * @return Whether subType is known to ICU. If false, output was not + * modified. + */ + static bool findBySubType(StringPiece subType, MeasureUnit* output); + + friend struct MeasureUnitImpl; }; U_NAMESPACE_END diff --git a/deps/icu-small/source/i18n/unicode/numberformatter.h b/deps/icu-small/source/i18n/unicode/numberformatter.h index 42d4687ed3feb3..615cf49f7b7539 100644 --- a/deps/icu-small/source/i18n/unicode/numberformatter.h +++ b/deps/icu-small/source/i18n/unicode/numberformatter.h @@ -155,6 +155,8 @@ class DecNum; class NumberRangeFormatterImpl; struct RangeMacroProps; struct UFormattedNumberImpl; +class MutablePatternModifier; +class ImmutablePatternModifier; /** * Used for NumberRangeFormatter and implemented in numrange_fluent.cpp. @@ -980,9 +982,13 @@ class U_I18N_API IntegerWidth : public UMemory { friend struct impl::MacroProps; friend struct impl::MicroProps; - // To allow NumberFormatterImpl to access isBogus() and perform other operations: + // To allow NumberFormatterImpl to access isBogus(): friend class impl::NumberFormatterImpl; + // To allow the use of this class when formatting: + friend class impl::MutablePatternModifier; + friend class impl::ImmutablePatternModifier; + // So that NumberPropertyMapper can create instances friend class impl::NumberPropertyMapper; @@ -1409,9 +1415,6 @@ struct U_I18N_API MacroProps : public UMemory { /** @internal */ const PluralRules* rules = nullptr; // no ownership - /** @internal */ - const CurrencySymbols* currencySymbols = nullptr; // no ownership - /** @internal */ int32_t threshold = kInternalDefaultThreshold; @@ -1433,6 +1436,16 @@ struct U_I18N_API MacroProps : public UMemory { } // namespace impl +#if (U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN) && defined(_MSC_VER) +// Ignore MSVC warning 4661. This is generated for NumberFormatterSettings<>::toSkeleton() as this method +// is defined elsewhere (in number_skeletons.cpp). The compiler is warning that the explicit template instantiation +// inside this single translation unit (CPP file) is incomplete, and thus it isn't sure if the template class is +// fully defined. However, since each translation unit explicitly instantiates all the necessary template classes, +// they will all be passed to the linker, and the linker will still find and export all the class members. +#pragma warning(push) +#pragma warning(disable: 4661) +#endif + /** * An abstract base class for specifying settings related to number formatting. This class is implemented by * {@link UnlocalizedNumberFormatter} and {@link LocalizedNumberFormatter}. This class is not intended for @@ -2082,7 +2095,6 @@ class U_I18N_API NumberFormatterSettings { */ UnicodeString toSkeleton(UErrorCode& status) const; -#ifndef U_HIDE_DRAFT_API /** * Returns the current (Un)LocalizedNumberFormatter as a LocalPointer * wrapping a heap-allocated copy of the current object. @@ -2092,7 +2104,7 @@ class U_I18N_API NumberFormatterSettings { * * @return A wrapped (Un)LocalizedNumberFormatter pointer, or a wrapped * nullptr on failure. - * @draft ICU 64 + * @stable ICU 64 */ LocalPointer clone() const &; @@ -2101,10 +2113,9 @@ class U_I18N_API NumberFormatterSettings { * * @return A wrapped (Un)LocalizedNumberFormatter pointer, or a wrapped * nullptr on failure. - * @draft ICU 64 + * @stable ICU 64 */ LocalPointer clone() &&; -#endif /* U_HIDE_DRAFT_API */ /** * Sets the UErrorCode if an error occurred in the fluent chain. @@ -2399,6 +2410,11 @@ class U_I18N_API LocalizedNumberFormatter friend class UnlocalizedNumberFormatter; }; +#if (U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN) && defined(_MSC_VER) +// Warning 4661. +#pragma warning(pop) +#endif + /** * The result of a number formatting operation. This class allows the result to be exported in several data types, * including a UnicodeString and a FieldPositionIterator. @@ -2410,15 +2426,12 @@ class U_I18N_API LocalizedNumberFormatter class U_I18N_API FormattedNumber : public UMemory, public FormattedValue { public: - // Default constructor cannot have #ifndef U_HIDE_DRAFT_API -#ifndef U_FORCE_HIDE_DRAFT_API /** * Default constructor; makes an empty FormattedNumber. - * @draft ICU 64 + * @stable ICU 64 */ FormattedNumber() : fData(nullptr), fErrorCode(U_INVALID_STATE_ERROR) {} -#endif // U_FORCE_HIDE_DRAFT_API /** * Move constructor: Leaves the source FormattedNumber in an undefined state. @@ -2472,60 +2485,6 @@ class U_I18N_API FormattedNumber : public UMemory, public FormattedValue { /** @copydoc FormattedValue::nextPosition() */ UBool nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const U_OVERRIDE; -#ifndef U_HIDE_DRAFT_API - /** - * Determines the start (inclusive) and end (exclusive) indices of the next occurrence of the given - * field in the output string. This allows you to determine the locations of, for example, - * the integer part, fraction part, or symbols. - * - * This is a simpler but less powerful alternative to {@link #nextPosition}. - * - * If a field occurs just once, calling this method will find that occurrence and return it. If a - * field occurs multiple times, this method may be called repeatedly with the following pattern: - * - *
-     * FieldPosition fpos(UNUM_GROUPING_SEPARATOR_FIELD);
-     * while (formattedNumber.nextFieldPosition(fpos, status)) {
-     *   // do something with fpos.
-     * }
-     * 
- * - * This method is useful if you know which field to query. If you want all available field position - * information, use {@link #nextPosition} or {@link #getAllFieldPositions}. - * - * @param fieldPosition - * Input+output variable. On input, the "field" property determines which field to look - * up, and the "beginIndex" and "endIndex" properties determine where to begin the search. - * On output, the "beginIndex" is set to the beginning of the first occurrence of the - * field with either begin or end indices after the input indices; "endIndex" is set to - * the end of that occurrence of the field (exclusive index). If a field position is not - * found, the method returns FALSE and the FieldPosition may or may not be changed. - * @param status - * Set if an error occurs while populating the FieldPosition. - * @return TRUE if a new occurrence of the field was found; FALSE otherwise. - * @draft ICU 62 - * @see UNumberFormatFields - */ - UBool nextFieldPosition(FieldPosition& fieldPosition, UErrorCode& status) const; - - /** - * Export the formatted number to a FieldPositionIterator. This allows you to determine which characters in - * the output string correspond to which fields, such as the integer part, fraction part, and sign. - * - * This is an alternative to the more powerful #nextPosition() API. - * - * If information on only one field is needed, use #nextPosition() or #nextFieldPosition() instead. - * - * @param iterator - * The FieldPositionIterator to populate with all of the fields present in the formatted number. - * @param status - * Set if an error occurs while populating the FieldPositionIterator. - * @draft ICU 62 - * @see UNumberFormatFields - */ - void getAllFieldPositions(FieldPositionIterator &iterator, UErrorCode &status) const; -#endif /* U_HIDE_DRAFT_API */ - #ifndef U_HIDE_DRAFT_API /** * Export the formatted number as a "numeric string" conforming to the @@ -2646,7 +2605,6 @@ class U_I18N_API NumberFormatter final { */ static UnlocalizedNumberFormatter forSkeleton(const UnicodeString& skeleton, UErrorCode& status); -#ifndef U_HIDE_DRAFT_API /** * Call this method at the beginning of a NumberFormatter fluent chain to create an instance based * on a given number skeleton string. @@ -2662,11 +2620,10 @@ class U_I18N_API NumberFormatter final { * @param status * Set to U_NUMBER_SKELETON_SYNTAX_ERROR if the skeleton was invalid. * @return An UnlocalizedNumberFormatter, to be used for chaining. - * @draft ICU 64 + * @stable ICU 64 */ static UnlocalizedNumberFormatter forSkeleton(const UnicodeString& skeleton, UParseError& perror, UErrorCode& status); -#endif /** * Use factory methods instead of the constructor to create a NumberFormatter. diff --git a/deps/icu-small/source/i18n/unicode/numberrangeformatter.h b/deps/icu-small/source/i18n/unicode/numberrangeformatter.h index e3a72aa8b21257..59f14d8be53189 100644 --- a/deps/icu-small/source/i18n/unicode/numberrangeformatter.h +++ b/deps/icu-small/source/i18n/unicode/numberrangeformatter.h @@ -449,7 +449,6 @@ class U_I18N_API NumberRangeFormatterSettings { */ Derived identityFallback(UNumberRangeIdentityFallback identityFallback) &&; -#ifndef U_HIDE_DRAFT_API /** * Returns the current (Un)LocalizedNumberRangeFormatter as a LocalPointer * wrapping a heap-allocated copy of the current object. @@ -459,7 +458,7 @@ class U_I18N_API NumberRangeFormatterSettings { * * @return A wrapped (Un)LocalizedNumberRangeFormatter pointer, or a wrapped * nullptr on failure. - * @draft ICU 64 + * @stable ICU 64 */ LocalPointer clone() const &; @@ -468,10 +467,9 @@ class U_I18N_API NumberRangeFormatterSettings { * * @return A wrapped (Un)LocalizedNumberRangeFormatter pointer, or a wrapped * nullptr on failure. - * @draft ICU 64 + * @stable ICU 64 */ LocalPointer clone() &&; -#endif /* U_HIDE_DRAFT_API */ /** * Sets the UErrorCode if an error occurred in the fluent chain. @@ -728,52 +726,6 @@ class U_I18N_API FormattedNumberRange : public UMemory, public FormattedValue { UBool nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const U_OVERRIDE; #ifndef U_HIDE_DRAFT_API - /** - * Determines the start (inclusive) and end (exclusive) indices of the next occurrence of the given - * field in the output string. This allows you to determine the locations of, for example, - * the integer part, fraction part, or symbols. - * - * If both sides of the range have the same field, the field will occur twice, once before the - * range separator and once after the range separator, if applicable. - * - * If a field occurs just once, calling this method will find that occurrence and return it. If a - * field occurs multiple times, this method may be called repeatedly with the following pattern: - * - *
-     * FieldPosition fpos(UNUM_INTEGER_FIELD);
-     * while (formattedNumberRange.nextFieldPosition(fpos, status)) {
-     *   // do something with fpos.
-     * }
-     * 
- * - * This method is useful if you know which field to query. If you want all available field position - * information, use #getAllFieldPositions(). - * - * @param fieldPosition - * Input+output variable. See {@link FormattedNumber#nextFieldPosition}. - * @param status - * Set if an error occurs while populating the FieldPosition. - * @return TRUE if a new occurrence of the field was found; FALSE otherwise. - * @draft ICU 63 - * @see UNumberFormatFields - */ - UBool nextFieldPosition(FieldPosition& fieldPosition, UErrorCode& status) const; - - /** - * Export the formatted number range to a FieldPositionIterator. This allows you to determine which characters in - * the output string correspond to which fields, such as the integer part, fraction part, and sign. - * - * If information on only one field is needed, use #nextFieldPosition() instead. - * - * @param iterator - * The FieldPositionIterator to populate with all of the fields present in the formatted number. - * @param status - * Set if an error occurs while populating the FieldPositionIterator. - * @draft ICU 63 - * @see UNumberFormatFields - */ - void getAllFieldPositions(FieldPositionIterator &iterator, UErrorCode &status) const; - /** * Export the first formatted number as a decimal number. This endpoint * is useful for obtaining the exact number being printed after scaling diff --git a/deps/icu-small/source/i18n/unicode/numfmt.h b/deps/icu-small/source/i18n/unicode/numfmt.h index fbd4fb4e5655b3..a882b6d2e5667d 100644 --- a/deps/icu-small/source/i18n/unicode/numfmt.h +++ b/deps/icu-small/source/i18n/unicode/numfmt.h @@ -239,12 +239,10 @@ class U_I18N_API NumberFormat : public Format { kPermillField = UNUM_PERMILL_FIELD, /** @stable ICU 2.0 */ kSignField = UNUM_SIGN_FIELD, -#ifndef U_HIDE_DRAFT_API - /** @draft ICU 64 */ + /** @stable ICU 64 */ kMeasureUnitField = UNUM_MEASURE_UNIT_FIELD, - /** @draft ICU 64 */ + /** @stable ICU 64 */ kCompactField = UNUM_COMPACT_FIELD, -#endif // U_HIDE_DRAFT_API /** * These constants are provided for backwards compatibility only. diff --git a/deps/icu-small/source/i18n/unicode/numsys.h b/deps/icu-small/source/i18n/unicode/numsys.h index 4fb7f044eddb76..88c172bd422a51 100644 --- a/deps/icu-small/source/i18n/unicode/numsys.h +++ b/deps/icu-small/source/i18n/unicode/numsys.h @@ -73,6 +73,12 @@ class U_I18N_API NumberingSystem : public UObject { */ NumberingSystem(const NumberingSystem& other); + /** + * Copy assignment. + * @stable ICU 4.2 + */ + NumberingSystem& operator=(const NumberingSystem& other) = default; + /** * Destructor. * @stable ICU 4.2 diff --git a/deps/icu-small/source/i18n/unicode/plurrule.h b/deps/icu-small/source/i18n/unicode/plurrule.h index a1553567caf8f5..408efbcc4a84f8 100644 --- a/deps/icu-small/source/i18n/unicode/plurrule.h +++ b/deps/icu-small/source/i18n/unicode/plurrule.h @@ -350,7 +350,6 @@ class U_I18N_API PluralRules : public UObject { */ UnicodeString select(double number) const; -#ifndef U_HIDE_DRAFT_API /** * Given a formatted number, returns the keyword of the first rule * that applies to the number. This function can be used with @@ -364,10 +363,9 @@ class U_I18N_API PluralRules : public UObject { * @param status Set if an error occurs while selecting plural keyword. * This could happen if the FormattedNumber is invalid. * @return The keyword of the selected rule. - * @draft ICU 64 + * @stable ICU 64 */ UnicodeString select(const number::FormattedNumber& number, UErrorCode& status) const; -#endif /* U_HIDE_DRAFT_API */ #ifndef U_HIDE_INTERNAL_API /** diff --git a/deps/icu-small/source/i18n/unicode/regex.h b/deps/icu-small/source/i18n/unicode/regex.h index a003e337856af9..2f8d31d97f012f 100644 --- a/deps/icu-small/source/i18n/unicode/regex.h +++ b/deps/icu-small/source/i18n/unicode/regex.h @@ -66,7 +66,7 @@ class RegexCImpl; class RegexMatcher; class RegexPattern; struct REStackFrame; -class RuleBasedBreakIterator; +class BreakIterator; class UnicodeSet; class UVector; class UVector32; @@ -612,12 +612,6 @@ class U_I18N_API RegexPattern U_FINAL : public UObject { UVector32 *fGroupMap; // Map from capture group number to position of // the group's variables in the matcher stack frame. - UnicodeSet **fStaticSets; // Ptr to static (shared) sets for predefined - // regex character classes, e.g. Word. - - Regex8BitSet *fStaticSets8; // Ptr to the static (shared) latin-1 only - // sets for predefined regex classes. - int32_t fStartType; // Info on how a match must start. int32_t fInitialStringIdx; // int32_t fInitialStringLen; @@ -1780,7 +1774,9 @@ class U_I18N_API RegexMatcher U_FINAL : public UObject { void MatchAt(int64_t startIdx, UBool toEnd, UErrorCode &status); inline void backTrack(int64_t &inputIdx, int32_t &patIdx); UBool isWordBoundary(int64_t pos); // perform Perl-like \b test - UBool isUWordBoundary(int64_t pos); // perform RBBI based \b test + UBool isUWordBoundary(int64_t pos, UErrorCode &status); // perform RBBI based \b test + // Find a grapheme cluster boundary using a break iterator. For handling \X in regexes. + int64_t followingGCBoundary(int64_t pos, UErrorCode &status); REStackFrame *resetStack(); inline REStackFrame *StateSave(REStackFrame *fp, int64_t savePatIdx, UErrorCode &status); void IncrementTime(UErrorCode &status); @@ -1874,7 +1870,8 @@ class U_I18N_API RegexMatcher U_FINAL : public UObject { UErrorCode fDeferredStatus; // Save error state that cannot be immediately // reported, or that permanently disables this matcher. - RuleBasedBreakIterator *fWordBreakItr; + BreakIterator *fWordBreakItr; + BreakIterator *fGCBreakItr; }; U_NAMESPACE_END diff --git a/deps/icu-small/source/i18n/unicode/reldatefmt.h b/deps/icu-small/source/i18n/unicode/reldatefmt.h index fb691a545105b6..a991bc7986b32d 100644 --- a/deps/icu-small/source/i18n/unicode/reldatefmt.h +++ b/deps/icu-small/source/i18n/unicode/reldatefmt.h @@ -264,7 +264,6 @@ class UnicodeString; class FormattedRelativeDateTime; class FormattedRelativeDateTimeData; -#ifndef U_HIDE_DRAFT_API /** * An immutable class containing the result of a relative datetime formatting operation. * @@ -272,25 +271,25 @@ class FormattedRelativeDateTimeData; * * Not intended for public subclassing. * - * @draft ICU 64 + * @stable ICU 64 */ class U_I18N_API FormattedRelativeDateTime : public UMemory, public FormattedValue { public: /** * Default constructor; makes an empty FormattedRelativeDateTime. - * @draft ICU 64 + * @stable ICU 64 */ FormattedRelativeDateTime() : fData(nullptr), fErrorCode(U_INVALID_STATE_ERROR) {} /** * Move constructor: Leaves the source FormattedRelativeDateTime in an undefined state. - * @draft ICU 64 + * @stable ICU 64 */ FormattedRelativeDateTime(FormattedRelativeDateTime&& src) U_NOEXCEPT; /** * Destruct an instance of FormattedRelativeDateTime. - * @draft ICU 64 + * @stable ICU 64 */ virtual ~FormattedRelativeDateTime() U_OVERRIDE; @@ -302,7 +301,7 @@ class U_I18N_API FormattedRelativeDateTime : public UMemory, public FormattedVal /** * Move assignment: Leaves the source FormattedRelativeDateTime in an undefined state. - * @draft ICU 64 + * @stable ICU 64 */ FormattedRelativeDateTime& operator=(FormattedRelativeDateTime&& src) U_NOEXCEPT; @@ -327,7 +326,6 @@ class U_I18N_API FormattedRelativeDateTime : public UMemory, public FormattedVal : fData(nullptr), fErrorCode(errorCode) {} friend class RelativeDateTimeFormatter; }; -#endif /* U_HIDE_DRAFT_API */ /** * Formats simple relative dates. There are two types of relative dates that @@ -492,7 +490,6 @@ class U_I18N_API RelativeDateTimeFormatter : public UObject { UnicodeString& appendTo, UErrorCode& status) const; -#ifndef U_HIDE_DRAFT_API /** * Formats a relative date with a quantity such as "in 5 days" or * "3 months ago" @@ -508,14 +505,13 @@ class U_I18N_API RelativeDateTimeFormatter : public UObject { * @param unit the unit e.g day? month? year? * @param status ICU error code returned here. * @return The formatted relative datetime - * @draft ICU 64 + * @stable ICU 64 */ FormattedRelativeDateTime formatToValue( double quantity, UDateDirection direction, UDateRelativeUnit unit, UErrorCode& status) const; -#endif /* U_HIDE_DRAFT_API */ /** * Formats a relative date without a quantity. @@ -539,7 +535,6 @@ class U_I18N_API RelativeDateTimeFormatter : public UObject { UnicodeString& appendTo, UErrorCode& status) const; -#ifndef U_HIDE_DRAFT_API /** * Formats a relative date without a quantity. * @@ -553,13 +548,12 @@ class U_I18N_API RelativeDateTimeFormatter : public UObject { * @param unit e.g SATURDAY, DAY, MONTH * @param status ICU error code returned here. * @return The formatted relative datetime - * @draft ICU 64 + * @stable ICU 64 */ FormattedRelativeDateTime formatToValue( UDateDirection direction, UDateAbsoluteUnit unit, UErrorCode& status) const; -#endif /* U_HIDE_DRAFT_API */ /** * Format a combination of URelativeDateTimeUnit and numeric offset @@ -587,7 +581,6 @@ class U_I18N_API RelativeDateTimeFormatter : public UObject { UnicodeString& appendTo, UErrorCode& status) const; -#ifndef U_HIDE_DRAFT_API /** * Format a combination of URelativeDateTimeUnit and numeric offset * using a numeric style, e.g. "1 week ago", "in 1 week", @@ -604,13 +597,12 @@ class U_I18N_API RelativeDateTimeFormatter : public UObject { * UDAT_REL_UNIT_FRIDAY. * @param status ICU error code returned here. * @return The formatted relative datetime - * @draft ICU 64 + * @stable ICU 64 */ FormattedRelativeDateTime formatNumericToValue( double offset, URelativeDateTimeUnit unit, UErrorCode& status) const; -#endif /* U_HIDE_DRAFT_API */ /** * Format a combination of URelativeDateTimeUnit and numeric offset @@ -638,7 +630,6 @@ class U_I18N_API RelativeDateTimeFormatter : public UObject { UnicodeString& appendTo, UErrorCode& status) const; -#ifndef U_HIDE_DRAFT_API /** * Format a combination of URelativeDateTimeUnit and numeric offset * using a text style if possible, e.g. "last week", "this week", @@ -655,13 +646,12 @@ class U_I18N_API RelativeDateTimeFormatter : public UObject { * UDAT_REL_UNIT_FRIDAY. * @param status ICU error code returned here. * @return The formatted relative datetime - * @draft ICU 64 + * @stable ICU 64 */ FormattedRelativeDateTime formatToValue( double offset, URelativeDateTimeUnit unit, UErrorCode& status) const; -#endif /* U_HIDE_DRAFT_API */ /** * Combines a relative date string and a time string in this object's @@ -724,13 +714,11 @@ class U_I18N_API RelativeDateTimeFormatter : public UObject { UErrorCode& status, Args... args) const; -#ifndef U_HIDE_DRAFT_API // for FormattedRelativeDateTime template FormattedRelativeDateTime doFormatToValue( F callback, UErrorCode& status, Args... args) const; -#endif // U_HIDE_DRAFT_API void formatImpl( double quantity, diff --git a/deps/icu-small/source/i18n/unicode/selfmt.h b/deps/icu-small/source/i18n/unicode/selfmt.h old mode 100755 new mode 100644 diff --git a/deps/icu-small/source/i18n/unicode/smpdtfmt.h b/deps/icu-small/source/i18n/unicode/smpdtfmt.h index 79fa817d5afb89..b4b0e5fb390801 100644 --- a/deps/icu-small/source/i18n/unicode/smpdtfmt.h +++ b/deps/icu-small/source/i18n/unicode/smpdtfmt.h @@ -1274,6 +1274,7 @@ class U_I18N_API SimpleDateFormat: public DateFormat { int32_t count, UDisplayContext capitalizationContext, int32_t fieldNum, + char16_t fieldToOutput, FieldPositionHandler& handler, Calendar& cal, UErrorCode& status) const; // in case of illegal argument diff --git a/deps/icu-small/source/i18n/unicode/udat.h b/deps/icu-small/source/i18n/unicode/udat.h index bdbd080c005821..cf7a165e70ab4f 100644 --- a/deps/icu-small/source/i18n/unicode/udat.h +++ b/deps/icu-small/source/i18n/unicode/udat.h @@ -958,7 +958,37 @@ udat_getBooleanAttribute(const UDateFormat* fmt, UDateFormatBooleanAttribute att U_CAPI void U_EXPORT2 udat_setBooleanAttribute(UDateFormat *fmt, UDateFormatBooleanAttribute attr, UBool newValue, UErrorCode* status); +#ifndef U_HIDE_DRAFT_API +/** + * Hour Cycle. + * @draft ICU 67 + */ +typedef enum UDateFormatHourCycle { + /** + * Hour in am/pm (0~11) + * @draft ICU 67 + */ + UDAT_HOUR_CYCLE_11, + + /** + * Hour in am/pm (1~12) + * @draft ICU 67 + */ + UDAT_HOUR_CYCLE_12, + + /** + * Hour in day (0~23) + * @draft ICU 67 + */ + UDAT_HOUR_CYCLE_23, + /** + * Hour in day (1~24) + * @draft ICU 67 + */ + UDAT_HOUR_CYCLE_24 +} UDateFormatHourCycle; +#endif /* U_HIDE_DRAFT_API */ #if U_SHOW_CPLUSPLUS_API diff --git a/deps/icu-small/source/i18n/unicode/udateintervalformat.h b/deps/icu-small/source/i18n/unicode/udateintervalformat.h index 112f81b31e976b..6235ab710622ce 100644 --- a/deps/icu-small/source/i18n/unicode/udateintervalformat.h +++ b/deps/icu-small/source/i18n/unicode/udateintervalformat.h @@ -14,6 +14,7 @@ #if !UCONFIG_NO_FORMATTING +#include "unicode/ucal.h" #include "unicode/umisc.h" #include "unicode/localpointer.h" #include "unicode/uformattedvalue.h" @@ -82,14 +83,12 @@ struct UDateIntervalFormat; typedef struct UDateIntervalFormat UDateIntervalFormat; /**< C typedef for struct UDateIntervalFormat. @stable ICU 4.8 */ -#ifndef U_HIDE_DRAFT_API struct UFormattedDateInterval; /** * Opaque struct to contain the results of a UDateIntervalFormat operation. - * @draft ICU 64 + * @stable ICU 64 */ typedef struct UFormattedDateInterval UFormattedDateInterval; -#endif /* U_HIDE_DRAFT_API */ /** * Open a new UDateIntervalFormat object using the predefined rules for a @@ -132,8 +131,6 @@ udtitvfmt_open(const char* locale, U_STABLE void U_EXPORT2 udtitvfmt_close(UDateIntervalFormat *formatter); - -#ifndef U_HIDE_DRAFT_API /** * Creates an object to hold the result of a UDateIntervalFormat * operation. The object can be used repeatedly; it is cleared whenever @@ -141,7 +138,7 @@ udtitvfmt_close(UDateIntervalFormat *formatter); * * @param ec Set if an error occurs. * @return A pointer needing ownership. - * @draft ICU 64 + * @stable ICU 64 */ U_CAPI UFormattedDateInterval* U_EXPORT2 udtitvfmt_openResult(UErrorCode* ec); @@ -166,7 +163,7 @@ udtitvfmt_openResult(UErrorCode* ec); * @param uresult The object containing the formatted string. * @param ec Set if an error occurs. * @return A UFormattedValue owned by the input object. - * @draft ICU 64 + * @stable ICU 64 */ U_CAPI const UFormattedValue* U_EXPORT2 udtitvfmt_resultAsValue(const UFormattedDateInterval* uresult, UErrorCode* ec); @@ -175,11 +172,10 @@ udtitvfmt_resultAsValue(const UFormattedDateInterval* uresult, UErrorCode* ec); * Releases the UFormattedDateInterval created by udtitvfmt_openResult(). * * @param uresult The object to release. - * @draft ICU 64 + * @stable ICU 64 */ U_CAPI void U_EXPORT2 udtitvfmt_closeResult(UFormattedDateInterval* uresult); -#endif /* U_HIDE_DRAFT_API */ #if U_SHOW_CPLUSPLUS_API @@ -197,7 +193,6 @@ U_NAMESPACE_BEGIN */ U_DEFINE_LOCAL_OPEN_POINTER(LocalUDateIntervalFormatPointer, UDateIntervalFormat, udtitvfmt_close); -#ifndef U_HIDE_DRAFT_API /** * \class LocalUFormattedDateIntervalPointer * "Smart pointer" class, closes a UFormattedDateInterval via udtitvfmt_close(). @@ -205,10 +200,9 @@ U_DEFINE_LOCAL_OPEN_POINTER(LocalUDateIntervalFormatPointer, UDateIntervalFormat * * @see LocalPointerBase * @see LocalPointer - * @draft ICU 64 + * @stable ICU 64 */ U_DEFINE_LOCAL_OPEN_POINTER(LocalUFormattedDateIntervalPointer, UFormattedDateInterval, udtitvfmt_closeResult); -#endif /* U_HIDE_DRAFT_API */ U_NAMESPACE_END @@ -260,23 +254,48 @@ udtitvfmt_format(const UDateIntervalFormat* formatter, * UDateIntervalFormat object. * @param formatter * The UDateIntervalFormat object specifying the format conventions. - * @param result - * The UFormattedDateInterval to contain the result of the - * formatting operation. * @param fromDate * The starting point of the range. * @param toDate * The ending point of the range. + * @param result + * The UFormattedDateInterval to contain the result of the + * formatting operation. * @param status * A pointer to a UErrorCode to receive any errors. - * @draft ICU 64 + * @draft ICU 67 */ U_DRAFT void U_EXPORT2 udtitvfmt_formatToResult( const UDateIntervalFormat* formatter, - UFormattedDateInterval* result, UDate fromDate, UDate toDate, + UFormattedDateInterval* result, + UErrorCode* status); + +/** + * Formats a date/time range using the conventions established for the + * UDateIntervalFormat object. + * @param formatter + * The UDateIntervalFormat object specifying the format conventions. + * @param fromCalendar + * The starting point of the range. + * @param toCalendar + * The ending point of the range. + * @param result + * The UFormattedDateInterval to contain the result of the + * formatting operation. + * @param status + * A pointer to a UErrorCode to receive any errors. + * @draft ICU 67 + */ + +U_DRAFT void U_EXPORT2 +udtitvfmt_formatCalendarToResult( + const UDateIntervalFormat* formatter, + UCalendar* fromCalendar, + UCalendar* toCalendar, + UFormattedDateInterval* result, UErrorCode* status); #endif /* U_HIDE_DRAFT_API */ diff --git a/deps/icu-small/source/i18n/unicode/udatpg.h b/deps/icu-small/source/i18n/unicode/udatpg.h index 81956d12705d7d..4ec4a2d05116cb 100644 --- a/deps/icu-small/source/i18n/unicode/udatpg.h +++ b/deps/icu-small/source/i18n/unicode/udatpg.h @@ -20,6 +20,7 @@ #define __UDATPG_H__ #include "unicode/utypes.h" +#include "unicode/udat.h" #include "unicode/uenum.h" #include "unicode/localpointer.h" @@ -651,4 +652,26 @@ udatpg_getPatternForSkeleton(const UDateTimePatternGenerator *dtpg, const UChar *skeleton, int32_t skeletonLength, int32_t *pLength); +#if !UCONFIG_NO_FORMATTING + +#ifndef U_HIDE_DRAFT_API +/** + * Return the default hour cycle for a locale. Uses the locale that the + * UDateTimePatternGenerator was initially created with. + * + * Cannot be used on an empty UDateTimePatternGenerator instance. + * + * @param dtpg a pointer to UDateTimePatternGenerator. + * @param pErrorCode a pointer to the UErrorCode which must not indicate a + * failure before the function call. Set to U_UNSUPPORTED_ERROR + * if used on an empty instance. + * @return the default hour cycle. + * @draft ICU 67 + */ +U_DRAFT UDateFormatHourCycle U_EXPORT2 +udatpg_getDefaultHourCycle(const UDateTimePatternGenerator *dtpg, UErrorCode* pErrorCode); +#endif /* U_HIDE_DRAFT_API */ + +#endif /* #if !UCONFIG_NO_FORMATTING */ + #endif diff --git a/deps/icu-small/source/i18n/unicode/uformattedvalue.h b/deps/icu-small/source/i18n/unicode/uformattedvalue.h index 172558f7fb716a..71a6592e9dd062 100644 --- a/deps/icu-small/source/i18n/unicode/uformattedvalue.h +++ b/deps/icu-small/source/i18n/unicode/uformattedvalue.h @@ -10,8 +10,6 @@ #include "unicode/ufieldpositer.h" -#ifndef U_HIDE_DRAFT_API - /** * \file * \brief C API: Abstract operations for localized strings. @@ -31,41 +29,41 @@ * categories 2^28 and higher or below zero (with the highest bit turned on) * are private-use and will not be used by ICU in the future. * - * @draft ICU 64 + * @stable ICU 64 */ typedef enum UFieldCategory { /** * For an undefined field category. * - * @draft ICU 64 + * @stable ICU 64 */ UFIELD_CATEGORY_UNDEFINED = 0, /** * For fields in UDateFormatField (udat.h), from ICU 3.0. * - * @draft ICU 64 + * @stable ICU 64 */ UFIELD_CATEGORY_DATE, /** * For fields in UNumberFormatFields (unum.h), from ICU 49. * - * @draft ICU 64 + * @stable ICU 64 */ UFIELD_CATEGORY_NUMBER, /** * For fields in UListFormatterField (ulistformatter.h), from ICU 63. * - * @draft ICU 64 + * @stable ICU 64 */ UFIELD_CATEGORY_LIST, /** * For fields in URelativeDateTimeFormatterField (ureldatefmt.h), from ICU 64. * - * @draft ICU 64 + * @stable ICU 64 */ UFIELD_CATEGORY_RELATIVE_DATETIME, @@ -84,14 +82,14 @@ typedef enum UFieldCategory { /** * Category for spans in a list. * - * @draft ICU 64 + * @stable ICU 64 */ UFIELD_CATEGORY_LIST_SPAN = 0x1000 + UFIELD_CATEGORY_LIST, /** * Category for spans in a date interval. * - * @draft ICU 64 + * @stable ICU 64 */ UFIELD_CATEGORY_DATE_INTERVAL_SPAN = 0x1000 + UFIELD_CATEGORY_DATE_INTERVAL, @@ -108,7 +106,7 @@ struct UConstrainedFieldPosition; * 2. It allows you to set constraints to use when iterating over field positions. * 3. It is used for the newer FormattedValue APIs. * - * @draft ICU 64 + * @stable ICU 64 */ typedef struct UConstrainedFieldPosition UConstrainedFieldPosition; @@ -120,9 +118,9 @@ typedef struct UConstrainedFieldPosition UConstrainedFieldPosition; * * @param ec Set if an error occurs. * @return The new object, or NULL if an error occurs. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT UConstrainedFieldPosition* U_EXPORT2 +U_STABLE UConstrainedFieldPosition* U_EXPORT2 ucfpos_open(UErrorCode* ec); @@ -133,9 +131,9 @@ ucfpos_open(UErrorCode* ec); * * @param ucfpos The instance of UConstrainedFieldPosition. * @param ec Set if an error occurs. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT void U_EXPORT2 +U_STABLE void U_EXPORT2 ucfpos_reset( UConstrainedFieldPosition* ucfpos, UErrorCode* ec); @@ -145,9 +143,9 @@ ucfpos_reset( * Destroys a UConstrainedFieldPosition and releases its memory. * * @param ucfpos The instance of UConstrainedFieldPosition. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT void U_EXPORT2 +U_STABLE void U_EXPORT2 ucfpos_close(UConstrainedFieldPosition* ucfpos); @@ -174,9 +172,9 @@ ucfpos_close(UConstrainedFieldPosition* ucfpos); * @param ucfpos The instance of UConstrainedFieldPosition. * @param category The field category to fix when iterating. * @param ec Set if an error occurs. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT void U_EXPORT2 +U_STABLE void U_EXPORT2 ucfpos_constrainCategory( UConstrainedFieldPosition* ucfpos, int32_t category, @@ -207,9 +205,9 @@ ucfpos_constrainCategory( * @param category The field category to fix when iterating. * @param field The field to fix when iterating. * @param ec Set if an error occurs. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT void U_EXPORT2 +U_STABLE void U_EXPORT2 ucfpos_constrainField( UConstrainedFieldPosition* ucfpos, int32_t category, @@ -227,9 +225,9 @@ ucfpos_constrainField( * @param ucfpos The instance of UConstrainedFieldPosition. * @param ec Set if an error occurs. * @return The field category saved in the instance. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT int32_t U_EXPORT2 +U_STABLE int32_t U_EXPORT2 ucfpos_getCategory( const UConstrainedFieldPosition* ucfpos, UErrorCode* ec); @@ -245,9 +243,9 @@ ucfpos_getCategory( * @param ucfpos The instance of UConstrainedFieldPosition. * @param ec Set if an error occurs. * @return The field saved in the instance. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT int32_t U_EXPORT2 +U_STABLE int32_t U_EXPORT2 ucfpos_getField( const UConstrainedFieldPosition* ucfpos, UErrorCode* ec); @@ -262,9 +260,9 @@ ucfpos_getField( * @param pStart Set to the start index saved in the instance. Ignored if nullptr. * @param pLimit Set to the end index saved in the instance. Ignored if nullptr. * @param ec Set if an error occurs. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT void U_EXPORT2 +U_STABLE void U_EXPORT2 ucfpos_getIndexes( const UConstrainedFieldPosition* ucfpos, int32_t* pStart, @@ -282,9 +280,9 @@ ucfpos_getIndexes( * @param ucfpos The instance of UConstrainedFieldPosition. * @param ec Set if an error occurs. * @return The current iteration context from ucfpos_setInt64IterationContext. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT int64_t U_EXPORT2 +U_STABLE int64_t U_EXPORT2 ucfpos_getInt64IterationContext( const UConstrainedFieldPosition* ucfpos, UErrorCode* ec); @@ -298,9 +296,9 @@ ucfpos_getInt64IterationContext( * @param ucfpos The instance of UConstrainedFieldPosition. * @param context The new iteration context. * @param ec Set if an error occurs. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT void U_EXPORT2 +U_STABLE void U_EXPORT2 ucfpos_setInt64IterationContext( UConstrainedFieldPosition* ucfpos, int64_t context, @@ -317,9 +315,9 @@ ucfpos_setInt64IterationContext( * @param category The category to test. * @param field The field to test. * @param ec Set if an error occurs. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT UBool U_EXPORT2 +U_STABLE UBool U_EXPORT2 ucfpos_matchesField( const UConstrainedFieldPosition* ucfpos, int32_t category, @@ -341,9 +339,9 @@ ucfpos_matchesField( * @param start The new inclusive start index. * @param limit The new exclusive end index. * @param ec Set if an error occurs. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT void U_EXPORT2 +U_STABLE void U_EXPORT2 ucfpos_setState( UConstrainedFieldPosition* ucfpos, int32_t category, @@ -358,7 +356,7 @@ struct UFormattedValue; * An abstract formatted value: a string with associated field attributes. * Many formatters format to types compatible with UFormattedValue. * - * @draft ICU 64 + * @stable ICU 64 */ typedef struct UFormattedValue UFormattedValue; @@ -374,9 +372,9 @@ typedef struct UFormattedValue UFormattedValue; * @param pLength Output variable for the length of the string. Ignored if NULL. * @param ec Set if an error occurs. * @return A NUL-terminated char16 string owned by the UFormattedValue. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT const UChar* U_EXPORT2 +U_STABLE const UChar* U_EXPORT2 ufmtval_getString( const UFormattedValue* ufmtval, int32_t* pLength, @@ -404,9 +402,9 @@ ufmtval_getString( * and ucfpos_constrainField. * @param ec Set if an error occurs. * @return TRUE if another position was found; FALSE otherwise. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT UBool U_EXPORT2 +U_STABLE UBool U_EXPORT2 ufmtval_nextPosition( const UFormattedValue* ufmtval, UConstrainedFieldPosition* ucfpos, @@ -426,7 +424,7 @@ U_NAMESPACE_BEGIN * LocalUConstrainedFieldPositionPointer ucfpos(ucfpos_open(ec)); * // no need to explicitly call ucfpos_close() * - * @draft ICU 64 + * @stable ICU 64 */ U_DEFINE_LOCAL_OPEN_POINTER(LocalUConstrainedFieldPositionPointer, UConstrainedFieldPosition, @@ -436,6 +434,5 @@ U_NAMESPACE_END #endif // U_SHOW_CPLUSPLUS_API -#endif /* U_HIDE_DRAFT_API */ #endif /* #if !UCONFIG_NO_FORMATTING */ #endif // __UFORMATTEDVALUE_H__ diff --git a/deps/icu-small/source/i18n/unicode/ulistformatter.h b/deps/icu-small/source/i18n/unicode/ulistformatter.h index 0fbf72c9ff6abb..66cf50190bb0eb 100644 --- a/deps/icu-small/source/i18n/unicode/ulistformatter.h +++ b/deps/icu-small/source/i18n/unicode/ulistformatter.h @@ -34,37 +34,92 @@ struct UListFormatter; typedef struct UListFormatter UListFormatter; /**< C typedef for struct UListFormatter. @stable ICU 55 */ -#ifndef U_HIDE_DRAFT_API struct UFormattedList; /** * Opaque struct to contain the results of a UListFormatter operation. - * @draft ICU 64 + * @stable ICU 64 */ typedef struct UFormattedList UFormattedList; -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * FieldPosition and UFieldPosition selectors for format fields * defined by ListFormatter. - * @draft ICU 63 + * @stable ICU 63 */ typedef enum UListFormatterField { /** * The literal text in the result which came from the resources. - * @draft ICU 63 + * @stable ICU 63 */ ULISTFMT_LITERAL_FIELD, /** * The element text in the result which came from the input strings. - * @draft ICU 63 + * @stable ICU 63 */ ULISTFMT_ELEMENT_FIELD } UListFormatterField; + +#ifndef U_HIDE_DRAFT_API +/** + * Type of meaning expressed by the list. + * + * @draft ICU 67 + */ +typedef enum UListFormatterType { + /** + * Conjunction formatting, e.g. "Alice, Bob, Charlie, and Delta". + * + * @draft ICU 67 + */ + ULISTFMT_TYPE_AND, + + /** + * Disjunction (or alternative, or simply one of) formatting, e.g. + * "Alice, Bob, Charlie, or Delta". + * + * @draft ICU 67 + */ + ULISTFMT_TYPE_OR, + + /** + * Formatting of a list of values with units, e.g. "5 pounds, 12 ounces". + * + * @draft ICU 67 + */ + ULISTFMT_TYPE_UNITS +} UListFormatterType; + +/** + * Verbosity level of the list patterns. + * + * @draft ICU 67 + */ +typedef enum UListFormatterWidth { + /** + * Use list formatting with full words (no abbreviations) when possible. + * + * @draft ICU 67 + */ + ULISTFMT_WIDTH_WIDE, + + /** + * Use list formatting of typical length. + * @draft ICU 67 + */ + ULISTFMT_WIDTH_SHORT, + + /** + * Use list formatting of the shortest possible length. + * @draft ICU 67 + */ + ULISTFMT_WIDTH_NARROW, +} UListFormatterWidth; #endif /* U_HIDE_DRAFT_API */ /** * Open a new UListFormatter object using the rules for a given locale. + * The object will be initialized with AND type and WIDE width. + * * @param locale * The locale whose rules should be used; may be NULL for * default locale. @@ -83,6 +138,34 @@ U_CAPI UListFormatter* U_EXPORT2 ulistfmt_open(const char* locale, UErrorCode* status); +#ifndef U_HIDE_DRAFT_API +/** + * Open a new UListFormatter object appropriate for the given locale, list type, + * and style. + * + * @param locale + * The locale whose rules should be used; may be NULL for + * default locale. + * @param type + * The type of list formatting to use. + * @param width + * The width of formatting to use. + * @param status + * A pointer to a standard ICU UErrorCode (input/output parameter). + * Its input value must pass the U_SUCCESS() test, or else the + * function returns immediately. The caller should check its output + * value with U_FAILURE(), or use with function chaining (see User + * Guide for details). + * @return + * A pointer to a UListFormatter object for the specified locale, + * or NULL if an error occurred. + * @draft ICU 67 + */ +U_DRAFT UListFormatter* U_EXPORT2 +ulistfmt_openForType(const char* locale, UListFormatterType type, + UListFormatterWidth width, UErrorCode* status); +#endif /* U_HIDE_DRAFT_API */ + /** * Close a UListFormatter object. Once closed it may no longer be used. * @param listfmt @@ -92,7 +175,6 @@ ulistfmt_open(const char* locale, U_CAPI void U_EXPORT2 ulistfmt_close(UListFormatter *listfmt); -#ifndef U_HIDE_DRAFT_API /** * Creates an object to hold the result of a UListFormatter * operation. The object can be used repeatedly; it is cleared whenever @@ -100,7 +182,7 @@ ulistfmt_close(UListFormatter *listfmt); * * @param ec Set if an error occurs. * @return A pointer needing ownership. - * @draft ICU 64 + * @stable ICU 64 */ U_CAPI UFormattedList* U_EXPORT2 ulistfmt_openResult(UErrorCode* ec); @@ -124,7 +206,7 @@ ulistfmt_openResult(UErrorCode* ec); * @param uresult The object containing the formatted string. * @param ec Set if an error occurs. * @return A UFormattedValue owned by the input object. - * @draft ICU 64 + * @stable ICU 64 */ U_CAPI const UFormattedValue* U_EXPORT2 ulistfmt_resultAsValue(const UFormattedList* uresult, UErrorCode* ec); @@ -133,11 +215,10 @@ ulistfmt_resultAsValue(const UFormattedList* uresult, UErrorCode* ec); * Releases the UFormattedList created by ulistfmt_openResult(). * * @param uresult The object to release. - * @draft ICU 64 + * @stable ICU 64 */ U_CAPI void U_EXPORT2 ulistfmt_closeResult(UFormattedList* uresult); -#endif /* U_HIDE_DRAFT_API */ #if U_SHOW_CPLUSPLUS_API @@ -155,7 +236,6 @@ U_NAMESPACE_BEGIN */ U_DEFINE_LOCAL_OPEN_POINTER(LocalUListFormatterPointer, UListFormatter, ulistfmt_close); -#ifndef U_HIDE_DRAFT_API /** * \class LocalUFormattedListPointer * "Smart pointer" class, closes a UFormattedList via ulistfmt_closeResult(). @@ -163,10 +243,9 @@ U_DEFINE_LOCAL_OPEN_POINTER(LocalUListFormatterPointer, UListFormatter, ulistfmt * * @see LocalPointerBase * @see LocalPointer - * @draft ICU 64 + * @stable ICU 64 */ U_DEFINE_LOCAL_OPEN_POINTER(LocalUFormattedListPointer, UFormattedList, ulistfmt_closeResult); -#endif /* U_HIDE_DRAFT_API */ U_NAMESPACE_END @@ -215,7 +294,6 @@ ulistfmt_format(const UListFormatter* listfmt, int32_t resultCapacity, UErrorCode* status); -#ifndef U_HIDE_DRAFT_API /** * Formats a list of strings to a UFormattedList, which exposes more * information than the string exported by ulistfmt_format(). @@ -240,7 +318,7 @@ ulistfmt_format(const UListFormatter* listfmt, * operation. See ulistfmt_openResult(). * @param status * Error code set if an error occurred during formatting. - * @draft ICU 64 + * @stable ICU 64 */ U_CAPI void U_EXPORT2 ulistfmt_formatStringsToResult( @@ -250,7 +328,6 @@ ulistfmt_formatStringsToResult( int32_t stringCount, UFormattedList* uresult, UErrorCode* status); -#endif /* U_HIDE_DRAFT_API */ #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/unicode/unum.h b/deps/icu-small/source/i18n/unicode/unum.h index 77cde03533f4d1..b5f21ea5859071 100644 --- a/deps/icu-small/source/i18n/unicode/unum.h +++ b/deps/icu-small/source/i18n/unicode/unum.h @@ -377,12 +377,10 @@ typedef enum UNumberFormatFields { UNUM_PERMILL_FIELD, /** @stable ICU 49 */ UNUM_SIGN_FIELD, -#ifndef U_HIDE_DRAFT_API - /** @draft ICU 64 */ + /** @stable ICU 64 */ UNUM_MEASURE_UNIT_FIELD, - /** @draft ICU 64 */ + /** @stable ICU 64 */ UNUM_COMPACT_FIELD, -#endif /* U_HIDE_DRAFT_API */ #ifndef U_HIDE_DEPRECATED_API /** @@ -1032,17 +1030,15 @@ typedef enum UNumberFormatAttribute { * @stable ICU 51 */ UNUM_SCALE = 21, -#ifndef U_HIDE_DRAFT_API /** * Minimum grouping digits; most commonly set to 2 to print "1000" instead of "1,000". * See DecimalFormat::getMinimumGroupingDigits(). * * For better control over grouping strategies, use UNumberFormatter. * - * @draft ICU 64 + * @stable ICU 64 */ UNUM_MINIMUM_GROUPING_DIGITS = 22, -#endif /* U_HIDE_DRAFT_API */ /** * if this attribute is set to 0, it is set to UNUM_CURRENCY_STANDARD purpose, @@ -1083,12 +1079,10 @@ typedef enum UNumberFormatAttribute { */ UNUM_PARSE_DECIMAL_MARK_REQUIRED = 0x1002, -#ifndef U_HIDE_DRAFT_API - /** * Parsing: if set to 1, parsing is sensitive to case (lowercase/uppercase). * - * @draft ICU 64 + * @stable ICU 64 */ UNUM_PARSE_CASE_SENSITIVE = 0x1003, @@ -1097,12 +1091,10 @@ typedef enum UNumberFormatAttribute { * * For better control over sign display, use UNumberFormatter. * - * @draft ICU 64 + * @stable ICU 64 */ UNUM_SIGN_ALWAYS_SHOWN = 0x1004, -#endif /* U_HIDE_DRAFT_API */ - #ifndef U_HIDE_INTERNAL_API /** Limit of boolean attributes. (value should * not depend on U_HIDE conditionals) diff --git a/deps/icu-small/source/i18n/unicode/unumberformatter.h b/deps/icu-small/source/i18n/unicode/unumberformatter.h index b27507f7a8f561..af98ba0027238a 100644 --- a/deps/icu-small/source/i18n/unicode/unumberformatter.h +++ b/deps/icu-small/source/i18n/unicode/unumberformatter.h @@ -336,7 +336,7 @@ typedef enum UNumberSignDisplay { /** * Show the minus sign on negative numbers and the plus sign on positive numbers. Do not show a - * sign on zero or NaN, unless the sign bit is set (-0.0 gets a sign). + * sign on zero, numbers that round to zero, or NaN. * * @stable ICU 61 */ @@ -344,9 +344,8 @@ typedef enum UNumberSignDisplay { /** * Use the locale-dependent accounting format on negative numbers, and show the plus sign on - * positive numbers. Do not show a sign on zero or NaN, unless the sign bit is set (-0.0 gets a - * sign). For more information on the accounting format, see the ACCOUNTING sign display - * strategy. + * positive numbers. Do not show a sign on zero, numbers that round to zero, or NaN. For more + * information on the accounting format, see the ACCOUNTING sign display strategy. * * @stable ICU 61 */ @@ -428,7 +427,7 @@ typedef struct UFormattedNumber UFormattedNumber; * NOTE: This is a C-compatible API; C++ users should build against numberformatter.h instead. * * @param skeleton The skeleton string, like u"percent precision-integer" - * @param skeletonLen The number of UChars in the skeleton string, or -1 it it is NUL-terminated. + * @param skeletonLen The number of UChars in the skeleton string, or -1 if it is NUL-terminated. * @param locale The NUL-terminated locale ID. * @param ec Set if an error occurs. * @stable ICU 62 @@ -438,23 +437,21 @@ unumf_openForSkeletonAndLocale(const UChar* skeleton, int32_t skeletonLen, const UErrorCode* ec); -#ifndef U_HIDE_DRAFT_API /** * Like unumf_openForSkeletonAndLocale, but accepts a UParseError, which will be populated with the * location of a skeleton syntax error if such a syntax error exists. * * @param skeleton The skeleton string, like u"percent precision-integer" - * @param skeletonLen The number of UChars in the skeleton string, or -1 it it is NUL-terminated. + * @param skeletonLen The number of UChars in the skeleton string, or -1 if it is NUL-terminated. * @param locale The NUL-terminated locale ID. * @param perror A parse error struct populated if an error occurs when parsing. Can be NULL. * If no error occurs, perror->offset will be set to -1. * @param ec Set if an error occurs. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT UNumberFormatter* U_EXPORT2 +U_STABLE UNumberFormatter* U_EXPORT2 unumf_openForSkeletonAndLocaleWithError( const UChar* skeleton, int32_t skeletonLen, const char* locale, UParseError* perror, UErrorCode* ec); -#endif // U_HIDE_DRAFT_API /** @@ -532,7 +529,6 @@ U_STABLE void U_EXPORT2 unumf_formatDecimal(const UNumberFormatter* uformatter, const char* value, int32_t valueLen, UFormattedNumber* uresult, UErrorCode* ec); -#ifndef U_HIDE_DRAFT_API /** * Returns a representation of a UFormattedNumber as a UFormattedValue, * which can be subsequently passed to any API requiring that type. @@ -545,11 +541,10 @@ unumf_formatDecimal(const UNumberFormatter* uformatter, const char* value, int32 * @param uresult The object containing the formatted string. * @param ec Set if an error occurs. * @return A UFormattedValue owned by the input object. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT const UFormattedValue* U_EXPORT2 +U_STABLE const UFormattedValue* U_EXPORT2 unumf_resultAsValue(const UFormattedNumber* uresult, UErrorCode* ec); -#endif /* U_HIDE_DRAFT_API */ /** diff --git a/deps/icu-small/source/i18n/unicode/upluralrules.h b/deps/icu-small/source/i18n/unicode/upluralrules.h index fc1b2fb57173b8..9c09dfab8bb9f6 100644 --- a/deps/icu-small/source/i18n/unicode/upluralrules.h +++ b/deps/icu-small/source/i18n/unicode/upluralrules.h @@ -152,7 +152,6 @@ uplrules_select(const UPluralRules *uplrules, UChar *keyword, int32_t capacity, UErrorCode *status); -#ifndef U_HIDE_DRAFT_API /** * Given a formatted number, returns the keyword of the first rule * that applies to the number, according to the supplied UPluralRules object. @@ -168,14 +167,13 @@ uplrules_select(const UPluralRules *uplrules, * @param capacity The capacity of the keyword buffer. * @param status A pointer to a UErrorCode to receive any errors. * @return The length of the keyword. - * @draft ICU 64 + * @stable ICU 64 */ U_CAPI int32_t U_EXPORT2 uplrules_selectFormatted(const UPluralRules *uplrules, const struct UFormattedNumber* number, UChar *keyword, int32_t capacity, UErrorCode *status); -#endif /* U_HIDE_DRAFT_API */ #ifndef U_HIDE_INTERNAL_API /** diff --git a/deps/icu-small/source/i18n/unicode/ureldatefmt.h b/deps/icu-small/source/i18n/unicode/ureldatefmt.h index 1aa554dc7c0d7a..d12f0988a88ed1 100644 --- a/deps/icu-small/source/i18n/unicode/ureldatefmt.h +++ b/deps/icu-small/source/i18n/unicode/ureldatefmt.h @@ -175,25 +175,23 @@ typedef enum URelativeDateTimeUnit { #endif /* U_HIDE_DEPRECATED_API */ } URelativeDateTimeUnit; -#ifndef U_HIDE_DRAFT_API /** * FieldPosition and UFieldPosition selectors for format fields * defined by RelativeDateTimeFormatter. - * @draft ICU 64 + * @stable ICU 64 */ typedef enum URelativeDateTimeFormatterField { /** * Represents a literal text string, like "tomorrow" or "days ago". - * @draft ICU 64 + * @stable ICU 64 */ UDAT_REL_LITERAL_FIELD, /** * Represents a number quantity, like "3" in "3 days ago". - * @draft ICU 64 + * @stable ICU 64 */ UDAT_REL_NUMERIC_FIELD, } URelativeDateTimeFormatterField; -#endif // U_HIDE_DRAFT_API /** @@ -252,11 +250,10 @@ ureldatefmt_open( const char* locale, U_STABLE void U_EXPORT2 ureldatefmt_close(URelativeDateTimeFormatter *reldatefmt); -#ifndef U_HIDE_DRAFT_API struct UFormattedRelativeDateTime; /** * Opaque struct to contain the results of a URelativeDateTimeFormatter operation. - * @draft ICU 64 + * @stable ICU 64 */ typedef struct UFormattedRelativeDateTime UFormattedRelativeDateTime; @@ -267,9 +264,9 @@ typedef struct UFormattedRelativeDateTime UFormattedRelativeDateTime; * * @param ec Set if an error occurs. * @return A pointer needing ownership. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT UFormattedRelativeDateTime* U_EXPORT2 +U_STABLE UFormattedRelativeDateTime* U_EXPORT2 ureldatefmt_openResult(UErrorCode* ec); /** @@ -284,20 +281,19 @@ ureldatefmt_openResult(UErrorCode* ec); * @param ufrdt The object containing the formatted string. * @param ec Set if an error occurs. * @return A UFormattedValue owned by the input object. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT const UFormattedValue* U_EXPORT2 +U_STABLE const UFormattedValue* U_EXPORT2 ureldatefmt_resultAsValue(const UFormattedRelativeDateTime* ufrdt, UErrorCode* ec); /** * Releases the UFormattedRelativeDateTime created by ureldatefmt_openResult. * * @param ufrdt The object to release. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT void U_EXPORT2 +U_STABLE void U_EXPORT2 ureldatefmt_closeResult(UFormattedRelativeDateTime* ufrdt); -#endif /* U_HIDE_DRAFT_API */ #if U_SHOW_CPLUSPLUS_API @@ -315,7 +311,6 @@ U_NAMESPACE_BEGIN */ U_DEFINE_LOCAL_OPEN_POINTER(LocalURelativeDateTimeFormatterPointer, URelativeDateTimeFormatter, ureldatefmt_close); -#ifndef U_HIDE_DRAFT_API /** * \class LocalUFormattedRelativeDateTimePointer * "Smart pointer" class, closes a UFormattedRelativeDateTime via ureldatefmt_closeResult(). @@ -323,10 +318,9 @@ U_DEFINE_LOCAL_OPEN_POINTER(LocalURelativeDateTimeFormatterPointer, URelativeDat * * @see LocalPointerBase * @see LocalPointer - * @draft ICU 64 + * @stable ICU 64 */ U_DEFINE_LOCAL_OPEN_POINTER(LocalUFormattedRelativeDateTimePointer, UFormattedRelativeDateTime, ureldatefmt_closeResult); -#endif /* U_HIDE_DRAFT_API */ U_NAMESPACE_END @@ -368,7 +362,6 @@ ureldatefmt_formatNumeric( const URelativeDateTimeFormatter* reldatefmt, int32_t resultCapacity, UErrorCode* status); -#ifndef U_HIDE_DRAFT_API /** * Format a combination of URelativeDateTimeUnit and numeric * offset using a numeric style, e.g. "1 week ago", "in 1 week", @@ -390,16 +383,15 @@ ureldatefmt_formatNumeric( const URelativeDateTimeFormatter* reldatefmt, * A pointer to a UErrorCode to receive any errors. In * case of error status, the contents of result are * undefined. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT void U_EXPORT2 +U_STABLE void U_EXPORT2 ureldatefmt_formatNumericToResult( const URelativeDateTimeFormatter* reldatefmt, double offset, URelativeDateTimeUnit unit, UFormattedRelativeDateTime* result, UErrorCode* status); -#endif /* U_HIDE_DRAFT_API */ /** * Format a combination of URelativeDateTimeUnit and numeric offset @@ -437,7 +429,6 @@ ureldatefmt_format( const URelativeDateTimeFormatter* reldatefmt, int32_t resultCapacity, UErrorCode* status); -#ifndef U_HIDE_DRAFT_API /** * Format a combination of URelativeDateTimeUnit and numeric offset * using a text style if possible, e.g. "last week", "this week", @@ -462,16 +453,15 @@ ureldatefmt_format( const URelativeDateTimeFormatter* reldatefmt, * A pointer to a UErrorCode to receive any errors. In * case of error status, the contents of result are * undefined. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT void U_EXPORT2 +U_STABLE void U_EXPORT2 ureldatefmt_formatToResult( const URelativeDateTimeFormatter* reldatefmt, double offset, URelativeDateTimeUnit unit, UFormattedRelativeDateTime* result, UErrorCode* status); -#endif /* U_HIDE_DRAFT_API */ /** * Combines a relative date string and a time string in this object's diff --git a/deps/icu-small/source/i18n/vtzone.cpp b/deps/icu-small/source/i18n/vtzone.cpp index bda3d1115e3d13..aa2e1763966710 100644 --- a/deps/icu-small/source/i18n/vtzone.cpp +++ b/deps/icu-small/source/i18n/vtzone.cpp @@ -526,15 +526,15 @@ static void parseRRULE(const UnicodeString& rrule, int32_t& month, int32_t& dow, static TimeZoneRule* createRuleByRRULE(const UnicodeString& zonename, int rawOffset, int dstSavings, UDate start, UVector* dates, int fromOffset, UErrorCode& status) { if (U_FAILURE(status)) { - return NULL; + return nullptr; } - if (dates == NULL || dates->size() == 0) { + if (dates == nullptr || dates->size() == 0) { status = U_ILLEGAL_ARGUMENT_ERROR; - return NULL; + return nullptr; } int32_t i, j; - DateTimeRule *adtr = NULL; + DateTimeRule *adtr = nullptr; // Parse the first rule UnicodeString rrule = *((UnicodeString*)dates->elementAt(0)); @@ -545,7 +545,7 @@ static TimeZoneRule* createRuleByRRULE(const UnicodeString& zonename, int rawOff parseRRULE(rrule, month, dayOfWeek, nthDayOfWeek, days, daysCount, until, status); if (U_FAILURE(status)) { - return NULL; + return nullptr; } if (dates->size() == 1) { @@ -620,7 +620,7 @@ static TimeZoneRule* createRuleByRRULE(const UnicodeString& zonename, int rawOff int32_t tmp_daysCount = UPRV_LENGTHOF(tmp_days); parseRRULE(rrule, tmp_month, tmp_dayOfWeek, tmp_nthDayOfWeek, tmp_days, tmp_daysCount, tmp_until, status); if (U_FAILURE(status)) { - return NULL; + return nullptr; } // If UNTIL is newer than previous one, use the one if (tmp_until > until) { @@ -713,14 +713,14 @@ static TimeZoneRule* createRuleByRRULE(const UnicodeString& zonename, int rawOff // first Sunday after 15th day in the month adtr = new DateTimeRule(month, dayOfMonth, dayOfWeek, TRUE, startMID, DateTimeRule::WALL_TIME); } - if (adtr == NULL) { + if (adtr == nullptr) { goto unsupportedRRule; } return new AnnualTimeZoneRule(zonename, rawOffset, dstSavings, adtr, startYear, endYear); unsupportedRRule: status = U_INVALID_STATE_ERROR; - return NULL; + return nullptr; } /* @@ -729,34 +729,35 @@ static TimeZoneRule* createRuleByRRULE(const UnicodeString& zonename, int rawOff static TimeZoneRule* createRuleByRDATE(const UnicodeString& zonename, int32_t rawOffset, int32_t dstSavings, UDate start, UVector* dates, int32_t fromOffset, UErrorCode& status) { if (U_FAILURE(status)) { - return NULL; + return nullptr; } - TimeArrayTimeZoneRule *retVal = NULL; - if (dates == NULL || dates->size() == 0) { + TimeArrayTimeZoneRule *retVal = nullptr; + if (dates == nullptr || dates->size() == 0) { // When no RDATE line is provided, use start (DTSTART) // as the transition time - retVal = new TimeArrayTimeZoneRule(zonename, rawOffset, dstSavings, - &start, 1, DateTimeRule::UTC_TIME); + retVal = new TimeArrayTimeZoneRule(zonename, rawOffset, dstSavings, &start, 1, DateTimeRule::UTC_TIME); } else { // Create an array of transition times int32_t size = dates->size(); UDate* times = (UDate*)uprv_malloc(sizeof(UDate) * size); - if (times == NULL) { + if (times == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; - return NULL; + return nullptr; } for (int32_t i = 0; i < size; i++) { UnicodeString *datestr = (UnicodeString*)dates->elementAt(i); times[i] = parseDateTimeString(*datestr, fromOffset, status); if (U_FAILURE(status)) { uprv_free(times); - return NULL; + return nullptr; } } - retVal = new TimeArrayTimeZoneRule(zonename, rawOffset, dstSavings, - times, size, DateTimeRule::UTC_TIME); + retVal = new TimeArrayTimeZoneRule(zonename, rawOffset, dstSavings, times, size, DateTimeRule::UTC_TIME); uprv_free(times); } + if (retVal == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + } return retVal; } @@ -800,12 +801,15 @@ static UBool isEquivalentDateRule(int32_t month, int32_t weekInMonth, int32_t da /* * Convert the rule to its equivalent rule using WALL_TIME mode. - * This function returns NULL when the specified DateTimeRule is already + * This function returns nullptr when the specified DateTimeRule is already * using WALL_TIME mode. */ -static DateTimeRule* toWallTimeRule(const DateTimeRule* rule, int32_t rawOffset, int32_t dstSavings) { +static DateTimeRule *toWallTimeRule(const DateTimeRule *rule, int32_t rawOffset, int32_t dstSavings, UErrorCode &status) { + if (U_FAILURE(status)) { + return nullptr; + } if (rule->getTimeRuleType() == DateTimeRule::WALL_TIME) { - return NULL; + return nullptr; } int32_t wallt = rule->getRuleMillisInDay(); if (rule->getTimeRuleType() == DateTimeRule::UTC_TIME) { @@ -864,12 +868,14 @@ static DateTimeRule* toWallTimeRule(const DateTimeRule* rule, int32_t rawOffset, } } // Create a new rule - DateTimeRule *modifiedRule; + DateTimeRule *modifiedRule = nullptr; if (dtype == DateTimeRule::DOM) { modifiedRule = new DateTimeRule(month, dom, wallt, DateTimeRule::WALL_TIME); } else { - modifiedRule = new DateTimeRule(month, dom, dow, - (dtype == DateTimeRule::DOW_GEQ_DOM), wallt, DateTimeRule::WALL_TIME); + modifiedRule = new DateTimeRule(month, dom, dow, (dtype == DateTimeRule::DOW_GEQ_DOM), wallt, DateTimeRule::WALL_TIME); + } + if (modifiedRule == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; } return modifiedRule; } @@ -956,21 +962,24 @@ VTZReader::read(void) { UOBJECT_DEFINE_RTTI_IMPLEMENTATION(VTimeZone) VTimeZone::VTimeZone() -: BasicTimeZone(), tz(NULL), vtzlines(NULL), +: BasicTimeZone(), tz(nullptr), vtzlines(nullptr), lastmod(MAX_MILLIS) { } VTimeZone::VTimeZone(const VTimeZone& source) -: BasicTimeZone(source), tz(NULL), vtzlines(NULL), +: BasicTimeZone(source), tz(nullptr), vtzlines(nullptr), tzurl(source.tzurl), lastmod(source.lastmod), olsonzid(source.olsonzid), icutzver(source.icutzver) { - if (source.tz != NULL) { + if (source.tz != nullptr) { tz = source.tz->clone(); } - if (source.vtzlines != NULL) { + if (source.vtzlines != nullptr) { UErrorCode status = U_ZERO_ERROR; int32_t size = source.vtzlines->size(); vtzlines = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, size, status); + if (vtzlines == nullptr) { + return; + } if (U_SUCCESS(status)) { for (int32_t i = 0; i < size; i++) { UnicodeString *line = (UnicodeString*)source.vtzlines->elementAt(i); @@ -980,17 +989,17 @@ VTimeZone::VTimeZone(const VTimeZone& source) } } } - if (U_FAILURE(status) && vtzlines != NULL) { + if (U_FAILURE(status) && vtzlines != nullptr) { delete vtzlines; } } } VTimeZone::~VTimeZone() { - if (tz != NULL) { + if (tz != nullptr) { delete tz; } - if (vtzlines != NULL) { + if (vtzlines != nullptr) { delete vtzlines; } } @@ -1002,21 +1011,21 @@ VTimeZone::operator=(const VTimeZone& right) { } if (*this != right) { BasicTimeZone::operator=(right); - if (tz != NULL) { + if (tz != nullptr) { delete tz; - tz = NULL; + tz = nullptr; } - if (right.tz != NULL) { + if (right.tz != nullptr) { tz = right.tz->clone(); } - if (vtzlines != NULL) { + if (vtzlines != nullptr) { delete vtzlines; } - if (right.vtzlines != NULL) { + if (right.vtzlines != nullptr) { UErrorCode status = U_ZERO_ERROR; int32_t size = right.vtzlines->size(); vtzlines = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, size, status); - if (U_SUCCESS(status)) { + if (vtzlines != nullptr && U_SUCCESS(status)) { for (int32_t i = 0; i < size; i++) { UnicodeString *line = (UnicodeString*)right.vtzlines->elementAt(i); vtzlines->addElement(line->clone(), status); @@ -1025,9 +1034,9 @@ VTimeZone::operator=(const VTimeZone& right) { } } } - if (U_FAILURE(status) && vtzlines != NULL) { + if (U_FAILURE(status) && vtzlines != nullptr) { delete vtzlines; - vtzlines = NULL; + vtzlines = nullptr; } } tzurl = right.tzurl; @@ -1065,15 +1074,18 @@ VTimeZone::operator!=(const TimeZone& that) const { VTimeZone* VTimeZone::createVTimeZoneByID(const UnicodeString& ID) { VTimeZone *vtz = new VTimeZone(); + if (vtz == nullptr) { + return nullptr; + } vtz->tz = (BasicTimeZone*)TimeZone::createTimeZone(ID); vtz->tz->getID(vtz->olsonzid); // Set ICU tzdata version UErrorCode status = U_ZERO_ERROR; - UResourceBundle *bundle = NULL; - const UChar* versionStr = NULL; + UResourceBundle *bundle = nullptr; + const UChar* versionStr = nullptr; int32_t len = 0; - bundle = ures_openDirect(NULL, "zoneinfo64", &status); + bundle = ures_openDirect(nullptr, "zoneinfo64", &status); versionStr = ures_getStringByKey(bundle, "TZVersion", &len, &status); if (U_SUCCESS(status)) { vtz->icutzver.setTo(versionStr, len); @@ -1085,26 +1097,26 @@ VTimeZone::createVTimeZoneByID(const UnicodeString& ID) { VTimeZone* VTimeZone::createVTimeZoneFromBasicTimeZone(const BasicTimeZone& basic_time_zone, UErrorCode &status) { if (U_FAILURE(status)) { - return NULL; + return nullptr; } VTimeZone *vtz = new VTimeZone(); - if (vtz == NULL) { + if (vtz == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; - return NULL; + return nullptr; } vtz->tz = basic_time_zone.clone(); - if (vtz->tz == NULL) { + if (vtz->tz == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; delete vtz; - return NULL; + return nullptr; } vtz->tz->getID(vtz->olsonzid); // Set ICU tzdata version - UResourceBundle *bundle = NULL; - const UChar* versionStr = NULL; + UResourceBundle *bundle = nullptr; + const UChar* versionStr = nullptr; int32_t len = 0; - bundle = ures_openDirect(NULL, "zoneinfo64", &status); + bundle = ures_openDirect(nullptr, "zoneinfo64", &status); versionStr = ures_getStringByKey(bundle, "TZVersion", &len, &status); if (U_SUCCESS(status)) { vtz->icutzver.setTo(versionStr, len); @@ -1116,14 +1128,18 @@ VTimeZone::createVTimeZoneFromBasicTimeZone(const BasicTimeZone& basic_time_zone VTimeZone* VTimeZone::createVTimeZone(const UnicodeString& vtzdata, UErrorCode& status) { if (U_FAILURE(status)) { - return NULL; + return nullptr; } VTZReader reader(vtzdata); VTimeZone *vtz = new VTimeZone(); + if (vtz == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return nullptr; + } vtz->load(reader, status); if (U_FAILURE(status)) { delete vtz; - return NULL; + return nullptr; } return vtz; } @@ -1251,6 +1267,9 @@ VTimeZone::getTimeZoneRules(const InitialTimeZoneRule*& initial, void VTimeZone::load(VTZReader& reader, UErrorCode& status) { vtzlines = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, DEFAULT_VTIMEZONE_LINES, status); + if (vtzlines == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + } if (U_FAILURE(status)) { return; } @@ -1264,10 +1283,15 @@ VTimeZone::load(VTZReader& reader, UErrorCode& status) { if (ch == 0xFFFF) { // end of file if (start && line.startsWith(ICAL_END_VTIMEZONE, -1)) { - vtzlines->addElement(new UnicodeString(line), status); + LocalPointer element(new UnicodeString(line), status); + if (U_FAILURE(status)) { + goto cleanupVtzlines; + } + vtzlines->addElement(element.getAlias(), status); if (U_FAILURE(status)) { goto cleanupVtzlines; } + element.orphan(); // on success, vtzlines owns the object. success = TRUE; } break; @@ -1281,10 +1305,15 @@ VTimeZone::load(VTZReader& reader, UErrorCode& status) { // NOT followed by TAB/SP -> new line if (start) { if (line.length() > 0) { - vtzlines->addElement(new UnicodeString(line), status); + LocalPointer element(new UnicodeString(line), status); if (U_FAILURE(status)) { goto cleanupVtzlines; } + vtzlines->addElement(element.getAlias(), status); + if (U_FAILURE(status)) { + goto cleanupVtzlines; + } + element.orphan(); // on success, vtzlines owns the object. } } line.remove(); @@ -1299,19 +1328,29 @@ VTimeZone::load(VTZReader& reader, UErrorCode& status) { eol = TRUE; if (start) { if (line.startsWith(ICAL_END_VTIMEZONE, -1)) { - vtzlines->addElement(new UnicodeString(line), status); + LocalPointer element(new UnicodeString(line), status); + if (U_FAILURE(status)) { + goto cleanupVtzlines; + } + vtzlines->addElement(element.getAlias(), status); if (U_FAILURE(status)) { goto cleanupVtzlines; } + element.orphan(); // on success, vtzlines owns the object. success = TRUE; break; } } else { if (line.startsWith(ICAL_BEGIN_VTIMEZONE, -1)) { - vtzlines->addElement(new UnicodeString(line), status); + LocalPointer element(new UnicodeString(line), status); if (U_FAILURE(status)) { goto cleanupVtzlines; } + vtzlines->addElement(element.getAlias(), status); + if (U_FAILURE(status)) { + goto cleanupVtzlines; + } + element.orphan(); // on success, vtzlines owns the object. line.remove(); start = TRUE; eol = FALSE; @@ -1333,7 +1372,7 @@ VTimeZone::load(VTZReader& reader, UErrorCode& status) { cleanupVtzlines: delete vtzlines; - vtzlines = NULL; + vtzlines = nullptr; } // parser state @@ -1349,12 +1388,12 @@ VTimeZone::parse(UErrorCode& status) { if (U_FAILURE(status)) { return; } - if (vtzlines == NULL || vtzlines->size() == 0) { + if (vtzlines == nullptr || vtzlines->size() == 0) { status = U_INVALID_STATE_ERROR; return; } - InitialTimeZoneRule *initialRule = NULL; - RuleBasedTimeZone *rbtz = NULL; + InitialTimeZoneRule *initialRule = nullptr; + RuleBasedTimeZone *rbtz = nullptr; // timezone ID UnicodeString tzid; @@ -1373,13 +1412,16 @@ VTimeZone::parse(UErrorCode& status) { UnicodeString name; // RFC2445 prop name UnicodeString value; // RFC2445 prop value - UVector *dates = NULL; // list of RDATE or RRULE strings - UVector *rules = NULL; // list of TimeZoneRule instances + UVector *dates = nullptr; // list of RDATE or RRULE strings + UVector *rules = nullptr; // list of TimeZoneRule instances int32_t finalRuleIdx = -1; int32_t finalRuleCount = 0; rules = new UVector(status); + if (rules == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + } if (U_FAILURE(status)) { goto cleanupParse; } @@ -1387,11 +1429,10 @@ VTimeZone::parse(UErrorCode& status) { rules->setDeleter(deleteTimeZoneRule); dates = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status); - if (U_FAILURE(status)) { - goto cleanupParse; - } - if (rules == NULL || dates == NULL) { + if (dates == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; + } + if (U_FAILURE(status)) { goto cleanupParse; } @@ -1468,7 +1509,7 @@ VTimeZone::parse(UErrorCode& status) { // by comma UBool nextDate = TRUE; int32_t dstart = 0; - UnicodeString *dstr; + UnicodeString *dstr = nullptr; while (nextDate) { int32_t dend = value.indexOf(COMMA, dstart); if (dend == -1) { @@ -1477,7 +1518,11 @@ VTimeZone::parse(UErrorCode& status) { } else { dstr = new UnicodeString(value, dstart, dend - dstart); } - dates->addElement(dstr, status); + if (dstr == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + } else { + dates->addElement(dstr, status); + } if (U_FAILURE(status)) { goto cleanupParse; } @@ -1489,10 +1534,15 @@ VTimeZone::parse(UErrorCode& status) { goto cleanupParse; } isRRULE = true; - dates->addElement(new UnicodeString(value), status); + LocalPointer element(new UnicodeString(value), status); + if (U_FAILURE(status)) { + goto cleanupParse; + } + dates->addElement(element.getAlias(), status); if (U_FAILURE(status)) { goto cleanupParse; } + element.orphan(); // on success, dates owns the object. } else if (name.compare(ICAL_END, -1) == 0) { // Mandatory properties if (dtstart.length() == 0 || from.length() == 0 || to.length() == 0) { @@ -1504,7 +1554,7 @@ VTimeZone::parse(UErrorCode& status) { } // create a time zone rule - TimeZoneRule *rule = NULL; + TimeZoneRule *rule = nullptr; int32_t fromOffset = 0; int32_t toOffset = 0; int32_t rawOffset = 0; @@ -1546,7 +1596,7 @@ VTimeZone::parse(UErrorCode& status) { } else { rule = createRuleByRDATE(zonename, rawOffset, dstSavings, start, dates, fromOffset, status); } - if (U_FAILURE(status) || rule == NULL) { + if (U_FAILURE(status) || rule == nullptr) { goto cleanupParse; } else { UBool startAvail = rule->getFirstStart(fromOffset, 0, actualStart); @@ -1586,25 +1636,24 @@ VTimeZone::parse(UErrorCode& status) { // Create a initial rule getDefaultTZName(tzid, FALSE, zonename); - initialRule = new InitialTimeZoneRule(zonename, - initialRawOffset, initialDSTSavings); - if (initialRule == NULL) { + initialRule = new InitialTimeZoneRule(zonename, initialRawOffset, initialDSTSavings); + if (initialRule == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; goto cleanupParse; } // Finally, create the RuleBasedTimeZone rbtz = new RuleBasedTimeZone(tzid, initialRule); - if (rbtz == NULL) { + if (rbtz == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; goto cleanupParse; } - initialRule = NULL; // already adopted by RBTZ, no need to delete + initialRule = nullptr; // already adopted by RBTZ, no need to delete for (n = 0; n < rules->size(); n++) { TimeZoneRule *r = (TimeZoneRule*)rules->elementAt(n); AnnualTimeZoneRule *atzrule = dynamic_cast(r); - if (atzrule != NULL) { + if (atzrule != nullptr) { if (atzrule->getEndYear() == AnnualTimeZoneRule::MAX_YEAR) { finalRuleCount++; finalRuleIdx = n; @@ -1649,7 +1698,7 @@ VTimeZone::parse(UErrorCode& status) { } } - TimeZoneRule *newRule; + TimeZoneRule *newRule = nullptr; UnicodeString tznam; if (start == finalStart) { // Transform this into a single transition @@ -1672,7 +1721,7 @@ VTimeZone::parse(UErrorCode& status) { finalRule->getStartYear(), y); } - if (newRule == NULL) { + if (newRule == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; goto cleanupParse; } @@ -1704,20 +1753,20 @@ VTimeZone::parse(UErrorCode& status) { return; cleanupParse: - if (rules != NULL) { + if (rules != nullptr) { while (!rules->isEmpty()) { TimeZoneRule *r = (TimeZoneRule*)rules->orphanElementAt(0); delete r; } delete rules; } - if (dates != NULL) { + if (dates != nullptr) { delete dates; } - if (initialRule != NULL) { + if (initialRule != nullptr) { delete initialRule; } - if (rbtz != NULL) { + if (rbtz != nullptr) { delete rbtz; } return; @@ -1725,7 +1774,7 @@ VTimeZone::parse(UErrorCode& status) { void VTimeZone::write(VTZWriter& writer, UErrorCode& status) const { - if (vtzlines != NULL) { + if (vtzlines != nullptr) { for (int32_t i = 0; i < vtzlines->size(); i++) { UnicodeString *line = (UnicodeString*)vtzlines->elementAt(i); if (line->startsWith(ICAL_TZURL, -1) @@ -1765,8 +1814,8 @@ VTimeZone::write(UDate start, VTZWriter& writer, UErrorCode& status) const { if (U_FAILURE(status)) { return; } - InitialTimeZoneRule *initial = NULL; - UVector *transitionRules = NULL; + InitialTimeZoneRule *initial = nullptr; + UVector *transitionRules = nullptr; UVector customProps(uprv_deleteUObject, uhash_compareUnicodeString, status); UnicodeString tzid; @@ -1779,7 +1828,7 @@ VTimeZone::write(UDate start, VTZWriter& writer, UErrorCode& status) const { // Create a RuleBasedTimeZone with the subset rule getID(tzid); RuleBasedTimeZone rbtz(tzid, initial); - if (transitionRules != NULL) { + if (transitionRules != nullptr) { while (!transitionRules->isEmpty()) { TimeZoneRule *tr = (TimeZoneRule*)transitionRules->orphanElementAt(0); rbtz.addTransitionRule(tr, status); @@ -1788,7 +1837,7 @@ VTimeZone::write(UDate start, VTZWriter& writer, UErrorCode& status) const { } } delete transitionRules; - transitionRules = NULL; + transitionRules = nullptr; } rbtz.complete(status); if (U_FAILURE(status)) { @@ -1797,6 +1846,10 @@ VTimeZone::write(UDate start, VTZWriter& writer, UErrorCode& status) const { if (olsonzid.length() > 0 && icutzver.length() > 0) { UnicodeString *icutzprop = new UnicodeString(ICU_TZINFO_PROP); + if (icutzprop == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + goto cleanupWritePartial; + } icutzprop->append(olsonzid); icutzprop->append((UChar)0x005B/*'['*/); icutzprop->append(icutzver); @@ -1813,10 +1866,10 @@ VTimeZone::write(UDate start, VTZWriter& writer, UErrorCode& status) const { return; cleanupWritePartial: - if (initial != NULL) { + if (initial != nullptr) { delete initial; } - if (transitionRules != NULL) { + if (transitionRules != nullptr) { while (!transitionRules->isEmpty()) { TimeZoneRule *tr = (TimeZoneRule*)transitionRules->orphanElementAt(0); delete tr; @@ -1835,14 +1888,14 @@ VTimeZone::writeSimple(UDate time, VTZWriter& writer, UErrorCode& status) const UnicodeString tzid; // Extract simple rules - InitialTimeZoneRule *initial = NULL; - AnnualTimeZoneRule *std = NULL, *dst = NULL; + InitialTimeZoneRule *initial = nullptr; + AnnualTimeZoneRule *std = nullptr, *dst = nullptr; getSimpleRulesNear(time, initial, std, dst, status); if (U_SUCCESS(status)) { // Create a RuleBasedTimeZone with the subset rule getID(tzid); RuleBasedTimeZone rbtz(tzid, initial); - if (std != NULL && dst != NULL) { + if (std != nullptr && dst != nullptr) { rbtz.addTransitionRule(std, status); rbtz.addTransitionRule(dst, status); } @@ -1852,6 +1905,10 @@ VTimeZone::writeSimple(UDate time, VTZWriter& writer, UErrorCode& status) const if (olsonzid.length() > 0 && icutzver.length() > 0) { UnicodeString *icutzprop = new UnicodeString(ICU_TZINFO_PROP); + if (icutzprop == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + goto cleanupWriteSimple; + } icutzprop->append(olsonzid); icutzprop->append((UChar)0x005B/*'['*/); icutzprop->append(icutzver); @@ -1869,13 +1926,13 @@ VTimeZone::writeSimple(UDate time, VTZWriter& writer, UErrorCode& status) const return; cleanupWriteSimple: - if (initial != NULL) { + if (initial != nullptr) { delete initial; } - if (std != NULL) { + if (std != nullptr) { delete std; } - if (dst != NULL) { + if (dst != nullptr) { delete dst; } } @@ -1891,7 +1948,7 @@ VTimeZone::writeZone(VTZWriter& w, BasicTimeZone& basictz, return; } - if (customProps != NULL) { + if (customProps != nullptr) { for (int32_t i = 0; i < customProps->size(); i++) { UnicodeString *custprop = (UnicodeString*)customProps->elementAt(i); w.write(*custprop); @@ -1912,7 +1969,7 @@ VTimeZone::writeZone(VTZWriter& w, BasicTimeZone& basictz, UDate dstStartTime = 0.0; UDate dstUntilTime = 0.0; int32_t dstCount = 0; - AnnualTimeZoneRule *finalDstRule = NULL; + AnnualTimeZoneRule *finalDstRule = nullptr; UnicodeString stdName; int32_t stdFromOffset = 0; @@ -1926,7 +1983,7 @@ VTimeZone::writeZone(VTZWriter& w, BasicTimeZone& basictz, UDate stdStartTime = 0.0; UDate stdUntilTime = 0.0; int32_t stdCount = 0; - AnnualTimeZoneRule *finalStdRule = NULL; + AnnualTimeZoneRule *finalStdRule = nullptr; int32_t year, month, dom, dow, doy, mid; UBool hasTransitions = FALSE; @@ -1953,8 +2010,8 @@ VTimeZone::writeZone(VTZWriter& w, BasicTimeZone& basictz, UBool sameRule = FALSE; const AnnualTimeZoneRule *atzrule; if (isDst) { - if (finalDstRule == NULL - && (atzrule = dynamic_cast(tzt.getTo())) != NULL + if (finalDstRule == nullptr + && (atzrule = dynamic_cast(tzt.getTo())) != nullptr && atzrule->getEndYear() == AnnualTimeZoneRule::MAX_YEAR ) { finalDstRule = atzrule->clone(); @@ -2000,12 +2057,12 @@ VTimeZone::writeZone(VTZWriter& w, BasicTimeZone& basictz, dstStartTime = dstUntilTime = t; dstCount = 1; } - if (finalStdRule != NULL && finalDstRule != NULL) { + if (finalStdRule != nullptr && finalDstRule != nullptr) { break; } } else { - if (finalStdRule == NULL - && (atzrule = dynamic_cast(tzt.getTo())) != NULL + if (finalStdRule == nullptr + && (atzrule = dynamic_cast(tzt.getTo())) != nullptr && atzrule->getEndYear() == AnnualTimeZoneRule::MAX_YEAR ) { finalStdRule = atzrule->clone(); @@ -2051,7 +2108,7 @@ VTimeZone::writeZone(VTZWriter& w, BasicTimeZone& basictz, stdStartTime = stdUntilTime = t; stdCount = 1; } - if (finalStdRule != NULL && finalDstRule != NULL) { + if (finalStdRule != nullptr && finalDstRule != nullptr) { break; } } @@ -2075,7 +2132,7 @@ VTimeZone::writeZone(VTZWriter& w, BasicTimeZone& basictz, } } else { if (dstCount > 0) { - if (finalDstRule == NULL) { + if (finalDstRule == nullptr) { if (dstCount == 1) { writeZonePropsByTime(w, TRUE, dstName, dstFromOffset, dstToOffset, dstStartTime, TRUE, status); @@ -2117,7 +2174,7 @@ VTimeZone::writeZone(VTZWriter& w, BasicTimeZone& basictz, } } if (stdCount > 0) { - if (finalStdRule == NULL) { + if (finalStdRule == nullptr) { if (stdCount == 1) { writeZonePropsByTime(w, FALSE, stdName, stdFromOffset, stdToOffset, stdStartTime, TRUE, status); @@ -2163,10 +2220,10 @@ VTimeZone::writeZone(VTZWriter& w, BasicTimeZone& basictz, cleanupWriteZone: - if (finalStdRule != NULL) { + if (finalStdRule != nullptr) { delete finalStdRule; } - if (finalDstRule != NULL) { + if (finalDstRule != nullptr) { delete finalDstRule; } } @@ -2479,8 +2536,11 @@ VTimeZone::writeFinalRule(VTZWriter& writer, UBool isDst, const AnnualTimeZoneRu return; } UBool modifiedRule = TRUE; - const DateTimeRule *dtrule = toWallTimeRule(rule->getRule(), fromRawOffset, fromDSTSavings); - if (dtrule == NULL) { + const DateTimeRule *dtrule = toWallTimeRule(rule->getRule(), fromRawOffset, fromDSTSavings, status); + if (U_FAILURE(status)) { + return; + } + if (dtrule == nullptr) { modifiedRule = FALSE; dtrule = rule->getRule(); } diff --git a/deps/icu-small/source/tools/genccode/genccode.c b/deps/icu-small/source/tools/genccode/genccode.c index 91e94d7f5181c4..c5bbdf60d7d910 100644 --- a/deps/icu-small/source/tools/genccode/genccode.c +++ b/deps/icu-small/source/tools/genccode/genccode.c @@ -69,6 +69,7 @@ enum { #ifdef CAN_GENERATE_OBJECTS kOptObject, kOptMatchArch, + kOptSkipDllExport, #endif kOptFilename, kOptAssembly @@ -82,8 +83,9 @@ static UOption options[]={ UOPTION_DEF("name", 'n', UOPT_REQUIRES_ARG), UOPTION_DEF("entrypoint", 'e', UOPT_REQUIRES_ARG), #ifdef CAN_GENERATE_OBJECTS -/*5*/UOPTION_DEF("object", 'o', UOPT_NO_ARG), +/*6*/UOPTION_DEF("object", 'o', UOPT_NO_ARG), UOPTION_DEF("match-arch", 'm', UOPT_REQUIRES_ARG), + UOPTION_DEF("skip-dll-export", '\0', UOPT_NO_ARG), #endif UOPTION_DEF("filename", 'f', UOPT_REQUIRES_ARG), UOPTION_DEF("assembly", 'a', UOPT_REQUIRES_ARG) @@ -127,7 +129,8 @@ main(int argc, char* argv[]) { fprintf(stderr, "\t-o or --object write a .obj file instead of .c\n" "\t-m or --match-arch file.o match the architecture (CPU, 32/64 bits) of the specified .o\n" - "\t ELF format defaults to i386. Windows defaults to the native platform.\n"); + "\t ELF format defaults to i386. Windows defaults to the native platform.\n" + "\t--skip-dll-export Don't export the ICU data entry point symbol (for use when statically linking)\n"); #endif fprintf(stderr, "\t-f or --filename Specify an alternate base filename. (default: symbolname_typ)\n" @@ -193,7 +196,8 @@ main(int argc, char* argv[]) { options[kOptMatchArch].doesOccur ? options[kOptMatchArch].value : NULL, options[kOptFilename].doesOccur ? options[kOptFilename].value : NULL, NULL, - 0); + 0, + !options[kOptSkipDllExport].doesOccur); break; #endif default: diff --git a/deps/icu-small/source/tools/pkgdata/pkgdata.cpp b/deps/icu-small/source/tools/pkgdata/pkgdata.cpp index c3249bad293e3c..41a13406cf1f31 100644 --- a/deps/icu-small/source/tools/pkgdata/pkgdata.cpp +++ b/deps/icu-small/source/tools/pkgdata/pkgdata.cpp @@ -46,6 +46,7 @@ #include "flagparser.h" #include "filetools.h" #include "charstr.h" +#include "uassert.h" #if U_HAVE_POPEN # include @@ -95,7 +96,7 @@ static int32_t pkg_archiveLibrary(const char *targetDir, const char *version, UB static void createFileNames(UPKGOptions *o, const char mode, const char *version_major, const char *version, const char *libName, const UBool reverseExt, UBool noVersion); static int32_t initializePkgDataFlags(UPKGOptions *o); -static int32_t pkg_getOptionsFromICUConfig(UBool verbose, UOption *option); +static int32_t pkg_getPkgDataPath(UBool verbose, UOption *option); static int runCommand(const char* command, UBool specialHandling=FALSE); #define IN_COMMON_MODE(mode) (mode == 'a' || mode == 'c') @@ -309,7 +310,7 @@ main(int argc, char* argv[]) { #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN) if(!options[BLDOPT].doesOccur && uprv_strcmp(options[MODE].value, "common") != 0) { - if (pkg_getOptionsFromICUConfig(options[VERBOSE].doesOccur, &options[BLDOPT]) != 0) { + if (pkg_getPkgDataPath(options[VERBOSE].doesOccur, &options[BLDOPT]) != 0) { fprintf(stderr, " required parameter is missing: -O is required for static and shared builds.\n"); fprintf(stderr, "Run '%s --help' for help.\n", progname); return 1; @@ -775,7 +776,8 @@ static int32_t pkg_executeOptions(UPKGOptions *o) { (optMatchArch[0] == 0 ? NULL : optMatchArch), NULL, gencFilePath, - sizeof(gencFilePath)); + sizeof(gencFilePath), + TRUE); pkg_destroyOptMatchArch(optMatchArch); #if U_PLATFORM_IS_LINUX_BASED result = pkg_generateLibraryFile(targetDir, mode, gencFilePath); @@ -1131,12 +1133,15 @@ static int32_t pkg_installLibrary(const char *installDir, const char *targetDir, int32_t result = 0; char cmd[SMALL_BUFFER_MAX_SIZE]; - sprintf(cmd, "cd %s && %s %s %s%s%s", + auto ret = snprintf(cmd, + SMALL_BUFFER_MAX_SIZE, + "cd %s && %s %s %s%s%s", targetDir, pkgDataFlags[INSTALL_CMD], libFileNames[LIB_FILE_VERSION], - installDir, PKGDATA_FILE_SEP_STRING, libFileNames[LIB_FILE_VERSION] - ); + installDir, PKGDATA_FILE_SEP_STRING, libFileNames[LIB_FILE_VERSION]); + (void)ret; + U_ASSERT(0 <= ret && ret < SMALL_BUFFER_MAX_SIZE); result = runCommand(cmd); @@ -1254,10 +1259,14 @@ static int32_t pkg_installFileMode(const char *installDir, const char *srcDir, c buffer[bufferLength-1] = 0; } - sprintf(cmd, "%s %s%s%s %s%s%s", + auto ret = snprintf(cmd, + SMALL_BUFFER_MAX_SIZE, + "%s %s%s%s %s%s%s", pkgDataFlags[INSTALL_CMD], srcDir, PKGDATA_FILE_SEP_STRING, buffer, installDir, PKGDATA_FILE_SEP_STRING, buffer); + (void)ret; + U_ASSERT(0 <= ret && ret < SMALL_BUFFER_MAX_SIZE); result = runCommand(cmd); if (result != 0) { @@ -1689,12 +1698,20 @@ static int32_t pkg_createWithoutAssemblyCode(UPKGOptions *o, const char *targetD break; } } - sprintf(newName, "%s_%s", + auto ret = snprintf(newName, + SMALL_BUFFER_MAX_SIZE, + "%s_%s", DATA_PREFIX[n], newNameTmp); - sprintf(dataName, "%s_%s", + (void)ret; + U_ASSERT(0 <= ret && ret < SMALL_BUFFER_MAX_SIZE); + ret = snprintf(dataName, + SMALL_BUFFER_MAX_SIZE, + "%s_%s", o->shortName, DATA_PREFIX[n]); + (void)ret; + U_ASSERT(0 <= ret && ret < SMALL_BUFFER_MAX_SIZE); } if (newName[0] != 0) { break; @@ -2158,41 +2175,46 @@ static void loadLists(UPKGOptions *o, UErrorCode *status) } /* for each file list file */ } -/* Try calling icu-config directly to get the option file. */ - static int32_t pkg_getOptionsFromICUConfig(UBool verbose, UOption *option) { +/* Helper for pkg_getPkgDataPath() */ #if U_HAVE_POPEN - LocalPipeFilePointer p; - size_t n; - static char buf[512] = ""; +static UBool getPkgDataPath(const char *cmd, UBool verbose, char *buf, size_t items) { icu::CharString cmdBuf; UErrorCode status = U_ZERO_ERROR; - const char cmd[] = "icu-config --incpkgdatafile"; - char dirBuf[1024] = ""; - /* #1 try the same path where pkgdata was called from. */ - findDirname(progname, dirBuf, UPRV_LENGTHOF(dirBuf), &status); - if(U_SUCCESS(status)) { - cmdBuf.append(dirBuf, status); - if (cmdBuf[0] != 0) { - cmdBuf.append( U_FILE_SEP_STRING, status ); - } - cmdBuf.append( cmd, status ); - - if(verbose) { - fprintf(stdout, "# Calling icu-config: %s\n", cmdBuf.data()); - } - p.adoptInstead(popen(cmdBuf.data(), "r")); - } - - if(p.isNull() || (n = fread(buf, 1, UPRV_LENGTHOF(buf)-1, p.getAlias())) <= 0) { - if(verbose) { - fprintf(stdout, "# Calling icu-config: %s\n", cmd); - } + LocalPipeFilePointer p; + size_t n; + + cmdBuf.append(cmd, status); + if (verbose) { + fprintf(stdout, "# Calling: %s\n", cmdBuf.data()); + } + p.adoptInstead( popen(cmdBuf.data(), "r") ); + + if (p.isNull() || (n = fread(buf, 1, items-1, p.getAlias())) <= 0) { + fprintf(stderr, "%s: Error calling '%s'\n", progname, cmd); + *buf = 0; + return FALSE; + } - p.adoptInstead(popen(cmd, "r")); - if(p.isNull() || (n = fread(buf, 1, UPRV_LENGTHOF(buf)-1, p.getAlias())) <= 0) { - fprintf(stderr, "%s: icu-config: No icu-config found. (fix PATH or use -O option)\n", progname); + return TRUE; +} +#endif + +/* Get path to pkgdata.inc. Try pkg-config first, falling back to icu-config. */ +static int32_t pkg_getPkgDataPath(UBool verbose, UOption *option) { +#if U_HAVE_POPEN + static char buf[512] = ""; + UBool pkgconfigIsValid = TRUE; + const char *pkgconfigCmd = "pkg-config --variable=pkglibdir icu-uc"; + const char *icuconfigCmd = "icu-config --incpkgdatafile"; + const char *pkgdata = "pkgdata.inc"; + + if (!getPkgDataPath(pkgconfigCmd, verbose, buf, UPRV_LENGTHOF(buf))) { + if (!getPkgDataPath(icuconfigCmd, verbose, buf, UPRV_LENGTHOF(buf))) { + fprintf(stderr, "%s: icu-config not found. Fix PATH or specify -O option\n", progname); return -1; } + + pkgconfigIsValid = FALSE; } for (int32_t length = strlen(buf) - 1; length >= 0; length--) { @@ -2203,21 +2225,18 @@ static void loadLists(UPKGOptions *o, UErrorCode *status) } } - if(buf[strlen(buf)-1]=='\n') - { - buf[strlen(buf)-1]=0; - } - - if(buf[0] == 0) - { - fprintf(stderr, "%s: icu-config: invalid response from icu-config (fix PATH or use -O option)\n", progname); + if (!*buf) { + fprintf(stderr, "%s: Unable to locate pkgdata.inc. Unable to parse the results of '%s'. Check paths or use the -O option to specify the path to pkgdata.inc.\n", progname, pkgconfigIsValid ? pkgconfigCmd : icuconfigCmd); return -1; } - if(verbose) { - fprintf(stdout, "# icu-config said: %s\n", buf); + if (pkgconfigIsValid) { + uprv_strcat(buf, U_FILE_SEP_STRING); + uprv_strcat(buf, pkgdata); } + buf[strlen(buf)] = 0; + option->value = buf; option->doesOccur = TRUE; diff --git a/deps/icu-small/source/tools/toolutil/pkg_genc.cpp b/deps/icu-small/source/tools/toolutil/pkg_genc.cpp index b68b2d9c7c7b13..31db2e2184b3be 100644 --- a/deps/icu-small/source/tools/toolutil/pkg_genc.cpp +++ b/deps/icu-small/source/tools/toolutil/pkg_genc.cpp @@ -131,6 +131,9 @@ static const struct AssemblyType { {"gcc", ".globl %s\n" "\t.section .note.GNU-stack,\"\",%%progbits\n" + "#ifdef __CET__\n" + "# include \n" + "#endif\n" "\t.section .rodata\n" "\t.balign 16\n" "#ifdef U_HIDE_DATA_SYMBOL\n" @@ -878,7 +881,8 @@ writeObjectCode( const char *optMatchArch, const char *optFilename, char *outFilePath, - size_t outFilePathCapacity) { + size_t outFilePathCapacity, + UBool optWinDllExport) { /* common variables */ char buffer[4096], entry[96]={ 0 }; FileStream *in, *out; @@ -888,6 +892,8 @@ writeObjectCode( uint16_t cpu, bits; UBool makeBigEndian; + (void)optWinDllExport; /* unused except Windows */ + /* platform-specific variables and initialization code */ #ifdef U_ELF /* 32-bit Elf file header */ @@ -1254,12 +1260,17 @@ writeObjectCode( uprv_memset(&symbolNames, 0, sizeof(symbolNames)); /* write the linker export directive */ - uprv_strcpy(objHeader.linkerOptions, "-export:"); - length=8; - uprv_strcpy(objHeader.linkerOptions+length, entry); - length+=entryLength; - uprv_strcpy(objHeader.linkerOptions+length, ",data "); - length+=6; + if (optWinDllExport) { + uprv_strcpy(objHeader.linkerOptions, "-export:"); + length=8; + uprv_strcpy(objHeader.linkerOptions+length, entry); + length+=entryLength; + uprv_strcpy(objHeader.linkerOptions+length, ",data "); + length+=6; + } + else { + length=0; + } /* set the file header */ objHeader.fileHeader.Machine=cpu; diff --git a/deps/icu-small/source/tools/toolutil/pkg_genc.h b/deps/icu-small/source/tools/toolutil/pkg_genc.h index 47e8304a6890c5..b231aa6170c287 100644 --- a/deps/icu-small/source/tools/toolutil/pkg_genc.h +++ b/deps/icu-small/source/tools/toolutil/pkg_genc.h @@ -100,6 +100,7 @@ writeObjectCode( const char *optMatchArch, const char *optFilename, char *outFilePath, - size_t outFilePathCapacity); + size_t outFilePathCapacity, + UBool optWinDllExport); #endif diff --git a/deps/icu-small/source/tools/toolutil/toolutil.cpp b/deps/icu-small/source/tools/toolutil/toolutil.cpp index 25f9c116ee18d4..f0d6be5cf5ee2a 100644 --- a/deps/icu-small/source/tools/toolutil/toolutil.cpp +++ b/deps/icu-small/source/tools/toolutil/toolutil.cpp @@ -60,6 +60,8 @@ #include +#include + #include "unicode/errorcode.h" #include "unicode/putil.h" #include "cmemory.h" @@ -243,7 +245,7 @@ struct UToolMemory { char name[64]; int32_t capacity, maxCapacity, size, idx; void *array; - alignas(max_align_t) char staticArray[1]; + alignas(std::max_align_t) char staticArray[1]; }; U_CAPI UToolMemory * U_EXPORT2 diff --git a/deps/npm/.npmignore b/deps/npm/.npmignore index c42aaf956257d5..f45f47b93829b8 100644 --- a/deps/npm/.npmignore +++ b/deps/npm/.npmignore @@ -24,5 +24,5 @@ html/*.png *.pyc - +Session.vim .nyc_output diff --git a/deps/npm/.travis.yml b/deps/npm/.travis.yml index cec3aac226b1c1..9fb0d51133692c 100644 --- a/deps/npm/.travis.yml +++ b/deps/npm/.travis.yml @@ -12,9 +12,6 @@ node_js: env: "DEPLOY_VERSION=testing" -notifications: - slack: npm-inc:kRqQjto7YbINqHPb1X6nS3g8 - install: - "node . install" diff --git a/deps/npm/AUTHORS b/deps/npm/AUTHORS index c2a38c02d53f97..08cade33b6ff10 100644 --- a/deps/npm/AUTHORS +++ b/deps/npm/AUTHORS @@ -691,3 +691,7 @@ Vitaliy Markitanov <9357021+vit100@users.noreply.github.com> simon_s John Kennedy Bernard Kitchens +Jarda Snajdr +Naix Geng <1308363651@qq.com> +Dylan Treisman +mum-never-proud diff --git a/deps/npm/CHANGELOG.md b/deps/npm/CHANGELOG.md index 5cd9c8d8f88615..bae7de70605601 100644 --- a/deps/npm/CHANGELOG.md +++ b/deps/npm/CHANGELOG.md @@ -1,3 +1,18 @@ +## 6.14.5 (2020-05-01) + +### BUG FIXES + +* [`33ec41f18`](https://github.com/npm/cli/commit/33ec41f18f557146607cb14a7a38c707fce6d42c) [#758](https://github.com/npm/cli/pull/758) fix: relativize file links when inflating shrinkwrap ([@jsnajdr](https://github.com/jsnajdr)) +* [`94ed456df`](https://github.com/npm/cli/commit/94ed456dfb0b122fd4192429024f034d06c3c454) [#1162](https://github.com/npm/cli/pull/1162) fix: npm init help output ([@mum-never-proud](https://github.com/mum-never-proud)) + +### DEPENDENCIES + +* [`5587ac01f`](https://github.com/npm/cli/commit/5587ac01ffd0d2ea830a6bbb67bb34a611ffc409) `npm-registry-fetch@4.0.4` + * [`fc5d94c39`](https://github.com/npm/npm-registry-fetch/commit/fc5d94c39ca218d78df77249ab3a6bf1d9ed9db1) fix: removed default timeout +* [`07a4d8884`](https://github.com/npm/cli/commit/07a4d8884448359bac485a49c05fd2d23d06834b) `graceful-fs@4.2.4` +* [`8228d1f2e`](https://github.com/npm/cli/commit/8228d1f2e427ad9adee617266108acd1ee39b4a5) `mkdirp@0.5.5` +* [`e6d208317`](https://github.com/npm/cli/commit/e6d20831740a84aea766da2a2913cf82a4d56ada) `nopt@4.0.3` + ## 6.14.4 (2020-03-24) ### DEPENDENCIES diff --git a/deps/npm/CONTRIBUTING.md b/deps/npm/CONTRIBUTING.md index 981f0457d5c6bf..c08bd090cb64b4 100644 --- a/deps/npm/CONTRIBUTING.md +++ b/deps/npm/CONTRIBUTING.md @@ -73,7 +73,7 @@ All interactions in the npm repository are covered by the [npm Code of Conduct]( # Make sure you install the dependencies first before running tests. $ npm install -# Run tests for the CLI (it could take awhile). +# Run tests for the CLI (it could take a while). $ npm run test ``` @@ -97,7 +97,7 @@ $ make link ################# # ALTERNATIVELY ################# -# If ou're working on a feature or bug, you can run the same command on your +# If you're working on a feature or bug, you can run the same command on your # working branch and link that code. # Create new branch to work from (there are many ways) @@ -130,7 +130,7 @@ let you know that it's sent the request to start the benchmark suite. ![image](https://user-images.githubusercontent.com/2818462/72312698-e2e57f80-3656-11ea-9fcf-4a8f6b97b0d1.png) -If you've updated your pull-reuqest and you'd like to run the the benchmark suite again, simple update your original comment, by adding `test this please ✅` again, or simply just adding another emoji to the **end**. _(The trigger is the phrase "test this please ✅" at the beginning of a comment. Updates will trigger as well, so long as the phrase stays at the beginning.)_. +If you've updated your pull-request and you'd like to run the the benchmark suite again, simple update your original comment, by adding `test this please ✅` again, or simply just adding another emoji to the **end**. _(The trigger is the phrase "test this please ✅" at the beginning of a comment. Updates will trigger as well, so long as the phrase stays at the beginning.)_. ![image](https://user-images.githubusercontent.com/2818462/72313006-ec231c00-3657-11ea-9bd9-227634d67362.png) diff --git a/deps/npm/docs/content/cli-commands/npm.md b/deps/npm/docs/content/cli-commands/npm.md index 01a9308204d196..2d9789dd77c1c6 100644 --- a/deps/npm/docs/content/cli-commands/npm.md +++ b/deps/npm/docs/content/cli-commands/npm.md @@ -57,14 +57,14 @@ on a preinstalled git. If one of the packages npm tries to install is a native node module and requires compiling of C++ Code, npm will use -[node-gyp](https://github.com/TooTallNate/node-gyp) for that task. -For a Unix system, [node-gyp](https://github.com/TooTallNate/node-gyp) +[node-gyp](https://github.com/nodejs/node-gyp) for that task. +For a Unix system, [node-gyp](https://github.com/nodejs/node-gyp) needs Python, make and a buildchain like GCC. On Windows, Python and Microsoft Visual Studio C++ are needed. Python 3 is -not supported by [node-gyp](https://github.com/TooTallNate/node-gyp). +not supported by [node-gyp](https://github.com/nodejs/node-gyp). For more information visit -[the node-gyp repository](https://github.com/TooTallNate/node-gyp) and -the [node-gyp Wiki](https://github.com/TooTallNate/node-gyp/wiki). +[the node-gyp repository](https://github.com/nodejs/node-gyp) and +the [node-gyp Wiki](https://github.com/nodejs/node-gyp/wiki). ### Directories diff --git a/deps/npm/docs/content/using-npm/scripts.md b/deps/npm/docs/content/using-npm/scripts.md index a9ca433fdea08c..befedd0724aa56 100644 --- a/deps/npm/docs/content/using-npm/scripts.md +++ b/deps/npm/docs/content/using-npm/scripts.md @@ -145,9 +145,15 @@ suites, then those executables will be added to the `PATH` for executing the scripts. So, if your package.json has this: ```json -{ "name" : "foo" -, "dependencies" : { "bar" : "0.1.x" } -, "scripts": { "start" : "bar ./test" } } +{ + "name" : "foo", + "dependencies" : { + "bar" : "0.1.x" + }, + "scripts": { + "start" : "bar ./test" + } +} ``` then you could run `npm start` to execute the `bar` script, which is @@ -176,9 +182,15 @@ there is a config param of `[@]:`. For example, if the package.json has this: ```json -{ "name" : "foo" -, "config" : { "port" : "8080" } -, "scripts" : { "start" : "node server.js" } } +{ + "name" : "foo", + "config" : { + "port" : "8080" + }, + "scripts" : { + "start" : "node server.js" + } +} ``` and the server.js is this: @@ -213,10 +225,11 @@ process.env.npm_package_scripts_install === "foo.js" For example, if your package.json contains this: ```json -{ "scripts" : - { "install" : "scripts/install.js" - , "postinstall" : "scripts/postinstall.js" - , "uninstall" : "scripts/uninstall.js" +{ + "scripts" : { + "install" : "scripts/install.js", + "postinstall" : "scripts/install.js", + "uninstall" : "scripts/uninstall.js" } } ``` @@ -232,10 +245,11 @@ If you want to run a make command, you can do so. This works just fine: ```json -{ "scripts" : - { "preinstall" : "./configure" - , "install" : "make && make install" - , "test" : "make test" +{ + "scripts" : { + "preinstall" : "./configure", + "install" : "make && make install", + "test" : "make test" } } ``` diff --git a/deps/npm/docs/public/cli-commands/npm-access/index.html b/deps/npm/docs/public/cli-commands/npm-access/index.html index f3853e530b6b3a..63df3a3728374c 100644 --- a/deps/npm/docs/public/cli-commands/npm-access/index.html +++ b/deps/npm/docs/public/cli-commands/npm-access/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm access

+

npm access

Set access level on published packages

Synopsis

npm access public [<package>]
@@ -148,4 +148,4 @@ 

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-adduser/index.html b/deps/npm/docs/public/cli-commands/npm-adduser/index.html index 7b96fcce677001..ada805d205847f 100644 --- a/deps/npm/docs/public/cli-commands/npm-adduser/index.html +++ b/deps/npm/docs/public/cli-commands/npm-adduser/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

+

section: cli-commands title: npm-adduser description: Set access level on published packages

@@ -143,4 +143,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-audit/index.html b/deps/npm/docs/public/cli-commands/npm-audit/index.html index 5d57fac3d4e3e5..78afd583ec1937 100644 --- a/deps/npm/docs/public/cli-commands/npm-audit/index.html +++ b/deps/npm/docs/public/cli-commands/npm-audit/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm audit

+

npm audit

Run a security audit

Synopsis

npm audit [--json|--parseable|--audit-level=(low|moderate|high|critical)]
@@ -165,4 +165,4 @@ 

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-bin/index.html b/deps/npm/docs/public/cli-commands/npm-bin/index.html index c54afe93556aeb..ba6fd6ea4d2aea 100644 --- a/deps/npm/docs/public/cli-commands/npm-bin/index.html +++ b/deps/npm/docs/public/cli-commands/npm-bin/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm bin

+

npm bin

Display npm bin folder

Synopsis

npm bin [-g|--global]
@@ -94,4 +94,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-bugs/index.html b/deps/npm/docs/public/cli-commands/npm-bugs/index.html index d9f5b5282ff212..b93cd6604c1ba8 100644 --- a/deps/npm/docs/public/cli-commands/npm-bugs/index.html +++ b/deps/npm/docs/public/cli-commands/npm-bugs/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm bugs

+

npm bugs

Bugs for a package in a web browser maybe

Synopsis

npm bugs [<pkgname>]
@@ -114,4 +114,4 @@ 

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-build/index.html b/deps/npm/docs/public/cli-commands/npm-build/index.html index 8850a4e9d88f3e..b0e8aeaa7b788a 100644 --- a/deps/npm/docs/public/cli-commands/npm-build/index.html +++ b/deps/npm/docs/public/cli-commands/npm-build/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm build

+

npm build

Build a package

Synopsis

npm build [<package-folder>]
@@ -100,4 +100,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-bundle/index.html b/deps/npm/docs/public/cli-commands/npm-bundle/index.html index 9e8457cc5ac1c3..2be5194916c775 100644 --- a/deps/npm/docs/public/cli-commands/npm-bundle/index.html +++ b/deps/npm/docs/public/cli-commands/npm-bundle/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm bundle

+

npm bundle

REMOVED

Description

The npm bundle command has been removed in 1.0, for the simple reason @@ -91,4 +91,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-cache/index.html b/deps/npm/docs/public/cli-commands/npm-cache/index.html index bbf164e0fb1e5a..481cc9e44c585a 100644 --- a/deps/npm/docs/public/cli-commands/npm-cache/index.html +++ b/deps/npm/docs/public/cli-commands/npm-cache/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm cache

+

npm cache

Manipulates packages cache

Synopsis

npm cache add <tarball file>
@@ -145,4 +145,4 @@ 

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-ci/index.html b/deps/npm/docs/public/cli-commands/npm-ci/index.html index 08b46aff44b0d5..5b671a8a751d5e 100644 --- a/deps/npm/docs/public/cli-commands/npm-ci/index.html +++ b/deps/npm/docs/public/cli-commands/npm-ci/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm ci

+

npm ci

Install a project with a clean slate

Synopsis

npm ci
@@ -122,4 +122,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-completion/index.html b/deps/npm/docs/public/cli-commands/npm-completion/index.html index 0a8d28382f08e5..8ffddbecb65d23 100644 --- a/deps/npm/docs/public/cli-commands/npm-completion/index.html +++ b/deps/npm/docs/public/cli-commands/npm-completion/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm completion

+

npm completion

Tab Completion for npm

Synopsis

source <(npm completion)
@@ -104,4 +104,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-config/index.html b/deps/npm/docs/public/cli-commands/npm-config/index.html index 5f6c38423fd106..7d6227d2d9db79 100644 --- a/deps/npm/docs/public/cli-commands/npm-config/index.html +++ b/deps/npm/docs/public/cli-commands/npm-config/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm config

+

npm config

Manage the npm configuration files

Synopsis

npm config set <key> <value> [-g|--global]
@@ -128,4 +128,4 @@ 

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-dedupe/index.html b/deps/npm/docs/public/cli-commands/npm-dedupe/index.html index 0b9b4e795290c3..88d4bddb6f8468 100644 --- a/deps/npm/docs/public/cli-commands/npm-dedupe/index.html +++ b/deps/npm/docs/public/cli-commands/npm-dedupe/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm dedupe

+

npm dedupe

Reduce duplication

Synopsis

npm dedupe
@@ -121,4 +121,4 @@ 

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-deprecate/index.html b/deps/npm/docs/public/cli-commands/npm-deprecate/index.html index 503e6ec7fc4660..1bb22d2979f39f 100644 --- a/deps/npm/docs/public/cli-commands/npm-deprecate/index.html +++ b/deps/npm/docs/public/cli-commands/npm-deprecate/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm deprecate

+

npm deprecate

Deprecate a version of a package

Synopsis

npm deprecate <pkg>[@<version>] <message>
@@ -100,4 +100,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-dist-tag/index.html b/deps/npm/docs/public/cli-commands/npm-dist-tag/index.html index 7955f8def330eb..4201cb3f3c74f4 100644 --- a/deps/npm/docs/public/cli-commands/npm-dist-tag/index.html +++ b/deps/npm/docs/public/cli-commands/npm-dist-tag/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

+

section: cli-commands title: npm-dist-tag description: Modify package distribution tags

@@ -149,4 +149,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-docs/index.html b/deps/npm/docs/public/cli-commands/npm-docs/index.html index 42f18e75075ce1..b5dedd56d12a68 100644 --- a/deps/npm/docs/public/cli-commands/npm-docs/index.html +++ b/deps/npm/docs/public/cli-commands/npm-docs/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm docs

+

npm docs

Docs for a package in a web browser maybe

Synopsis

npm docs [<pkgname> [<pkgname> ...]]
@@ -115,4 +115,4 @@ 

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-doctor/index.html b/deps/npm/docs/public/cli-commands/npm-doctor/index.html index ac94c50d0edca3..a38eb67e3d21a6 100644 --- a/deps/npm/docs/public/cli-commands/npm-doctor/index.html +++ b/deps/npm/docs/public/cli-commands/npm-doctor/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm doctor

+

npm doctor

Check your environments

Synopsis

npm doctor
@@ -163,4 +163,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-edit/index.html b/deps/npm/docs/public/cli-commands/npm-edit/index.html index bddb1c09c83afc..d0a8bf18f0ffda 100644 --- a/deps/npm/docs/public/cli-commands/npm-edit/index.html +++ b/deps/npm/docs/public/cli-commands/npm-edit/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm edit

+

npm edit

Edit an installed package

Synopsis

npm edit <pkg>[/<subpkg>...]
@@ -110,4 +110,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-explore/index.html b/deps/npm/docs/public/cli-commands/npm-explore/index.html index 97f438294558d4..91374a0fac95cd 100644 --- a/deps/npm/docs/public/cli-commands/npm-explore/index.html +++ b/deps/npm/docs/public/cli-commands/npm-explore/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

+

section: cli-commands title: npm-explore description: Browse an installed package

@@ -114,4 +114,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-fund/index.html b/deps/npm/docs/public/cli-commands/npm-fund/index.html index f58901446cd58a..3d160d633ac550 100644 --- a/deps/npm/docs/public/cli-commands/npm-fund/index.html +++ b/deps/npm/docs/public/cli-commands/npm-fund/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm fund

+

npm fund

Retrieve funding information

Synopsis

    npm fund [<pkg>]
@@ -128,4 +128,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-help-search/index.html b/deps/npm/docs/public/cli-commands/npm-help-search/index.html index abd84b775782d5..e9cc5ffc7ef4d6 100644 --- a/deps/npm/docs/public/cli-commands/npm-help-search/index.html +++ b/deps/npm/docs/public/cli-commands/npm-help-search/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm help-search

+

npm help-search

Search npm help documentation

Synopsis

npm help-search <text>
@@ -105,4 +105,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-help/index.html b/deps/npm/docs/public/cli-commands/npm-help/index.html index e38710dc87f52c..0a8ab53f2a4828 100644 --- a/deps/npm/docs/public/cli-commands/npm-help/index.html +++ b/deps/npm/docs/public/cli-commands/npm-help/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm help

+

npm help

Get help on npm

Synopsis

npm help <term> [<terms..>]
@@ -107,4 +107,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-hook/index.html b/deps/npm/docs/public/cli-commands/npm-hook/index.html index bd3e717c829525..d60bcddbb96af5 100644 --- a/deps/npm/docs/public/cli-commands/npm-hook/index.html +++ b/deps/npm/docs/public/cli-commands/npm-hook/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm hook

+

npm hook

Manage registry hooks

Synopsis

npm hook ls [pkg]
@@ -119,4 +119,4 @@ 

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-init/index.html b/deps/npm/docs/public/cli-commands/npm-init/index.html index 0515fcadc6ce4b..9b51a55ff46419 100644 --- a/deps/npm/docs/public/cli-commands/npm-init/index.html +++ b/deps/npm/docs/public/cli-commands/npm-init/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm init

+

npm init

create a package.json file

Synopsis

npm init [--force|-f|--yes|-y|--scope]
@@ -126,4 +126,4 @@ 

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-install-ci-test/index.html b/deps/npm/docs/public/cli-commands/npm-install-ci-test/index.html index 78f717dc33e524..ca152fa1cd238f 100644 --- a/deps/npm/docs/public/cli-commands/npm-install-ci-test/index.html +++ b/deps/npm/docs/public/cli-commands/npm-install-ci-test/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm install-ci-test

+

npm install-ci-test

Install a project with a clean slate and run tests

Synopsis

npm install-ci-test
@@ -93,4 +93,4 @@ 

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-install-test/index.html b/deps/npm/docs/public/cli-commands/npm-install-test/index.html index d63b61afcf1249..368eb1929d46f3 100644 --- a/deps/npm/docs/public/cli-commands/npm-install-test/index.html +++ b/deps/npm/docs/public/cli-commands/npm-install-test/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm install-test

+

npm install-test

Install package(s) and run tests

Synopsis

npm install-test (with no args, in package dir)
@@ -102,4 +102,4 @@ 

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-install/index.html b/deps/npm/docs/public/cli-commands/npm-install/index.html index 16a98c965a6d08..8e8b3fd7ff4b74 100644 --- a/deps/npm/docs/public/cli-commands/npm-install/index.html +++ b/deps/npm/docs/public/cli-commands/npm-install/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm install

+

npm install

Install a package

Synopsis

npm install (with no args, in package dir)
@@ -468,4 +468,4 @@ 

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-link/index.html b/deps/npm/docs/public/cli-commands/npm-link/index.html index 5b568995d6209d..c19007eb504fe0 100644 --- a/deps/npm/docs/public/cli-commands/npm-link/index.html +++ b/deps/npm/docs/public/cli-commands/npm-link/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm link

+

npm link

Synopsis

npm link (in package dir)
@@ -134,4 +134,4 @@ 

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-logout/index.html b/deps/npm/docs/public/cli-commands/npm-logout/index.html index 7e4ce934fb5c4c..6a357ee4d358ea 100644 --- a/deps/npm/docs/public/cli-commands/npm-logout/index.html +++ b/deps/npm/docs/public/cli-commands/npm-logout/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm logout

+

npm logout

Log out of the registry

Synopsis

npm logout [--registry=<url>] [--scope=<@scope>]
@@ -109,4 +109,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-ls/index.html b/deps/npm/docs/public/cli-commands/npm-ls/index.html index 89ed133f3ab21b..e879abe100bc1f 100644 --- a/deps/npm/docs/public/cli-commands/npm-ls/index.html +++ b/deps/npm/docs/public/cli-commands/npm-ls/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm ls

+
\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-org/index.html b/deps/npm/docs/public/cli-commands/npm-org/index.html index 0a7800216e28e1..456c231887b571 100644 --- a/deps/npm/docs/public/cli-commands/npm-org/index.html +++ b/deps/npm/docs/public/cli-commands/npm-org/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm org

+

npm org

Manage orgs

Synopsis

npm org set <orgname> <username> [developer | admin | owner]
@@ -107,4 +107,4 @@ 

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-outdated/index.html b/deps/npm/docs/public/cli-commands/npm-outdated/index.html index 77274aff6bf25d..8fe29cc37003c2 100644 --- a/deps/npm/docs/public/cli-commands/npm-outdated/index.html +++ b/deps/npm/docs/public/cli-commands/npm-outdated/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm outdated

+

npm outdated

Check for outdated packages

Synopsis

npm outdated [[<@scope>/]<pkg> ...]
@@ -178,4 +178,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-owner/index.html b/deps/npm/docs/public/cli-commands/npm-owner/index.html index d128bf2ff1136a..64784997a926d9 100644 --- a/deps/npm/docs/public/cli-commands/npm-owner/index.html +++ b/deps/npm/docs/public/cli-commands/npm-owner/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm owner

+

npm owner

Manage package owners

Synopsis

npm owner add <user> [<@scope>/]<pkg>
@@ -114,4 +114,4 @@ 

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-pack/index.html b/deps/npm/docs/public/cli-commands/npm-pack/index.html index 1bdd218cfb3f11..f07ac85d9e5b00 100644 --- a/deps/npm/docs/public/cli-commands/npm-pack/index.html +++ b/deps/npm/docs/public/cli-commands/npm-pack/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm pack

+

npm pack

Create a tarball from a package

Synopsis

npm pack [[<@scope>/]<pkg>...] [--dry-run]
@@ -102,4 +102,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-ping/index.html b/deps/npm/docs/public/cli-commands/npm-ping/index.html index 478c206499f759..b6d0f2b6be43d4 100644 --- a/deps/npm/docs/public/cli-commands/npm-ping/index.html +++ b/deps/npm/docs/public/cli-commands/npm-ping/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm ping

+

npm ping

Ping npm registry

Synopsis

npm ping [--registry <registry>]
@@ -95,4 +95,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-prefix/index.html b/deps/npm/docs/public/cli-commands/npm-prefix/index.html index aa5515abf372bb..4f7aea9576a868 100644 --- a/deps/npm/docs/public/cli-commands/npm-prefix/index.html +++ b/deps/npm/docs/public/cli-commands/npm-prefix/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm prefix

+

npm prefix

Display prefix

Synopsis

npm prefix [-g]
@@ -98,4 +98,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-profile/index.html b/deps/npm/docs/public/cli-commands/npm-profile/index.html index 97617c3fb01b80..dfef3141e6ca16 100644 --- a/deps/npm/docs/public/cli-commands/npm-profile/index.html +++ b/deps/npm/docs/public/cli-commands/npm-profile/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm profile

+

npm profile

Change settings on your registry profile

Synopsis

npm profile get [--json|--parseable] [<property>]
@@ -148,4 +148,4 @@ 

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-prune/index.html b/deps/npm/docs/public/cli-commands/npm-prune/index.html index 8dc6092402f5e1..2b6ae9f754aa6e 100644 --- a/deps/npm/docs/public/cli-commands/npm-prune/index.html +++ b/deps/npm/docs/public/cli-commands/npm-prune/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm prune

+

npm prune

Remove extraneous packages

Synopsis

npm prune [[<@scope>/]<pkg>...] [--production] [--dry-run] [--json]
@@ -108,4 +108,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-publish/index.html b/deps/npm/docs/public/cli-commands/npm-publish/index.html index 4ba3e0db658254..f5ddb1f7b6f8bc 100644 --- a/deps/npm/docs/public/cli-commands/npm-publish/index.html +++ b/deps/npm/docs/public/cli-commands/npm-publish/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm publish

+

npm publish

Publish a package

Synopsis

npm publish [<tarball>|<folder>] [--tag <tag>] [--access <public|restricted>] [--otp otpcode] [--dry-run]
@@ -140,4 +140,4 @@ 

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-rebuild/index.html b/deps/npm/docs/public/cli-commands/npm-rebuild/index.html index 1be8c34433293f..667eb2d96b7906 100644 --- a/deps/npm/docs/public/cli-commands/npm-rebuild/index.html +++ b/deps/npm/docs/public/cli-commands/npm-rebuild/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm rebuild

+

npm rebuild

Rebuild a package

Synopsis

npm rebuild [[<@scope>/<name>]...]
@@ -93,4 +93,4 @@ 

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-repo/index.html b/deps/npm/docs/public/cli-commands/npm-repo/index.html index 790ee382f5e989..da85949c143802 100644 --- a/deps/npm/docs/public/cli-commands/npm-repo/index.html +++ b/deps/npm/docs/public/cli-commands/npm-repo/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm repo

+

npm repo

Open package repository page in the browser

Synopsis

npm repo [<pkg>]
@@ -101,4 +101,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-restart/index.html b/deps/npm/docs/public/cli-commands/npm-restart/index.html index 0a360a63e88e8f..cde0b9bf741e12 100644 --- a/deps/npm/docs/public/cli-commands/npm-restart/index.html +++ b/deps/npm/docs/public/cli-commands/npm-restart/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm restart

+

npm restart

Restart a package

Synopsis

npm restart [-- <args>]
@@ -113,4 +113,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-root/index.html b/deps/npm/docs/public/cli-commands/npm-root/index.html index 28c9770f184c2a..1018371d5e8844 100644 --- a/deps/npm/docs/public/cli-commands/npm-root/index.html +++ b/deps/npm/docs/public/cli-commands/npm-root/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm root

+

npm root

Display npm root

Synopsis

npm root [-g]
@@ -94,4 +94,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-run-script/index.html b/deps/npm/docs/public/cli-commands/npm-run-script/index.html index 3afd3d51c62c09..3d4e3fed8109d5 100644 --- a/deps/npm/docs/public/cli-commands/npm-run-script/index.html +++ b/deps/npm/docs/public/cli-commands/npm-run-script/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm run-script

+

npm run-script

Run arbitrary package scripts

Synopsis

npm run-script <command> [--silent] [-- <args>...]
@@ -143,4 +143,4 @@ 

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-search/index.html b/deps/npm/docs/public/cli-commands/npm-search/index.html index d97c2b26efa3dd..77968fc78a5796 100644 --- a/deps/npm/docs/public/cli-commands/npm-search/index.html +++ b/deps/npm/docs/public/cli-commands/npm-search/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm search

+

npm search

Search for packages

Synopsis

npm search [-l|--long] [--json] [--parseable] [--no-description] [search terms ...]
@@ -168,4 +168,4 @@ 

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-shrinkwrap/index.html b/deps/npm/docs/public/cli-commands/npm-shrinkwrap/index.html index 2cff81bb8c896b..7ac4b1117182d4 100644 --- a/deps/npm/docs/public/cli-commands/npm-shrinkwrap/index.html +++ b/deps/npm/docs/public/cli-commands/npm-shrinkwrap/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm shrinkwrap

+

npm shrinkwrap

Lock down dependency versions for publication

Synopsis

npm shrinkwrap
@@ -101,4 +101,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-star/index.html b/deps/npm/docs/public/cli-commands/npm-star/index.html index d0c887c754a130..5186681c685a79 100644 --- a/deps/npm/docs/public/cli-commands/npm-star/index.html +++ b/deps/npm/docs/public/cli-commands/npm-star/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm star

+

npm star

Mark your favorite packages

Synopsis

npm star [<pkg>...]
@@ -96,4 +96,4 @@ 

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-stars/index.html b/deps/npm/docs/public/cli-commands/npm-stars/index.html index 226a132de82039..9edac6d450dd9e 100644 --- a/deps/npm/docs/public/cli-commands/npm-stars/index.html +++ b/deps/npm/docs/public/cli-commands/npm-stars/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm stars

+

npm stars

View packages marked as favorites

Synopsis

npm stars [<user>]
@@ -96,4 +96,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-start/index.html b/deps/npm/docs/public/cli-commands/npm-start/index.html index 387e4fe959e9c9..f16afcecd2b119 100644 --- a/deps/npm/docs/public/cli-commands/npm-start/index.html +++ b/deps/npm/docs/public/cli-commands/npm-start/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm start

+

npm start

Start a package

Synopsis

npm start [-- <args>]
@@ -98,4 +98,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-stop/index.html b/deps/npm/docs/public/cli-commands/npm-stop/index.html index e6fed3aeec6c23..07ba9067e27357 100644 --- a/deps/npm/docs/public/cli-commands/npm-stop/index.html +++ b/deps/npm/docs/public/cli-commands/npm-stop/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm stop

+

npm stop

Stop a package

Synopsis

npm stop [-- <args>]
@@ -94,4 +94,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-team/index.html b/deps/npm/docs/public/cli-commands/npm-team/index.html index 6d6a0bd0866a40..c8776ba911df1a 100644 --- a/deps/npm/docs/public/cli-commands/npm-team/index.html +++ b/deps/npm/docs/public/cli-commands/npm-team/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm team

+

npm team

Manage organization teams and team memberships

Synopsis

npm team create <scope:team>
@@ -125,4 +125,4 @@ 

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-test/index.html b/deps/npm/docs/public/cli-commands/npm-test/index.html index 7f47f2ab2d328d..4b7638d884244c 100644 --- a/deps/npm/docs/public/cli-commands/npm-test/index.html +++ b/deps/npm/docs/public/cli-commands/npm-test/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm test

+

npm test

Test a package

Synopsis

npm test [-- <args>]
@@ -96,4 +96,4 @@ 

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-token/index.html b/deps/npm/docs/public/cli-commands/npm-token/index.html index 10f880ea2e132e..4ee8f7539b1e4e 100644 --- a/deps/npm/docs/public/cli-commands/npm-token/index.html +++ b/deps/npm/docs/public/cli-commands/npm-token/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm token

+

npm token

Manage your authentication tokens

Synopsis

  npm token list [--json|--parseable]
@@ -133,4 +133,4 @@ 

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-uninstall/index.html b/deps/npm/docs/public/cli-commands/npm-uninstall/index.html index 059bac05a46a2d..8bc3b7a03ee84d 100644 --- a/deps/npm/docs/public/cli-commands/npm-uninstall/index.html +++ b/deps/npm/docs/public/cli-commands/npm-uninstall/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm uninstall

+

npm uninstall

Remove a package

Synopsis

npm uninstall [<@scope>/]<pkg>[@<version>]... [-S|--save|-D|--save-dev|-O|--save-optional|--no-save]
@@ -118,4 +118,4 @@ 

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-unpublish/index.html b/deps/npm/docs/public/cli-commands/npm-unpublish/index.html index f9ea9a44155b54..e04fc20823049c 100644 --- a/deps/npm/docs/public/cli-commands/npm-unpublish/index.html +++ b/deps/npm/docs/public/cli-commands/npm-unpublish/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm unpublish

+

npm unpublish

Remove a package from the registry

Synopsis

Unpublishing a single version of a package

@@ -106,4 +106,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-update/index.html b/deps/npm/docs/public/cli-commands/npm-update/index.html index e6653d1f1908f8..094b12d0f5f3ad 100644 --- a/deps/npm/docs/public/cli-commands/npm-update/index.html +++ b/deps/npm/docs/public/cli-commands/npm-update/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm update

+

npm update

Update a package

Synopsis

npm update [-g] [<pkg>...]
@@ -167,4 +167,4 @@ 

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-version/index.html b/deps/npm/docs/public/cli-commands/npm-version/index.html index d540d9d254764a..9260a0a6b2e161 100644 --- a/deps/npm/docs/public/cli-commands/npm-version/index.html +++ b/deps/npm/docs/public/cli-commands/npm-version/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm version

+

npm version

Bump a package version

Synopsis

npm version [<newversion> | major | minor | patch | premajor | preminor | prepatch | prerelease [--preid=<prerelease-id>] | from-git]
@@ -180,4 +180,4 @@ 

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-view/index.html b/deps/npm/docs/public/cli-commands/npm-view/index.html index c9345b8d0893a6..66bf9750c71cb8 100644 --- a/deps/npm/docs/public/cli-commands/npm-view/index.html +++ b/deps/npm/docs/public/cli-commands/npm-view/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm view

+

npm view

View registry info

Synopsis

npm view [<@scope>/]<name>[@<version>] [<field>[.<subfield>]...]
@@ -145,4 +145,4 @@ 

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm-whoami/index.html b/deps/npm/docs/public/cli-commands/npm-whoami/index.html index e0c37ba0252cc8..7f25283a705b61 100644 --- a/deps/npm/docs/public/cli-commands/npm-whoami/index.html +++ b/deps/npm/docs/public/cli-commands/npm-whoami/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm whoami

+

npm whoami

Display npm username

Synopsis

npm whoami [--registry <registry>]
@@ -92,4 +92,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/cli-commands/npm/index.html b/deps/npm/docs/public/cli-commands/npm/index.html index 0d06bfb33ab2e2..d6c68a00732949 100644 --- a/deps/npm/docs/public/cli-commands/npm/index.html +++ b/deps/npm/docs/public/cli-commands/npm/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm

+

npm

javascript package manager

Synopsis

npm <command> [args]

Version

-

6.14.4

+

6.14.5

Description

npm is the package manager for the Node JavaScript platform. It puts modules in place so that node can find them, and manages dependency @@ -106,14 +106,14 @@

If one of the packages npm tries to install is a native node module and requires compiling of C++ Code, npm will use -node-gyp for that task. -For a Unix system, node-gyp +node-gyp for that task. +For a Unix system, node-gyp needs Python, make and a buildchain like GCC. On Windows, Python and Microsoft Visual Studio C++ are needed. Python 3 is -not supported by node-gyp. +not supported by node-gyp. For more information visit -the node-gyp repository and -the node-gyp Wiki.

+the node-gyp repository and +the node-gyp Wiki.

Directories

See folders to learn about where npm puts stuff.

In particular, npm has two modes of operation:

@@ -211,4 +211,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/configuring-npm/folders/index.html b/deps/npm/docs/public/configuring-npm/folders/index.html index a48d6c70ff5ffd..3a7b2078ced93a 100644 --- a/deps/npm/docs/public/configuring-npm/folders/index.html +++ b/deps/npm/docs/public/configuring-npm/folders/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

folders

+

folders

Folder Structures Used by npm

Description

npm puts various things on your computer. That's its job.

@@ -240,4 +240,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/configuring-npm/install/index.html b/deps/npm/docs/public/configuring-npm/install/index.html index 1464ac5477af5a..5587e72e588736 100644 --- a/deps/npm/docs/public/configuring-npm/install/index.html +++ b/deps/npm/docs/public/configuring-npm/install/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

install

+

install

Download and Install npm

Description

To publish and install packages to and from the public npm registry, you must install Node.js and the npm command line interface using either a Node version manager or a Node installer. We strongly recommend using a Node version manager to install Node.js and npm. We do not recommend using a Node installer, since the Node installation process installs npm in a directory with local permissions and can cause permissions errors when you run npm packages globally.

@@ -123,4 +123,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/configuring-npm/npmrc/index.html b/deps/npm/docs/public/configuring-npm/npmrc/index.html index e1a2c4efda160e..b654a7f6aaf390 100644 --- a/deps/npm/docs/public/configuring-npm/npmrc/index.html +++ b/deps/npm/docs/public/configuring-npm/npmrc/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npmrc

+

npmrc

The npm config files

Description

npm gets its config settings from the command line, environment @@ -145,4 +145,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/configuring-npm/package-json/index.html b/deps/npm/docs/public/configuring-npm/package-json/index.html index 0c18b027fdb734..2edfaff524cf63 100644 --- a/deps/npm/docs/public/configuring-npm/package-json/index.html +++ b/deps/npm/docs/public/configuring-npm/package-json/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

package.json

+

package.json

Specifics of npm's package.json handling

Description

This document is all you need to know about what's required in your package.json @@ -713,4 +713,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/configuring-npm/package-lock-json/index.html b/deps/npm/docs/public/configuring-npm/package-lock-json/index.html index 6ffd16ebed3502..fe061fbb6ad16f 100644 --- a/deps/npm/docs/public/configuring-npm/package-lock-json/index.html +++ b/deps/npm/docs/public/configuring-npm/package-lock-json/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

package-lock.json

+

package-lock.json

A manifestation of the manifest

Description

package-lock.json is automatically generated for any operations where npm @@ -186,4 +186,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/configuring-npm/package-locks/index.html b/deps/npm/docs/public/configuring-npm/package-locks/index.html index 535f83b28e08e2..b2e311e1addb33 100644 --- a/deps/npm/docs/public/configuring-npm/package-locks/index.html +++ b/deps/npm/docs/public/configuring-npm/package-locks/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

package-locks

+

package-locks

An explanation of npm lockfiles

Description

Conceptually, the "input" to npm install is a package.json, while its @@ -214,4 +214,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/configuring-npm/shrinkwrap-json/index.html b/deps/npm/docs/public/configuring-npm/shrinkwrap-json/index.html index e2ff06feb4c377..7219fb663eadce 100644 --- a/deps/npm/docs/public/configuring-npm/shrinkwrap-json/index.html +++ b/deps/npm/docs/public/configuring-npm/shrinkwrap-json/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

npm shrinkwrap.json

+

npm shrinkwrap.json

A publishable lockfile

Description

npm-shrinkwrap.json is a file created by npm shrinkwrap. It is identical to @@ -102,4 +102,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/google-fonts/s/inconsolata/v18/QldKNThLqRwH-OJ1UHjlKGlZ5q4.woff b/deps/npm/docs/public/google-fonts/s/inconsolata/v18/QldKNThLqRwH-OJ1UHjlKGlZ5q4.woff deleted file mode 100644 index 9771531d13dd6e..00000000000000 Binary files a/deps/npm/docs/public/google-fonts/s/inconsolata/v18/QldKNThLqRwH-OJ1UHjlKGlZ5q4.woff and /dev/null differ diff --git a/deps/npm/docs/public/google-fonts/s/inconsolata/v18/QldKNThLqRwH-OJ1UHjlKGlZ5qg.woff2 b/deps/npm/docs/public/google-fonts/s/inconsolata/v18/QldKNThLqRwH-OJ1UHjlKGlZ5qg.woff2 deleted file mode 100644 index 77829329c652e9..00000000000000 Binary files a/deps/npm/docs/public/google-fonts/s/inconsolata/v18/QldKNThLqRwH-OJ1UHjlKGlZ5qg.woff2 and /dev/null differ diff --git a/deps/npm/docs/public/google-fonts/s/inconsolata/v18/QldXNThLqRwH-OJ1UHjlKGHiw71p5_o.woff b/deps/npm/docs/public/google-fonts/s/inconsolata/v18/QldXNThLqRwH-OJ1UHjlKGHiw71p5_o.woff deleted file mode 100644 index 656168951dd20d..00000000000000 Binary files a/deps/npm/docs/public/google-fonts/s/inconsolata/v18/QldXNThLqRwH-OJ1UHjlKGHiw71p5_o.woff and /dev/null differ diff --git a/deps/npm/docs/public/google-fonts/s/inconsolata/v18/QldXNThLqRwH-OJ1UHjlKGHiw71p5_w.woff2 b/deps/npm/docs/public/google-fonts/s/inconsolata/v18/QldXNThLqRwH-OJ1UHjlKGHiw71p5_w.woff2 deleted file mode 100644 index 8be24ab2809ad5..00000000000000 Binary files a/deps/npm/docs/public/google-fonts/s/inconsolata/v18/QldXNThLqRwH-OJ1UHjlKGHiw71p5_w.woff2 and /dev/null differ diff --git a/deps/npm/docs/public/index.html b/deps/npm/docs/public/index.html index a3bd3a8d519095..21fae68bfdbd5b 100644 --- a/deps/npm/docs/public/index.html +++ b/deps/npm/docs/public/index.html @@ -80,7 +80,7 @@ /* sc-component-id: sc-keyframes-gxCBeh */ @-webkit-keyframes gxCBeh{0%{-webkit-transform:rotate(0deg);-ms-transform:rotate(0deg);transform:rotate(0deg);}33%{-webkit-transform:rotate(8deg);-ms-transform:rotate(8deg);transform:rotate(8deg);}100%{-webkit-transform:rotate(0deg);-ms-transform:rotate(0deg);transform:rotate(0deg);}} @keyframes gxCBeh{0%{-webkit-transform:rotate(0deg);-ms-transform:rotate(0deg);transform:rotate(0deg);}33%{-webkit-transform:rotate(8deg);-ms-transform:rotate(8deg);transform:rotate(8deg);}100%{-webkit-transform:rotate(0deg);-ms-transform:rotate(0deg);transform:rotate(0deg);}} /* sc-component-id: sc-keyframes-hlcKXx */ -@-webkit-keyframes hlcKXx{0%{opacity:0;}50%{opacity:1;}100%{opacity:0;}} @keyframes hlcKXx{0%{opacity:0;}50%{opacity:1;}100%{opacity:0;}}
npm cli _
The intelligent package manager for the Node Javascript Platform. Install stuff and get coding!
npm cli _
The intelligent package manager for the Node Javascript Platform. Install stuff and get coding!
npm cli _
The intelligent package manager for the Node Javascript Platform. Install stuff and get coding!

The current stable version of npm is available on GitHub.

To upgrade, run: npm install npm@latest -g

\ No newline at end of file +
npm cli _
The intelligent package manager for the Node Javascript Platform. Install stuff and get coding!
npm cli _
The intelligent package manager for the Node Javascript Platform. Install stuff and get coding!
npm cli _
The intelligent package manager for the Node Javascript Platform. Install stuff and get coding!

The current stable version of npm is available on GitHub.

To upgrade, run: npm install npm@latest -g

\ No newline at end of file diff --git a/deps/npm/docs/public/using-npm/config/index.html b/deps/npm/docs/public/using-npm/config/index.html index 6d7c2995a95c3c..cc245172bb399c 100644 --- a/deps/npm/docs/public/using-npm/config/index.html +++ b/deps/npm/docs/public/using-npm/config/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

config

+

config

More than you probably want to know about npm configuration

Description

npm gets its configuration values from the following sources, sorted by priority:

@@ -1161,4 +1161,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/using-npm/developers/index.html b/deps/npm/docs/public/using-npm/developers/index.html index a6cbcdf43bc5e3..c6d6c506bac13a 100644 --- a/deps/npm/docs/public/using-npm/developers/index.html +++ b/deps/npm/docs/public/using-npm/developers/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

developers

+

developers

Developer Guide

Description

So, you've decided to use npm to develop (and maybe publish/deploy) @@ -259,4 +259,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/using-npm/disputes/index.html b/deps/npm/docs/public/using-npm/disputes/index.html index fa98276007062f..93a92cd27028e4 100644 --- a/deps/npm/docs/public/using-npm/disputes/index.html +++ b/deps/npm/docs/public/using-npm/disputes/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

disputes

+

disputes

Handling Module Name Disputes

This document describes the steps that you should take to resolve module name disputes with other npm publishers. It also describes special steps you should @@ -192,4 +192,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/using-npm/orgs/index.html b/deps/npm/docs/public/using-npm/orgs/index.html index 3ebd3a1444a936..0a6fa3f2b7ebe3 100644 --- a/deps/npm/docs/public/using-npm/orgs/index.html +++ b/deps/npm/docs/public/using-npm/orgs/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

orgs

+

orgs

Working with Teams & Orgs

Description

There are three levels of org users:

@@ -144,4 +144,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/using-npm/registry/index.html b/deps/npm/docs/public/using-npm/registry/index.html index 6cc806bc43651a..8bc4e9bde235ae 100644 --- a/deps/npm/docs/public/using-npm/registry/index.html +++ b/deps/npm/docs/public/using-npm/registry/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

registry

+

registry

The JavaScript Package Registry

Description

To resolve packages by name and version, npm talks to a registry website @@ -156,4 +156,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/using-npm/removal/index.html b/deps/npm/docs/public/using-npm/removal/index.html index 723334e4dae6e3..cc5fff6d64ce9d 100644 --- a/deps/npm/docs/public/using-npm/removal/index.html +++ b/deps/npm/docs/public/using-npm/removal/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

removal

+

removal

Cleaning the Slate

Synopsis

So sad to see you go.

@@ -116,4 +116,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/using-npm/scope/index.html b/deps/npm/docs/public/using-npm/scope/index.html index fe450fd3739bd7..362b542d13bd5b 100644 --- a/deps/npm/docs/public/using-npm/scope/index.html +++ b/deps/npm/docs/public/using-npm/scope/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

scope

+

scope

Scoped packages

Description

All npm packages have a name. Some package names also have a scope. A scope @@ -159,4 +159,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/using-npm/scripts/index.html b/deps/npm/docs/public/using-npm/scripts/index.html index d2376cf2754a68..4609d564041492 100644 --- a/deps/npm/docs/public/using-npm/scripts/index.html +++ b/deps/npm/docs/public/using-npm/scripts/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

scripts

+

scripts

How npm handles the "scripts" field

Description

The "scripts" property of of your package.json file supports a number of built-in scripts and their preset life cycle events as well as arbitrary scripts. These all can be executed by running npm run-script <stage> or npm run <stage> for short. Pre and post commands with matching names will be run for those as well (e.g. premyscript, myscript, postmyscript). Scripts from dependencies can be run with npm explore <pkg> -- npm run <stage>.

@@ -197,9 +197,15 @@

PATH for executing the scripts. So, if your package.json has this:

-
{ "name" : "foo"
-, "dependencies" : { "bar" : "0.1.x" }
-, "scripts": { "start" : "bar ./test" } }
+
{
+  "name" : "foo",
+  "dependencies" : {
+    "bar" : "0.1.x"
+  },
+  "scripts": {
+    "start" : "bar ./test"
+  }
+}

then you could run npm start to execute the bar script, which is exported into the node_modules/.bin directory on npm install.

package.json vars

@@ -218,9 +224,15 @@

<name>[@<version>]:<key>. For example, if the package.json has this:

-
{ "name" : "foo"
-, "config" : { "port" : "8080" }
-, "scripts" : { "start" : "node server.js" } }
+
{
+  "name" : "foo",
+  "config" : {
+    "port" : "8080"
+  },
+  "scripts" : {
+    "start" : "node server.js"
+  }
+}

and the server.js is this:

http.createServer(...).listen(process.env.npm_package_config_port)

then the user could change the behavior by doing:

@@ -236,10 +248,11 @@

process.env.npm_package_scripts_install === "foo.js"

Examples

For example, if your package.json contains this:

-
{ "scripts" :
-  { "install" : "scripts/install.js"
-  , "postinstall" : "scripts/postinstall.js"
-  , "uninstall" : "scripts/uninstall.js"
+
{
+  "scripts" : {
+    "install" : "scripts/install.js",
+    "postinstall" : "scripts/install.js",
+    "uninstall" : "scripts/uninstall.js"
   }
 }

then scripts/install.js will be called for the install @@ -250,10 +263,11 @@

{ "scripts" :
-  { "preinstall" : "./configure"
-  , "install" : "make && make install"
-  , "test" : "make test"
+
{
+  "scripts" : {
+    "preinstall" : "./configure",
+    "install" : "make && make install",
+    "test" : "make test"
   }
 }

Exiting

@@ -309,4 +323,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/docs/public/using-npm/semver/index.html b/deps/npm/docs/public/using-npm/semver/index.html index 79ff8e1c437f92..fd6017acf9e29e 100644 --- a/deps/npm/docs/public/using-npm/semver/index.html +++ b/deps/npm/docs/public/using-npm/semver/index.html @@ -26,7 +26,7 @@ /* sc-component-id: FoundTypo__Container-sc-1e373sc-0 */ .fMOzaj{margin:80px 0;border-top:1px solid black;padding:20px 0;} /* sc-component-id: Page__Content-sc-4b62ym-0 */ -.gJQTGP{max-width:760px;margin:auto;padding:0 30px 120px;}

semver(7) -- The semantic versioner for npm

+

semver(7) -- The semantic versioner for npm

Install

npm install --save semver

Usage

@@ -435,4 +435,4 @@

\ No newline at end of file +
\ No newline at end of file diff --git a/deps/npm/lib/init.js b/deps/npm/lib/init.js index 9d873689f6b7e1..41995abe22bbf1 100644 --- a/deps/npm/lib/init.js +++ b/deps/npm/lib/init.js @@ -63,7 +63,7 @@ function init (args, cb) { 'This utility will walk you through creating a package.json file.', 'It only covers the most common items, and tries to guess sensible defaults.', '', - 'See `npm help json` for definitive documentation on these fields', + 'See `npm help init` for definitive documentation on these fields', 'and exactly what they do.', '', 'Use `npm install ` afterwards to install a package and', diff --git a/deps/npm/lib/install/deps.js b/deps/npm/lib/install/deps.js index 3d8b333c64441c..72c71929630009 100644 --- a/deps/npm/lib/install/deps.js +++ b/deps/npm/lib/install/deps.js @@ -74,7 +74,10 @@ function doesChildVersionMatch (child, requested, requestor) { var childReq = child.package._requested if (childReq) { if (childReq.rawSpec === requested.rawSpec) return true - if (childReq.type === requested.type && childReq.saveSpec === requested.saveSpec) return true + if (childReq.type === requested.type) { + if (childReq.saveSpec === requested.saveSpec) return true + if (childReq.fetchSpec === requested.fetchSpec) return true + } } // If _requested didn't exist OR if it didn't match then we'll try using // _from. We pass it through npa to normalize the specifier. @@ -200,6 +203,7 @@ function removeObsoleteDep (child, log) { }) } +exports.packageRelativePath = packageRelativePath function packageRelativePath (tree) { if (!tree) return '' var requested = tree.package._requested || {} @@ -570,7 +574,7 @@ function addDependency (name, versionSpec, tree, log, done) { try { var req = childDependencySpecifier(tree, name, versionSpec) if (tree.swRequires && tree.swRequires[name]) { - var swReq = childDependencySpecifier(tree, name, tree.swRequires[name], tree.package._where) + var swReq = childDependencySpecifier(tree, name, tree.swRequires[name]) } } catch (err) { return done(err) diff --git a/deps/npm/lib/install/get-requested.js b/deps/npm/lib/install/get-requested.js index ab410ffc9b6e3c..df0eec6f6a6313 100644 --- a/deps/npm/lib/install/get-requested.js +++ b/deps/npm/lib/install/get-requested.js @@ -1,12 +1,15 @@ 'use strict' const npa = require('npm-package-arg') const moduleName = require('../utils/module-name.js') - +const packageRelativePath = require('./deps').packageRelativePath module.exports = function (child, reqBy) { if (!child.requiredBy.length) return if (!reqBy) reqBy = child.requiredBy[0] const deps = reqBy.package.dependencies || {} const devDeps = reqBy.package.devDependencies || {} + const optDeps = reqBy.package.optionalDependencies || {} const name = moduleName(child) - return npa.resolve(name, deps[name] || devDeps[name], reqBy.realpath) + const spec = deps[name] || devDeps[name] || optDeps[name] + const where = packageRelativePath(reqBy) + return npa.resolve(name, spec, where) } diff --git a/deps/npm/lib/install/inflate-shrinkwrap.js b/deps/npm/lib/install/inflate-shrinkwrap.js index 1ec4f9ba6dcfd7..122068c2012872 100644 --- a/deps/npm/lib/install/inflate-shrinkwrap.js +++ b/deps/npm/lib/install/inflate-shrinkwrap.js @@ -89,6 +89,20 @@ function tarballToVersion (name, tb) { return match[2] || match[1] } +function relativizeLink (name, spec, topPath, requested) { + if (!spec.startsWith('file:')) { + return + } + + let requestedPath = requested.fetchSpec + if (requested.type === 'file') { + requestedPath = path.dirname(requestedPath) + } + + const relativized = path.relative(requestedPath, path.resolve(topPath, spec.slice(5))) + return 'file:' + relativized +} + function inflatableChild (onDiskChild, name, topPath, tree, sw, requested, opts) { validate('OSSOOOO|ZSSOOOO', arguments) const usesIntegrity = ( @@ -101,7 +115,14 @@ function inflatableChild (onDiskChild, name, topPath, tree, sw, requested, opts) sw.resolved = sw.version sw.version = regTarball } - if (sw.requires) Object.keys(sw.requires).map(_ => { sw.requires[_] = tarballToVersion(_, sw.requires[_]) || sw.requires[_] }) + if (sw.requires) { + Object.keys(sw.requires).forEach(name => { + const spec = sw.requires[name] + sw.requires[name] = tarballToVersion(name, spec) || + relativizeLink(name, spec, topPath, requested) || + spec + }) + } const modernLink = requested.type === 'directory' && !sw.from if (hasModernMeta(onDiskChild) && childIsEquivalent(sw, requested, onDiskChild)) { // The version on disk matches the shrinkwrap entry. diff --git a/deps/npm/man/man1/npm-README.1 b/deps/npm/man/man1/npm-README.1 index 2ba6afd57c0e2f..f9f3511f7c364c 100644 --- a/deps/npm/man/man1/npm-README.1 +++ b/deps/npm/man/man1/npm-README.1 @@ -1,4 +1,4 @@ -.TH "NPM" "1" "March 2020" "" "" +.TH "NPM" "1" "May 2020" "" "" .SH "NAME" \fBnpm\fR \- a JavaScript package manager .P diff --git a/deps/npm/man/man1/npm-access.1 b/deps/npm/man/man1/npm-access.1 index 448c9859a44a62..583bbc0a252990 100644 --- a/deps/npm/man/man1/npm-access.1 +++ b/deps/npm/man/man1/npm-access.1 @@ -1,4 +1,4 @@ -.TH "NPM\-ACCESS" "1" "March 2020" "" "" +.TH "NPM\-ACCESS" "1" "May 2020" "" "" .SH "NAME" \fBnpm-access\fR \- Set access level on published packages .SS Synopsis diff --git a/deps/npm/man/man1/npm-adduser.1 b/deps/npm/man/man1/npm-adduser.1 index 3d005b13029d1a..db0e7e078dbcae 100644 --- a/deps/npm/man/man1/npm-adduser.1 +++ b/deps/npm/man/man1/npm-adduser.1 @@ -3,7 +3,7 @@ section: cli\-commands title: npm\-adduser .SH description: Set access level on published packages -.TH "NPM\-ADDUSER" "1" "March 2020" "" "" +.TH "NPM\-ADDUSER" "1" "May 2020" "" "" .SH "NAME" \fBnpm-adduser\fR \- Add a registry user account .SS Synopsis diff --git a/deps/npm/man/man1/npm-audit.1 b/deps/npm/man/man1/npm-audit.1 index d0a77fdf0d7815..db60498e2a210a 100644 --- a/deps/npm/man/man1/npm-audit.1 +++ b/deps/npm/man/man1/npm-audit.1 @@ -1,4 +1,4 @@ -.TH "NPM\-AUDIT" "1" "March 2020" "" "" +.TH "NPM\-AUDIT" "1" "May 2020" "" "" .SH "NAME" \fBnpm-audit\fR \- Run a security audit .SS Synopsis diff --git a/deps/npm/man/man1/npm-bin.1 b/deps/npm/man/man1/npm-bin.1 index 26480b0d0ff647..ffc64299daa1f7 100644 --- a/deps/npm/man/man1/npm-bin.1 +++ b/deps/npm/man/man1/npm-bin.1 @@ -1,4 +1,4 @@ -.TH "NPM\-BIN" "1" "March 2020" "" "" +.TH "NPM\-BIN" "1" "May 2020" "" "" .SH "NAME" \fBnpm-bin\fR \- Display npm bin folder .SS Synopsis diff --git a/deps/npm/man/man1/npm-bugs.1 b/deps/npm/man/man1/npm-bugs.1 index 1566c8706c1c53..967d15b73c5f6c 100644 --- a/deps/npm/man/man1/npm-bugs.1 +++ b/deps/npm/man/man1/npm-bugs.1 @@ -1,4 +1,4 @@ -.TH "NPM\-BUGS" "1" "March 2020" "" "" +.TH "NPM\-BUGS" "1" "May 2020" "" "" .SH "NAME" \fBnpm-bugs\fR \- Bugs for a package in a web browser maybe .SS Synopsis diff --git a/deps/npm/man/man1/npm-build.1 b/deps/npm/man/man1/npm-build.1 index 20919da86c19f8..5c1f2c802e1546 100644 --- a/deps/npm/man/man1/npm-build.1 +++ b/deps/npm/man/man1/npm-build.1 @@ -1,4 +1,4 @@ -.TH "NPM\-BUILD" "1" "March 2020" "" "" +.TH "NPM\-BUILD" "1" "May 2020" "" "" .SH "NAME" \fBnpm-build\fR \- Build a package .SS Synopsis diff --git a/deps/npm/man/man1/npm-bundle.1 b/deps/npm/man/man1/npm-bundle.1 index a2cb2ad35b4f2a..9b3b69753e8755 100644 --- a/deps/npm/man/man1/npm-bundle.1 +++ b/deps/npm/man/man1/npm-bundle.1 @@ -1,4 +1,4 @@ -.TH "NPM\-BUNDLE" "1" "March 2020" "" "" +.TH "NPM\-BUNDLE" "1" "May 2020" "" "" .SH "NAME" \fBnpm-bundle\fR \- REMOVED .SS Description diff --git a/deps/npm/man/man1/npm-cache.1 b/deps/npm/man/man1/npm-cache.1 index 30186d7925cf8f..201c7790106964 100644 --- a/deps/npm/man/man1/npm-cache.1 +++ b/deps/npm/man/man1/npm-cache.1 @@ -1,4 +1,4 @@ -.TH "NPM\-CACHE" "1" "March 2020" "" "" +.TH "NPM\-CACHE" "1" "May 2020" "" "" .SH "NAME" \fBnpm-cache\fR \- Manipulates packages cache .SS Synopsis diff --git a/deps/npm/man/man1/npm-ci.1 b/deps/npm/man/man1/npm-ci.1 index 625cf2ef7b4eea..807e94b067ad47 100644 --- a/deps/npm/man/man1/npm-ci.1 +++ b/deps/npm/man/man1/npm-ci.1 @@ -1,4 +1,4 @@ -.TH "NPM\-CI" "1" "March 2020" "" "" +.TH "NPM\-CI" "1" "May 2020" "" "" .SH "NAME" \fBnpm-ci\fR \- Install a project with a clean slate .SS Synopsis diff --git a/deps/npm/man/man1/npm-completion.1 b/deps/npm/man/man1/npm-completion.1 index 263e04cba27875..44e041d1032545 100644 --- a/deps/npm/man/man1/npm-completion.1 +++ b/deps/npm/man/man1/npm-completion.1 @@ -1,4 +1,4 @@ -.TH "NPM\-COMPLETION" "1" "March 2020" "" "" +.TH "NPM\-COMPLETION" "1" "May 2020" "" "" .SH "NAME" \fBnpm-completion\fR \- Tab Completion for npm .SS Synopsis diff --git a/deps/npm/man/man1/npm-config.1 b/deps/npm/man/man1/npm-config.1 index 2c71ad1410e40c..71016d0ef10dd3 100644 --- a/deps/npm/man/man1/npm-config.1 +++ b/deps/npm/man/man1/npm-config.1 @@ -1,4 +1,4 @@ -.TH "NPM\-CONFIG" "1" "March 2020" "" "" +.TH "NPM\-CONFIG" "1" "May 2020" "" "" .SH "NAME" \fBnpm-config\fR \- Manage the npm configuration files .SS Synopsis diff --git a/deps/npm/man/man1/npm-dedupe.1 b/deps/npm/man/man1/npm-dedupe.1 index 53e71c0f405040..3e41436455d37e 100644 --- a/deps/npm/man/man1/npm-dedupe.1 +++ b/deps/npm/man/man1/npm-dedupe.1 @@ -1,4 +1,4 @@ -.TH "NPM\-DEDUPE" "1" "March 2020" "" "" +.TH "NPM\-DEDUPE" "1" "May 2020" "" "" .SH "NAME" \fBnpm-dedupe\fR \- Reduce duplication .SS Synopsis diff --git a/deps/npm/man/man1/npm-deprecate.1 b/deps/npm/man/man1/npm-deprecate.1 index 3d7c160d987b33..aa14c873cc1a6f 100644 --- a/deps/npm/man/man1/npm-deprecate.1 +++ b/deps/npm/man/man1/npm-deprecate.1 @@ -1,4 +1,4 @@ -.TH "NPM\-DEPRECATE" "1" "March 2020" "" "" +.TH "NPM\-DEPRECATE" "1" "May 2020" "" "" .SH "NAME" \fBnpm-deprecate\fR \- Deprecate a version of a package .SS Synopsis diff --git a/deps/npm/man/man1/npm-dist-tag.1 b/deps/npm/man/man1/npm-dist-tag.1 index 9e8fb37ac0db3b..dae13ae00f086f 100644 --- a/deps/npm/man/man1/npm-dist-tag.1 +++ b/deps/npm/man/man1/npm-dist-tag.1 @@ -3,7 +3,7 @@ section: cli\-commands title: npm\-dist\-tag .SH description: Modify package distribution tags -.TH "NPM\-DIST\-TAG" "1" "March 2020" "" "" +.TH "NPM\-DIST\-TAG" "1" "May 2020" "" "" .SH "NAME" \fBnpm-dist-tag\fR \- Modify package distribution tags .SS Synopsis diff --git a/deps/npm/man/man1/npm-docs.1 b/deps/npm/man/man1/npm-docs.1 index e518a5082fd6de..8b6a846a9b71ff 100644 --- a/deps/npm/man/man1/npm-docs.1 +++ b/deps/npm/man/man1/npm-docs.1 @@ -1,4 +1,4 @@ -.TH "NPM\-DOCS" "1" "March 2020" "" "" +.TH "NPM\-DOCS" "1" "May 2020" "" "" .SH "NAME" \fBnpm-docs\fR \- Docs for a package in a web browser maybe .SS Synopsis diff --git a/deps/npm/man/man1/npm-doctor.1 b/deps/npm/man/man1/npm-doctor.1 index 4c04a7b6be9d41..188c80ac79ff7b 100644 --- a/deps/npm/man/man1/npm-doctor.1 +++ b/deps/npm/man/man1/npm-doctor.1 @@ -1,4 +1,4 @@ -.TH "NPM\-DOCTOR" "1" "March 2020" "" "" +.TH "NPM\-DOCTOR" "1" "May 2020" "" "" .SH "NAME" \fBnpm-doctor\fR \- Check your environments .SS Synopsis diff --git a/deps/npm/man/man1/npm-edit.1 b/deps/npm/man/man1/npm-edit.1 index 9f992f04d55f65..828825f8cb97ff 100644 --- a/deps/npm/man/man1/npm-edit.1 +++ b/deps/npm/man/man1/npm-edit.1 @@ -1,4 +1,4 @@ -.TH "NPM\-EDIT" "1" "March 2020" "" "" +.TH "NPM\-EDIT" "1" "May 2020" "" "" .SH "NAME" \fBnpm-edit\fR \- Edit an installed package .SS Synopsis diff --git a/deps/npm/man/man1/npm-explore.1 b/deps/npm/man/man1/npm-explore.1 index 74159220becef2..5859ed053ff71b 100644 --- a/deps/npm/man/man1/npm-explore.1 +++ b/deps/npm/man/man1/npm-explore.1 @@ -3,7 +3,7 @@ section: cli\-commands title: npm\-explore .SH description: Browse an installed package -.TH "NPM\-EXPLORE" "1" "March 2020" "" "" +.TH "NPM\-EXPLORE" "1" "May 2020" "" "" .SH "NAME" \fBnpm-explore\fR \- Browse an installed package .SS Synopsis diff --git a/deps/npm/man/man1/npm-fund.1 b/deps/npm/man/man1/npm-fund.1 index e4c418f8dae881..acb459d745e9bb 100644 --- a/deps/npm/man/man1/npm-fund.1 +++ b/deps/npm/man/man1/npm-fund.1 @@ -1,4 +1,4 @@ -.TH "NPM\-FUND" "1" "March 2020" "" "" +.TH "NPM\-FUND" "1" "May 2020" "" "" .SH "NAME" \fBnpm-fund\fR \- Retrieve funding information .SS Synopsis diff --git a/deps/npm/man/man1/npm-help-search.1 b/deps/npm/man/man1/npm-help-search.1 index 19c7d7b5f5693d..72c18bd5e6c54b 100644 --- a/deps/npm/man/man1/npm-help-search.1 +++ b/deps/npm/man/man1/npm-help-search.1 @@ -1,4 +1,4 @@ -.TH "NPM\-HELP\-SEARCH" "1" "March 2020" "" "" +.TH "NPM\-HELP\-SEARCH" "1" "May 2020" "" "" .SH "NAME" \fBnpm-help-search\fR \- Search npm help documentation .SS Synopsis diff --git a/deps/npm/man/man1/npm-help.1 b/deps/npm/man/man1/npm-help.1 index 6fa907cc9000f2..1aa3d6ddaea9da 100644 --- a/deps/npm/man/man1/npm-help.1 +++ b/deps/npm/man/man1/npm-help.1 @@ -1,4 +1,4 @@ -.TH "NPM\-HELP" "1" "March 2020" "" "" +.TH "NPM\-HELP" "1" "May 2020" "" "" .SH "NAME" \fBnpm-help\fR \- Get help on npm .SS Synopsis diff --git a/deps/npm/man/man1/npm-hook.1 b/deps/npm/man/man1/npm-hook.1 index 74169fb4423c60..9d6d0a04616aa6 100644 --- a/deps/npm/man/man1/npm-hook.1 +++ b/deps/npm/man/man1/npm-hook.1 @@ -1,4 +1,4 @@ -.TH "NPM\-HOOK" "1" "March 2020" "" "" +.TH "NPM\-HOOK" "1" "May 2020" "" "" .SH "NAME" \fBnpm-hook\fR \- Manage registry hooks .SS Synopsis diff --git a/deps/npm/man/man1/npm-init.1 b/deps/npm/man/man1/npm-init.1 index 5c1b522ccbf7bb..f33cede27f8d5d 100644 --- a/deps/npm/man/man1/npm-init.1 +++ b/deps/npm/man/man1/npm-init.1 @@ -1,4 +1,4 @@ -.TH "NPM\-INIT" "1" "March 2020" "" "" +.TH "NPM\-INIT" "1" "May 2020" "" "" .SH "NAME" \fBnpm-init\fR \- create a package\.json file .SS Synopsis diff --git a/deps/npm/man/man1/npm-install-ci-test.1 b/deps/npm/man/man1/npm-install-ci-test.1 index e5962b93fdae02..ed5559db37bad3 100644 --- a/deps/npm/man/man1/npm-install-ci-test.1 +++ b/deps/npm/man/man1/npm-install-ci-test.1 @@ -1,4 +1,4 @@ -.TH "NPM" "" "March 2020" "" "" +.TH "NPM" "" "May 2020" "" "" .SH "NAME" \fBnpm\fR .SS Synopsis diff --git a/deps/npm/man/man1/npm-install-test.1 b/deps/npm/man/man1/npm-install-test.1 index 73c7400b73d3de..6d65529eab00b1 100644 --- a/deps/npm/man/man1/npm-install-test.1 +++ b/deps/npm/man/man1/npm-install-test.1 @@ -1,4 +1,4 @@ -.TH "NPM" "" "March 2020" "" "" +.TH "NPM" "" "May 2020" "" "" .SH "NAME" \fBnpm\fR .SS Synopsis diff --git a/deps/npm/man/man1/npm-install.1 b/deps/npm/man/man1/npm-install.1 index 6bd9a4cd58e440..152becd7eaae61 100644 --- a/deps/npm/man/man1/npm-install.1 +++ b/deps/npm/man/man1/npm-install.1 @@ -1,4 +1,4 @@ -.TH "NPM\-INSTALL" "1" "March 2020" "" "" +.TH "NPM\-INSTALL" "1" "May 2020" "" "" .SH "NAME" \fBnpm-install\fR \- Install a package .SS Synopsis diff --git a/deps/npm/man/man1/npm-link.1 b/deps/npm/man/man1/npm-link.1 index 79ad02d88ca0db..84df5b7e446fb1 100644 --- a/deps/npm/man/man1/npm-link.1 +++ b/deps/npm/man/man1/npm-link.1 @@ -1,4 +1,4 @@ -.TH "NPM\-LINK" "1" "March 2020" "" "" +.TH "NPM\-LINK" "1" "May 2020" "" "" .SH "NAME" \fBnpm-link\fR \- Symlink a package folder .SS Synopsis diff --git a/deps/npm/man/man1/npm-logout.1 b/deps/npm/man/man1/npm-logout.1 index d9020ea68413cb..3a46bcc3af5c71 100644 --- a/deps/npm/man/man1/npm-logout.1 +++ b/deps/npm/man/man1/npm-logout.1 @@ -1,4 +1,4 @@ -.TH "NPM\-LOGOUT" "1" "March 2020" "" "" +.TH "NPM\-LOGOUT" "1" "May 2020" "" "" .SH "NAME" \fBnpm-logout\fR \- Log out of the registry .SS Synopsis diff --git a/deps/npm/man/man1/npm-ls.1 b/deps/npm/man/man1/npm-ls.1 index 54ef77772f060f..5e024fadb2f3ba 100644 --- a/deps/npm/man/man1/npm-ls.1 +++ b/deps/npm/man/man1/npm-ls.1 @@ -1,4 +1,4 @@ -.TH "NPM\-LS" "1" "March 2020" "" "" +.TH "NPM\-LS" "1" "May 2020" "" "" .SH "NAME" \fBnpm-ls\fR \- List installed packages .SS Synopsis @@ -22,7 +22,7 @@ For example, running \fBnpm ls promzard\fP in npm's source tree will show: .P .RS 2 .nf - npm@6\.14\.4 /path/to/npm + npm@6\.14\.5 /path/to/npm └─┬ init\-package\-json@0\.0\.4 └── promzard@0\.1\.5 .fi diff --git a/deps/npm/man/man1/npm-org.1 b/deps/npm/man/man1/npm-org.1 index d3f1531252ed66..cc343314f75c3c 100644 --- a/deps/npm/man/man1/npm-org.1 +++ b/deps/npm/man/man1/npm-org.1 @@ -1,4 +1,4 @@ -.TH "NPM\-ORG" "1" "March 2020" "" "" +.TH "NPM\-ORG" "1" "May 2020" "" "" .SH "NAME" \fBnpm-org\fR \- Manage orgs .SS Synopsis diff --git a/deps/npm/man/man1/npm-outdated.1 b/deps/npm/man/man1/npm-outdated.1 index 808555c7b1b989..d353c5f340a66c 100644 --- a/deps/npm/man/man1/npm-outdated.1 +++ b/deps/npm/man/man1/npm-outdated.1 @@ -1,4 +1,4 @@ -.TH "NPM\-OUTDATED" "1" "March 2020" "" "" +.TH "NPM\-OUTDATED" "1" "May 2020" "" "" .SH "NAME" \fBnpm-outdated\fR \- Check for outdated packages .SS Synopsis diff --git a/deps/npm/man/man1/npm-owner.1 b/deps/npm/man/man1/npm-owner.1 index f0e2f07a0cbc9a..34917c9b88340c 100644 --- a/deps/npm/man/man1/npm-owner.1 +++ b/deps/npm/man/man1/npm-owner.1 @@ -1,4 +1,4 @@ -.TH "NPM\-OWNER" "1" "March 2020" "" "" +.TH "NPM\-OWNER" "1" "May 2020" "" "" .SH "NAME" \fBnpm-owner\fR \- Manage package owners .SS Synopsis diff --git a/deps/npm/man/man1/npm-pack.1 b/deps/npm/man/man1/npm-pack.1 index dac6963b4a2672..c9163675ec45d0 100644 --- a/deps/npm/man/man1/npm-pack.1 +++ b/deps/npm/man/man1/npm-pack.1 @@ -1,4 +1,4 @@ -.TH "NPM\-PACK" "1" "March 2020" "" "" +.TH "NPM\-PACK" "1" "May 2020" "" "" .SH "NAME" \fBnpm-pack\fR \- Create a tarball from a package .SS Synopsis diff --git a/deps/npm/man/man1/npm-ping.1 b/deps/npm/man/man1/npm-ping.1 index 28ae935229cda4..0558082b0c4fbd 100644 --- a/deps/npm/man/man1/npm-ping.1 +++ b/deps/npm/man/man1/npm-ping.1 @@ -1,4 +1,4 @@ -.TH "NPM\-PING" "1" "March 2020" "" "" +.TH "NPM\-PING" "1" "May 2020" "" "" .SH "NAME" \fBnpm-ping\fR \- Ping npm registry .SS Synopsis diff --git a/deps/npm/man/man1/npm-prefix.1 b/deps/npm/man/man1/npm-prefix.1 index 3b695b870e085b..3483ad3708e43d 100644 --- a/deps/npm/man/man1/npm-prefix.1 +++ b/deps/npm/man/man1/npm-prefix.1 @@ -1,4 +1,4 @@ -.TH "NPM\-PREFIX" "1" "March 2020" "" "" +.TH "NPM\-PREFIX" "1" "May 2020" "" "" .SH "NAME" \fBnpm-prefix\fR \- Display prefix .SS Synopsis diff --git a/deps/npm/man/man1/npm-profile.1 b/deps/npm/man/man1/npm-profile.1 index b0990f099e5085..d1580469207b15 100644 --- a/deps/npm/man/man1/npm-profile.1 +++ b/deps/npm/man/man1/npm-profile.1 @@ -1,4 +1,4 @@ -.TH "NPM\-PROFILE" "1" "March 2020" "" "" +.TH "NPM\-PROFILE" "1" "May 2020" "" "" .SH "NAME" \fBnpm-profile\fR \- Change settings on your registry profile .SS Synopsis diff --git a/deps/npm/man/man1/npm-prune.1 b/deps/npm/man/man1/npm-prune.1 index b51f829ca9c9fc..95d8e15984e1f9 100644 --- a/deps/npm/man/man1/npm-prune.1 +++ b/deps/npm/man/man1/npm-prune.1 @@ -1,4 +1,4 @@ -.TH "NPM\-PRUNE" "1" "March 2020" "" "" +.TH "NPM\-PRUNE" "1" "May 2020" "" "" .SH "NAME" \fBnpm-prune\fR \- Remove extraneous packages .SS Synopsis diff --git a/deps/npm/man/man1/npm-publish.1 b/deps/npm/man/man1/npm-publish.1 index eec1f60120a4cd..d4ad6b01fb340d 100644 --- a/deps/npm/man/man1/npm-publish.1 +++ b/deps/npm/man/man1/npm-publish.1 @@ -1,4 +1,4 @@ -.TH "NPM\-PUBLISH" "1" "March 2020" "" "" +.TH "NPM\-PUBLISH" "1" "May 2020" "" "" .SH "NAME" \fBnpm-publish\fR \- Publish a package .SS Synopsis diff --git a/deps/npm/man/man1/npm-rebuild.1 b/deps/npm/man/man1/npm-rebuild.1 index 7e0d43fadf134d..41df28b52e6d01 100644 --- a/deps/npm/man/man1/npm-rebuild.1 +++ b/deps/npm/man/man1/npm-rebuild.1 @@ -1,4 +1,4 @@ -.TH "NPM\-REBUILD" "1" "March 2020" "" "" +.TH "NPM\-REBUILD" "1" "May 2020" "" "" .SH "NAME" \fBnpm-rebuild\fR \- Rebuild a package .SS Synopsis diff --git a/deps/npm/man/man1/npm-repo.1 b/deps/npm/man/man1/npm-repo.1 index 68920454a69173..360080640b59f9 100644 --- a/deps/npm/man/man1/npm-repo.1 +++ b/deps/npm/man/man1/npm-repo.1 @@ -1,4 +1,4 @@ -.TH "NPM\-REPO" "1" "March 2020" "" "" +.TH "NPM\-REPO" "1" "May 2020" "" "" .SH "NAME" \fBnpm-repo\fR \- Open package repository page in the browser .SS Synopsis diff --git a/deps/npm/man/man1/npm-restart.1 b/deps/npm/man/man1/npm-restart.1 index d90bebb90633d5..6c72553de428d2 100644 --- a/deps/npm/man/man1/npm-restart.1 +++ b/deps/npm/man/man1/npm-restart.1 @@ -1,4 +1,4 @@ -.TH "NPM\-RESTART" "1" "March 2020" "" "" +.TH "NPM\-RESTART" "1" "May 2020" "" "" .SH "NAME" \fBnpm-restart\fR \- Restart a package .SS Synopsis diff --git a/deps/npm/man/man1/npm-root.1 b/deps/npm/man/man1/npm-root.1 index dab19fcabf5a0e..93ff1323e3f0ce 100644 --- a/deps/npm/man/man1/npm-root.1 +++ b/deps/npm/man/man1/npm-root.1 @@ -1,4 +1,4 @@ -.TH "NPM\-ROOT" "1" "March 2020" "" "" +.TH "NPM\-ROOT" "1" "May 2020" "" "" .SH "NAME" \fBnpm-root\fR \- Display npm root .SS Synopsis diff --git a/deps/npm/man/man1/npm-run-script.1 b/deps/npm/man/man1/npm-run-script.1 index 8a7d2b6e2ff06c..4e38d392d63792 100644 --- a/deps/npm/man/man1/npm-run-script.1 +++ b/deps/npm/man/man1/npm-run-script.1 @@ -1,4 +1,4 @@ -.TH "NPM\-RUN\-SCRIPT" "1" "March 2020" "" "" +.TH "NPM\-RUN\-SCRIPT" "1" "May 2020" "" "" .SH "NAME" \fBnpm-run-script\fR \- Run arbitrary package scripts .SS Synopsis diff --git a/deps/npm/man/man1/npm-search.1 b/deps/npm/man/man1/npm-search.1 index 9b9b7861dab818..e2406f92252aae 100644 --- a/deps/npm/man/man1/npm-search.1 +++ b/deps/npm/man/man1/npm-search.1 @@ -1,4 +1,4 @@ -.TH "NPM\-SEARCH" "1" "March 2020" "" "" +.TH "NPM\-SEARCH" "1" "May 2020" "" "" .SH "NAME" \fBnpm-search\fR \- Search for packages .SS Synopsis diff --git a/deps/npm/man/man1/npm-shrinkwrap.1 b/deps/npm/man/man1/npm-shrinkwrap.1 index 59b2e499d1e9bf..4f4b95715cff88 100644 --- a/deps/npm/man/man1/npm-shrinkwrap.1 +++ b/deps/npm/man/man1/npm-shrinkwrap.1 @@ -1,4 +1,4 @@ -.TH "NPM\-SHRINKWRAP" "1" "March 2020" "" "" +.TH "NPM\-SHRINKWRAP" "1" "May 2020" "" "" .SH "NAME" \fBnpm-shrinkwrap\fR \- Lock down dependency versions for publication .SS Synopsis diff --git a/deps/npm/man/man1/npm-star.1 b/deps/npm/man/man1/npm-star.1 index e5a18f85be1374..023f409b75c006 100644 --- a/deps/npm/man/man1/npm-star.1 +++ b/deps/npm/man/man1/npm-star.1 @@ -1,4 +1,4 @@ -.TH "NPM\-STAR" "1" "March 2020" "" "" +.TH "NPM\-STAR" "1" "May 2020" "" "" .SH "NAME" \fBnpm-star\fR \- Mark your favorite packages .SS Synopsis diff --git a/deps/npm/man/man1/npm-stars.1 b/deps/npm/man/man1/npm-stars.1 index bcc7cce20518c1..b2e851319715b0 100644 --- a/deps/npm/man/man1/npm-stars.1 +++ b/deps/npm/man/man1/npm-stars.1 @@ -1,4 +1,4 @@ -.TH "NPM\-STARS" "1" "March 2020" "" "" +.TH "NPM\-STARS" "1" "May 2020" "" "" .SH "NAME" \fBnpm-stars\fR \- View packages marked as favorites .SS Synopsis diff --git a/deps/npm/man/man1/npm-start.1 b/deps/npm/man/man1/npm-start.1 index 64a22b7cb9461a..b64ec8b17533fe 100644 --- a/deps/npm/man/man1/npm-start.1 +++ b/deps/npm/man/man1/npm-start.1 @@ -1,4 +1,4 @@ -.TH "NPM\-START" "1" "March 2020" "" "" +.TH "NPM\-START" "1" "May 2020" "" "" .SH "NAME" \fBnpm-start\fR \- Start a package .SS Synopsis diff --git a/deps/npm/man/man1/npm-stop.1 b/deps/npm/man/man1/npm-stop.1 index 5144671e15fcdd..1e23c9385f6c0d 100644 --- a/deps/npm/man/man1/npm-stop.1 +++ b/deps/npm/man/man1/npm-stop.1 @@ -1,4 +1,4 @@ -.TH "NPM\-STOP" "1" "March 2020" "" "" +.TH "NPM\-STOP" "1" "May 2020" "" "" .SH "NAME" \fBnpm-stop\fR \- Stop a package .SS Synopsis diff --git a/deps/npm/man/man1/npm-team.1 b/deps/npm/man/man1/npm-team.1 index 6e0b1da57d6e06..2419f372b3d10b 100644 --- a/deps/npm/man/man1/npm-team.1 +++ b/deps/npm/man/man1/npm-team.1 @@ -1,4 +1,4 @@ -.TH "NPM\-TEAM" "1" "March 2020" "" "" +.TH "NPM\-TEAM" "1" "May 2020" "" "" .SH "NAME" \fBnpm-team\fR \- Manage organization teams and team memberships .SS Synopsis diff --git a/deps/npm/man/man1/npm-test.1 b/deps/npm/man/man1/npm-test.1 index fed0b5d5bb2dd1..b046fa0376d56f 100644 --- a/deps/npm/man/man1/npm-test.1 +++ b/deps/npm/man/man1/npm-test.1 @@ -1,4 +1,4 @@ -.TH "NPM\-TEST" "1" "March 2020" "" "" +.TH "NPM\-TEST" "1" "May 2020" "" "" .SH "NAME" \fBnpm-test\fR \- Test a package .SS Synopsis diff --git a/deps/npm/man/man1/npm-token.1 b/deps/npm/man/man1/npm-token.1 index 2ef8c563f1eb30..0a7555c14ec4f4 100644 --- a/deps/npm/man/man1/npm-token.1 +++ b/deps/npm/man/man1/npm-token.1 @@ -1,4 +1,4 @@ -.TH "NPM\-TOKEN" "1" "March 2020" "" "" +.TH "NPM\-TOKEN" "1" "May 2020" "" "" .SH "NAME" \fBnpm-token\fR \- Manage your authentication tokens .SS Synopsis diff --git a/deps/npm/man/man1/npm-uninstall.1 b/deps/npm/man/man1/npm-uninstall.1 index 72172f08c8f1fb..37ed8caf734e38 100644 --- a/deps/npm/man/man1/npm-uninstall.1 +++ b/deps/npm/man/man1/npm-uninstall.1 @@ -1,4 +1,4 @@ -.TH "NPM\-UNINSTALL" "1" "March 2020" "" "" +.TH "NPM\-UNINSTALL" "1" "May 2020" "" "" .SH "NAME" \fBnpm-uninstall\fR \- Remove a package .SS Synopsis diff --git a/deps/npm/man/man1/npm-unpublish.1 b/deps/npm/man/man1/npm-unpublish.1 index 5db95caffc36d5..e776bb047f00dd 100644 --- a/deps/npm/man/man1/npm-unpublish.1 +++ b/deps/npm/man/man1/npm-unpublish.1 @@ -1,4 +1,4 @@ -.TH "NPM\-UNPUBLISH" "1" "March 2020" "" "" +.TH "NPM\-UNPUBLISH" "1" "May 2020" "" "" .SH "NAME" \fBnpm-unpublish\fR \- Remove a package from the registry .SS Synopsis diff --git a/deps/npm/man/man1/npm-update.1 b/deps/npm/man/man1/npm-update.1 index b236b1eaaaa561..2006a973c2040e 100644 --- a/deps/npm/man/man1/npm-update.1 +++ b/deps/npm/man/man1/npm-update.1 @@ -1,4 +1,4 @@ -.TH "NPM\-UPDATE" "1" "March 2020" "" "" +.TH "NPM\-UPDATE" "1" "May 2020" "" "" .SH "NAME" \fBnpm-update\fR \- Update a package .SS Synopsis diff --git a/deps/npm/man/man1/npm-version.1 b/deps/npm/man/man1/npm-version.1 index 22dc7a71ed4b01..57cd4e9f6ff14c 100644 --- a/deps/npm/man/man1/npm-version.1 +++ b/deps/npm/man/man1/npm-version.1 @@ -1,4 +1,4 @@ -.TH "NPM\-VERSION" "1" "March 2020" "" "" +.TH "NPM\-VERSION" "1" "May 2020" "" "" .SH "NAME" \fBnpm-version\fR \- Bump a package version .SS Synopsis diff --git a/deps/npm/man/man1/npm-view.1 b/deps/npm/man/man1/npm-view.1 index 0bed92ababc3dd..a0b97326a48c76 100644 --- a/deps/npm/man/man1/npm-view.1 +++ b/deps/npm/man/man1/npm-view.1 @@ -1,4 +1,4 @@ -.TH "NPM\-VIEW" "1" "March 2020" "" "" +.TH "NPM\-VIEW" "1" "May 2020" "" "" .SH "NAME" \fBnpm-view\fR \- View registry info .SS Synopsis diff --git a/deps/npm/man/man1/npm-whoami.1 b/deps/npm/man/man1/npm-whoami.1 index c581a1f0a4d363..08dc425b269aeb 100644 --- a/deps/npm/man/man1/npm-whoami.1 +++ b/deps/npm/man/man1/npm-whoami.1 @@ -1,4 +1,4 @@ -.TH "NPM\-WHOAMI" "1" "March 2020" "" "" +.TH "NPM\-WHOAMI" "1" "May 2020" "" "" .SH "NAME" \fBnpm-whoami\fR \- Display npm username .SS Synopsis diff --git a/deps/npm/man/man1/npm.1 b/deps/npm/man/man1/npm.1 index a9ea697aea7dc2..fc2e735cc44d66 100644 --- a/deps/npm/man/man1/npm.1 +++ b/deps/npm/man/man1/npm.1 @@ -1,4 +1,4 @@ -.TH "NPM" "1" "March 2020" "" "" +.TH "NPM" "1" "May 2020" "" "" .SH "NAME" \fBnpm\fR \- javascript package manager .SS Synopsis @@ -10,7 +10,7 @@ npm [args] .RE .SS Version .P -6\.14\.4 +6\.14\.5 .SS Description .P npm is the package manager for the Node JavaScript platform\. It puts @@ -47,14 +47,14 @@ on a preinstalled git\. .P If one of the packages npm tries to install is a native node module and requires compiling of C++ Code, npm will use -node\-gyp \fIhttps://github\.com/TooTallNate/node\-gyp\fR for that task\. -For a Unix system, node\-gyp \fIhttps://github\.com/TooTallNate/node\-gyp\fR +node\-gyp \fIhttps://github\.com/nodejs/node\-gyp\fR for that task\. +For a Unix system, node\-gyp \fIhttps://github\.com/nodejs/node\-gyp\fR needs Python, make and a buildchain like GCC\. On Windows, Python and Microsoft Visual Studio C++ are needed\. Python 3 is -not supported by node\-gyp \fIhttps://github\.com/TooTallNate/node\-gyp\fR\|\. +not supported by node\-gyp \fIhttps://github\.com/nodejs/node\-gyp\fR\|\. For more information visit -the node\-gyp repository \fIhttps://github\.com/TooTallNate/node\-gyp\fR and -the node\-gyp Wiki \fIhttps://github\.com/TooTallNate/node\-gyp/wiki\fR\|\. +the node\-gyp repository \fIhttps://github\.com/nodejs/node\-gyp\fR and +the node\-gyp Wiki \fIhttps://github\.com/nodejs/node\-gyp/wiki\fR\|\. .SS Directories .P See npm help \fBfolders\fP to learn about where npm puts stuff\. diff --git a/deps/npm/man/man5/folders.5 b/deps/npm/man/man5/folders.5 index c88bdecd34f1e8..06fcc5032448ca 100644 --- a/deps/npm/man/man5/folders.5 +++ b/deps/npm/man/man5/folders.5 @@ -1,4 +1,4 @@ -.TH "FOLDERS" "5" "March 2020" "" "" +.TH "FOLDERS" "5" "May 2020" "" "" .SH "NAME" \fBfolders\fR \- Folder Structures Used by npm .SS Description diff --git a/deps/npm/man/man5/install.5 b/deps/npm/man/man5/install.5 index 9309aa1f17c006..08b410eddca817 100644 --- a/deps/npm/man/man5/install.5 +++ b/deps/npm/man/man5/install.5 @@ -1,4 +1,4 @@ -.TH "INSTALL" "5" "March 2020" "" "" +.TH "INSTALL" "5" "May 2020" "" "" .SH "NAME" \fBinstall\fR \- Download and Install npm .SS Description diff --git a/deps/npm/man/man5/npmrc.5 b/deps/npm/man/man5/npmrc.5 index bc3f8fdaed0e5b..ed5483983f300a 100644 --- a/deps/npm/man/man5/npmrc.5 +++ b/deps/npm/man/man5/npmrc.5 @@ -1,4 +1,4 @@ -.TH "NPMRC" "5" "March 2020" "" "" +.TH "NPMRC" "5" "May 2020" "" "" .SH "NAME" \fBnpmrc\fR \- The npm config files .SS Description diff --git a/deps/npm/man/man5/package-json.5 b/deps/npm/man/man5/package-json.5 index 13d90854131429..7ebe2dcf4a4918 100644 --- a/deps/npm/man/man5/package-json.5 +++ b/deps/npm/man/man5/package-json.5 @@ -1,4 +1,4 @@ -.TH "PACKAGE\.JSON" "5" "March 2020" "" "" +.TH "PACKAGE\.JSON" "5" "May 2020" "" "" .SH "NAME" \fBpackage.json\fR \- Specifics of npm's package\.json handling .SS Description diff --git a/deps/npm/man/man5/package-lock-json.5 b/deps/npm/man/man5/package-lock-json.5 index 43c6e419367742..5db9bea393f475 100644 --- a/deps/npm/man/man5/package-lock-json.5 +++ b/deps/npm/man/man5/package-lock-json.5 @@ -1,4 +1,4 @@ -.TH "PACKAGE\-LOCK\.JSON" "5" "March 2020" "" "" +.TH "PACKAGE\-LOCK\.JSON" "5" "May 2020" "" "" .SH "NAME" \fBpackage-lock.json\fR \- A manifestation of the manifest .SS Description diff --git a/deps/npm/man/man5/package-locks.5 b/deps/npm/man/man5/package-locks.5 index f610e42ba4ba4a..f7856325abbbe7 100644 --- a/deps/npm/man/man5/package-locks.5 +++ b/deps/npm/man/man5/package-locks.5 @@ -1,4 +1,4 @@ -.TH "PACKAGE\-LOCKS" "5" "March 2020" "" "" +.TH "PACKAGE\-LOCKS" "5" "May 2020" "" "" .SH "NAME" \fBpackage-locks\fR \- An explanation of npm lockfiles .SS Description diff --git a/deps/npm/man/man5/shrinkwrap-json.5 b/deps/npm/man/man5/shrinkwrap-json.5 index e891c84ecff4ee..227c7e87611217 100644 --- a/deps/npm/man/man5/shrinkwrap-json.5 +++ b/deps/npm/man/man5/shrinkwrap-json.5 @@ -1,4 +1,4 @@ -.TH "NPM\-SHRINKWRAP\.JSON" "5" "March 2020" "" "" +.TH "NPM\-SHRINKWRAP\.JSON" "5" "May 2020" "" "" .SH "NAME" \fBnpm-shrinkwrap.json\fR \- A publishable lockfile .SS Description diff --git a/deps/npm/man/man7/config.7 b/deps/npm/man/man7/config.7 index 0f653366b1d287..db95234d49e24b 100644 --- a/deps/npm/man/man7/config.7 +++ b/deps/npm/man/man7/config.7 @@ -1,4 +1,4 @@ -.TH "CONFIG" "7" "March 2020" "" "" +.TH "CONFIG" "7" "May 2020" "" "" .SH "NAME" \fBconfig\fR \- More than you probably want to know about npm configuration .SS Description diff --git a/deps/npm/man/man7/developers.7 b/deps/npm/man/man7/developers.7 index a84548af27c641..942ce4b431a448 100644 --- a/deps/npm/man/man7/developers.7 +++ b/deps/npm/man/man7/developers.7 @@ -1,4 +1,4 @@ -.TH "DEVELOPERS" "7" "March 2020" "" "" +.TH "DEVELOPERS" "7" "May 2020" "" "" .SH "NAME" \fBdevelopers\fR \- Developer Guide .SS Description diff --git a/deps/npm/man/man7/disputes.7 b/deps/npm/man/man7/disputes.7 index a94c70b3d833de..4c5a73a2e57771 100644 --- a/deps/npm/man/man7/disputes.7 +++ b/deps/npm/man/man7/disputes.7 @@ -1,4 +1,4 @@ -.TH "DISPUTES" "7" "March 2020" "" "" +.TH "DISPUTES" "7" "May 2020" "" "" .SH "NAME" \fBdisputes\fR \- Handling Module Name Disputes .P diff --git a/deps/npm/man/man7/orgs.7 b/deps/npm/man/man7/orgs.7 index 418537ead8c219..b32c26c19cb3a0 100644 --- a/deps/npm/man/man7/orgs.7 +++ b/deps/npm/man/man7/orgs.7 @@ -1,4 +1,4 @@ -.TH "ORGS" "7" "March 2020" "" "" +.TH "ORGS" "7" "May 2020" "" "" .SH "NAME" \fBorgs\fR \- Working with Teams & Orgs .SS Description diff --git a/deps/npm/man/man7/registry.7 b/deps/npm/man/man7/registry.7 index f22059121e843b..5de9a3e0968093 100644 --- a/deps/npm/man/man7/registry.7 +++ b/deps/npm/man/man7/registry.7 @@ -1,4 +1,4 @@ -.TH "REGISTRY" "7" "March 2020" "" "" +.TH "REGISTRY" "7" "May 2020" "" "" .SH "NAME" \fBregistry\fR \- The JavaScript Package Registry .SS Description diff --git a/deps/npm/man/man7/removal.7 b/deps/npm/man/man7/removal.7 index 7b7322628f2c65..254a685ad2c24d 100644 --- a/deps/npm/man/man7/removal.7 +++ b/deps/npm/man/man7/removal.7 @@ -1,4 +1,4 @@ -.TH "REMOVAL" "7" "March 2020" "" "" +.TH "REMOVAL" "7" "May 2020" "" "" .SH "NAME" \fBremoval\fR \- Cleaning the Slate .SS Synopsis diff --git a/deps/npm/man/man7/scope.7 b/deps/npm/man/man7/scope.7 index 1884347b8b6ab1..680125cf6d5c54 100644 --- a/deps/npm/man/man7/scope.7 +++ b/deps/npm/man/man7/scope.7 @@ -1,4 +1,4 @@ -.TH "SCOPE" "7" "March 2020" "" "" +.TH "SCOPE" "7" "May 2020" "" "" .SH "NAME" \fBscope\fR \- Scoped packages .SS Description diff --git a/deps/npm/man/man7/scripts.7 b/deps/npm/man/man7/scripts.7 index 17b549b05e7c1c..f507049bc186fb 100644 --- a/deps/npm/man/man7/scripts.7 +++ b/deps/npm/man/man7/scripts.7 @@ -1,4 +1,4 @@ -.TH "SCRIPTS" "7" "March 2020" "" "" +.TH "SCRIPTS" "7" "May 2020" "" "" .SH "NAME" \fBscripts\fR \- How npm handles the "scripts" field .SS Description @@ -194,9 +194,15 @@ executing the scripts\. So, if your package\.json has this: .P .RS 2 .nf -{ "name" : "foo" -, "dependencies" : { "bar" : "0\.1\.x" } -, "scripts": { "start" : "bar \./test" } } +{ + "name" : "foo", + "dependencies" : { + "bar" : "0\.1\.x" + }, + "scripts": { + "start" : "bar \./test" + } +} .fi .RE .P @@ -224,9 +230,15 @@ if the package\.json has this: .P .RS 2 .nf -{ "name" : "foo" -, "config" : { "port" : "8080" } -, "scripts" : { "start" : "node server\.js" } } +{ + "name" : "foo", + "config" : { + "port" : "8080" + }, + "scripts" : { + "start" : "node server\.js" + } +} .fi .RE .P @@ -267,10 +279,11 @@ For example, if your package\.json contains this: .P .RS 2 .nf -{ "scripts" : - { "install" : "scripts/install\.js" - , "postinstall" : "scripts/postinstall\.js" - , "uninstall" : "scripts/uninstall\.js" +{ + "scripts" : { + "install" : "scripts/install\.js", + "postinstall" : "scripts/install\.js", + "uninstall" : "scripts/uninstall\.js" } } .fi @@ -288,10 +301,11 @@ fine: .P .RS 2 .nf -{ "scripts" : - { "preinstall" : "\./configure" - , "install" : "make && make install" - , "test" : "make test" +{ + "scripts" : { + "preinstall" : "\./configure", + "install" : "make && make install", + "test" : "make test" } } .fi diff --git a/deps/npm/man/man7/semver.7 b/deps/npm/man/man7/semver.7 index 419716a83d737a..7e8df25a356581 100644 --- a/deps/npm/man/man7/semver.7 +++ b/deps/npm/man/man7/semver.7 @@ -1,4 +1,4 @@ -.TH "SEMVER" "7" "March 2020" "" "" +.TH "SEMVER" "7" "May 2020" "" "" .SH "NAME" \fBsemver\fR \- The semantic versioner for npm .SH Install diff --git a/deps/npm/node_modules/graceful-fs/graceful-fs.js b/deps/npm/node_modules/graceful-fs/graceful-fs.js index 8c75ee259e0911..de3df47fd55529 100644 --- a/deps/npm/node_modules/graceful-fs/graceful-fs.js +++ b/deps/npm/node_modules/graceful-fs/graceful-fs.js @@ -21,6 +21,14 @@ if (typeof Symbol === 'function' && typeof Symbol.for === 'function') { function noop () {} +function publishQueue(context, queue) { + Object.defineProperty(context, gracefulQueue, { + get: function() { + return queue + } + }) +} + var debug = noop if (util.debuglog) debug = util.debuglog('gfs4') @@ -32,14 +40,10 @@ else if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || '')) } // Once time initialization -if (!global[gracefulQueue]) { +if (!fs[gracefulQueue]) { // This queue can be shared by multiple loaded instances - var queue = [] - Object.defineProperty(global, gracefulQueue, { - get: function() { - return queue - } - }) + var queue = global[gracefulQueue] || [] + publishQueue(fs, queue) // Patch fs.close/closeSync to shared queue version, because we need // to retry() whenever a close happens *anywhere* in the program. @@ -79,12 +83,16 @@ if (!global[gracefulQueue]) { if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || '')) { process.on('exit', function() { - debug(global[gracefulQueue]) - require('assert').equal(global[gracefulQueue].length, 0) + debug(fs[gracefulQueue]) + require('assert').equal(fs[gracefulQueue].length, 0) }) } } +if (!global[gracefulQueue]) { + publishQueue(global, fs[gracefulQueue]); +} + module.exports = patch(clone(fs)) if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs.__patched) { module.exports = patch(fs) @@ -334,11 +342,11 @@ function patch (fs) { function enqueue (elem) { debug('ENQUEUE', elem[0].name, elem[1]) - global[gracefulQueue].push(elem) + fs[gracefulQueue].push(elem) } function retry () { - var elem = global[gracefulQueue].shift() + var elem = fs[gracefulQueue].shift() if (elem) { debug('RETRY', elem[0].name, elem[1]) elem[0].apply(null, elem[1]) diff --git a/deps/npm/node_modules/graceful-fs/package.json b/deps/npm/node_modules/graceful-fs/package.json index 788876e3220739..32518904d97418 100644 --- a/deps/npm/node_modules/graceful-fs/package.json +++ b/deps/npm/node_modules/graceful-fs/package.json @@ -1,19 +1,19 @@ { - "_from": "graceful-fs@4.2.3", - "_id": "graceful-fs@4.2.3", + "_from": "graceful-fs@4.2.4", + "_id": "graceful-fs@4.2.4", "_inBundle": false, - "_integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "_integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", "_location": "/graceful-fs", "_phantomChildren": {}, "_requested": { "type": "version", "registry": true, - "raw": "graceful-fs@4.2.3", + "raw": "graceful-fs@4.2.4", "name": "graceful-fs", "escapedName": "graceful-fs", - "rawSpec": "4.2.3", + "rawSpec": "4.2.4", "saveSpec": null, - "fetchSpec": "4.2.3" + "fetchSpec": "4.2.4" }, "_requiredBy": [ "#USER", @@ -41,10 +41,10 @@ "/test-exclude/load-json-file", "/write-file-atomic" ], - "_resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "_shasum": "4a12ff1b60376ef09862c2093edd908328be8423", - "_spec": "graceful-fs@4.2.3", - "_where": "/Users/mperrotte/npminc/cli", + "_resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "_shasum": "2256bde14d3632958c465ebc96dc467ca07a29fb", + "_spec": "graceful-fs@4.2.4", + "_where": "/Users/ruyadorno/Documents/workspace/cli", "bugs": { "url": "https://github.com/isaacs/node-graceful-fs/issues" }, @@ -98,5 +98,5 @@ "preversion": "npm test", "test": "node test.js | tap -" }, - "version": "4.2.3" + "version": "4.2.4" } diff --git a/deps/npm/node_modules/mkdirp/README.markdown b/deps/npm/node_modules/mkdirp/README.markdown index 3cc13153851162..fc314bfbd662cf 100644 --- a/deps/npm/node_modules/mkdirp/README.markdown +++ b/deps/npm/node_modules/mkdirp/README.markdown @@ -37,7 +37,7 @@ Create a new directory and any necessary subdirectories at `dir` with octal permission string `opts.mode`. If `opts` is a non-object, it will be treated as the `opts.mode`. -If `opts.mode` isn't specified, it defaults to `0777 & (~process.umask())`. +If `opts.mode` isn't specified, it defaults to `0777`. `cb(err, made)` fires with the error or the first directory `made` that had to be created, if any. @@ -52,7 +52,7 @@ Synchronously create a new directory and any necessary subdirectories at `dir` with octal permission string `opts.mode`. If `opts` is a non-object, it will be treated as the `opts.mode`. -If `opts.mode` isn't specified, it defaults to `0777 & (~process.umask())`. +If `opts.mode` isn't specified, it defaults to `0777`. Returns the first directory that had to be created, if any. diff --git a/deps/npm/node_modules/mkdirp/index.js b/deps/npm/node_modules/mkdirp/index.js index 2f1287071fc0d6..468d7cd8df53be 100644 --- a/deps/npm/node_modules/mkdirp/index.js +++ b/deps/npm/node_modules/mkdirp/index.js @@ -17,7 +17,7 @@ function mkdirP (p, opts, f, made) { var xfs = opts.fs || fs; if (mode === undefined) { - mode = _0777 & (~process.umask()); + mode = _0777 } if (!made) made = null; @@ -62,7 +62,7 @@ mkdirP.sync = function sync (p, opts, made) { var xfs = opts.fs || fs; if (mode === undefined) { - mode = _0777 & (~process.umask()); + mode = _0777 } if (!made) made = null; diff --git a/deps/npm/node_modules/mkdirp/package.json b/deps/npm/node_modules/mkdirp/package.json index 5ff5891b2c06d8..af775065f04fae 100644 --- a/deps/npm/node_modules/mkdirp/package.json +++ b/deps/npm/node_modules/mkdirp/package.json @@ -1,19 +1,19 @@ { - "_from": "mkdirp@0.5.4", - "_id": "mkdirp@0.5.4", + "_from": "mkdirp@0.5.5", + "_id": "mkdirp@0.5.5", "_inBundle": false, - "_integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==", + "_integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "_location": "/mkdirp", "_phantomChildren": {}, "_requested": { "type": "version", "registry": true, - "raw": "mkdirp@0.5.4", + "raw": "mkdirp@0.5.5", "name": "mkdirp", "escapedName": "mkdirp", - "rawSpec": "0.5.4", + "rawSpec": "0.5.5", "saveSpec": null, - "fetchSpec": "0.5.4" + "fetchSpec": "0.5.5" }, "_requiredBy": [ "#USER", @@ -32,9 +32,9 @@ "/tar", "/write" ], - "_resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz", - "_shasum": "fd01504a6797ec5c9be81ff43d204961ed64a512", - "_spec": "mkdirp@0.5.4", + "_resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "_shasum": "d91cefd62d1436ca0f41620e251288d420099def", + "_spec": "mkdirp@0.5.5", "_where": "/Users/ruyadorno/Documents/workspace/cli", "author": { "name": "James Halliday", @@ -51,7 +51,7 @@ "dependencies": { "minimist": "^1.2.5" }, - "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "deprecated": false, "description": "Recursively mkdir, like `mkdir -p`", "devDependencies": { "mock-fs": "^3.7.0", @@ -79,5 +79,5 @@ "scripts": { "test": "tap test/*.js" }, - "version": "0.5.4" + "version": "0.5.5" } diff --git a/deps/npm/node_modules/nopt/.npmignore b/deps/npm/node_modules/nopt/.npmignore deleted file mode 100644 index 3c3629e647f5dd..00000000000000 --- a/deps/npm/node_modules/nopt/.npmignore +++ /dev/null @@ -1 +0,0 @@ -node_modules diff --git a/deps/npm/node_modules/nopt/.travis.yml b/deps/npm/node_modules/nopt/.travis.yml deleted file mode 100644 index a1cef591c3cfd0..00000000000000 --- a/deps/npm/node_modules/nopt/.travis.yml +++ /dev/null @@ -1,8 +0,0 @@ -language: node_js -node_js: - - '0.12' - - '4' - - '6' - - '7' -before_install: - - npm install -g npm@latest diff --git a/deps/npm/node_modules/nopt/examples/my-program.js b/deps/npm/node_modules/nopt/examples/my-program.js deleted file mode 100755 index 142447e18e756c..00000000000000 --- a/deps/npm/node_modules/nopt/examples/my-program.js +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env node - -//process.env.DEBUG_NOPT = 1 - -// my-program.js -var nopt = require("../lib/nopt") - , Stream = require("stream").Stream - , path = require("path") - , knownOpts = { "foo" : [String, null] - , "bar" : [Stream, Number] - , "baz" : path - , "bloo" : [ "big", "medium", "small" ] - , "flag" : Boolean - , "pick" : Boolean - } - , shortHands = { "foofoo" : ["--foo", "Mr. Foo"] - , "b7" : ["--bar", "7"] - , "m" : ["--bloo", "medium"] - , "p" : ["--pick"] - , "f" : ["--flag", "true"] - , "g" : ["--flag"] - , "s" : "--flag" - } - // everything is optional. - // knownOpts and shorthands default to {} - // arg list defaults to process.argv - // slice defaults to 2 - , parsed = nopt(knownOpts, shortHands, process.argv, 2) - -console.log("parsed =\n"+ require("util").inspect(parsed)) diff --git a/deps/npm/node_modules/nopt/lib/nopt.js b/deps/npm/node_modules/nopt/lib/nopt.js index 1fb113514f3347..0ec5753d0cb898 100644 --- a/deps/npm/node_modules/nopt/lib/nopt.js +++ b/deps/npm/node_modules/nopt/lib/nopt.js @@ -113,7 +113,12 @@ function clean (data, types, typeDefs) { return d[k] }).filter(function (val) { return val !== remove }) - if (!val.length) delete data[k] + // if we allow Array specifically, then an empty array is how we + // express 'no value here', not null. Allow it. + if (!val.length && type.indexOf(Array) === -1) { + debug('VAL HAS NO LENGTH, DELETE IT', val, k, type.indexOf(Array)) + delete data[k] + } else if (isArray) { debug(isArray, data[k], val) data[k] = val diff --git a/deps/npm/node_modules/nopt/package.json b/deps/npm/node_modules/nopt/package.json index cea3624f4d14e5..1490f6d25d75cf 100644 --- a/deps/npm/node_modules/nopt/package.json +++ b/deps/npm/node_modules/nopt/package.json @@ -1,51 +1,54 @@ { - "_args": [ - [ - "nopt@4.0.1", - "/Users/rebecca/code/npm" - ] - ], - "_from": "nopt@4.0.1", - "_id": "nopt@4.0.1", + "_from": "nopt@4.0.3", + "_id": "nopt@4.0.3", "_inBundle": false, - "_integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "_integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", "_location": "/nopt", "_phantomChildren": {}, "_requested": { "type": "version", "registry": true, - "raw": "nopt@4.0.1", + "raw": "nopt@4.0.3", "name": "nopt", "escapedName": "nopt", - "rawSpec": "4.0.1", + "rawSpec": "4.0.3", "saveSpec": null, - "fetchSpec": "4.0.1" + "fetchSpec": "4.0.3" }, "_requiredBy": [ - "/" + "#USER", + "/", + "/node-gyp" ], - "_resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", - "_spec": "4.0.1", - "_where": "/Users/rebecca/code/npm", + "_resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "_shasum": "a375cad9d02fd921278d954c2254d5aa57e15e48", + "_spec": "nopt@4.0.3", + "_where": "/Users/ruyadorno/Documents/workspace/cli", "author": { "name": "Isaac Z. Schlueter", "email": "i@izs.me", "url": "http://blog.izs.me/" }, "bin": { - "nopt": "./bin/nopt.js" + "nopt": "bin/nopt.js" }, "bugs": { "url": "https://github.com/npm/nopt/issues" }, + "bundleDependencies": false, "dependencies": { "abbrev": "1", "osenv": "^0.1.4" }, + "deprecated": false, "description": "Option parsing for Node, supporting types, shorthands, etc. Used by npm.", "devDependencies": { - "tap": "^8.0.1" + "tap": "^14.10.6" }, + "files": [ + "bin", + "lib" + ], "homepage": "https://github.com/npm/nopt#readme", "license": "ISC", "main": "lib/nopt.js", @@ -55,7 +58,10 @@ "url": "git+https://github.com/npm/nopt.git" }, "scripts": { + "postversion": "npm publish", + "prepublishOnly": "git push origin --follow-tags", + "preversion": "npm test", "test": "tap test/*.js" }, - "version": "4.0.1" + "version": "4.0.3" } diff --git a/deps/npm/node_modules/nopt/test/basic.js b/deps/npm/node_modules/nopt/test/basic.js deleted file mode 100644 index 5c18ac0fc6a319..00000000000000 --- a/deps/npm/node_modules/nopt/test/basic.js +++ /dev/null @@ -1,303 +0,0 @@ -var nopt = require("../") - , test = require('tap').test - , isWin = process.platform === 'win32' - -test("passing a string results in a string", function (t) { - var parsed = nopt({ key: String }, {}, ["--key", "myvalue"], 0) - t.same(parsed.key, "myvalue") - t.end() -}) - -// https://github.com/npm/nopt/issues/31 -test("Empty String results in empty string, not true", function (t) { - var parsed = nopt({ empty: String }, {}, ["--empty"], 0) - t.same(parsed.empty, "") - t.end() -}) - -// https://github.com/npm/nopt/issues/65 -test("Empty String should not swallow next flag", function (t) { - var parsed = nopt({ empty: String, foo: String }, {}, ["--empty", "--foo"], 0) - t.same(parsed.empty, "") - t.same(parsed.foo, "") - t.end() -}) - -// https://github.com/npm/nopt/issues/66 -test("Empty String should not be true when type is single item Array", function (t) { - var parsed = nopt({ 'foo': [String] }, {}, ["--foo"], 0) - t.same(parsed.foo, "") - t.end() -}) - -test("~ path is resolved to " + (isWin ? '%USERPROFILE%' : '$HOME'), function (t) { - var path = require("path") - , the - - if (isWin) { - the = { - key: 'USERPROFILE', - dir: 'C:\\temp', - val: '~\\val' - } - } else { - the = { - key: 'HOME', - dir: '/tmp', - val: '~/val' - } - } - if (!process.env[the.key]) process.env[the.key] = v.dir - var parsed = nopt({key: path}, {}, ["--key=" + the.val], 0) - t.same(parsed.key, path.resolve(process.env[the.key], "val")) - t.end() -}) - -// https://github.com/npm/nopt/issues/24 -test("Unknown options are not parsed as numbers", function (t) { - var parsed = nopt({"parse-me": Number}, null, ['--leave-as-is=1.20', '--parse-me=1.20'], 0) - t.equal(parsed['leave-as-is'], '1.20') - t.equal(parsed['parse-me'], 1.2) - t.end() -}); - -// https://github.com/npm/nopt/issues/48 -test("Check types based on name of type", function (t) { - var parsed = nopt({"parse-me": {name: "Number"}}, null, ['--parse-me=1.20'], 0) - t.equal(parsed['parse-me'], 1.2) - t.end() -}) - - -test("Missing types are not parsed", function (t) { - var parsed = nopt({"parse-me": {}}, null, ['--parse-me=1.20'], 0) - //should only contain argv - t.equal(Object.keys(parsed).length, 1) - t.end() -}) - -test("Types passed without a name are not parsed", function (t) { - var parsed = nopt({"parse-me": {}}, {}, ['--parse-me=1.20'], 0) - //should only contain argv - t.equal(Object.keys(parsed).length, 1) - t.end() -}) - -test("other tests", function (t) { - - var util = require("util") - , Stream = require("stream") - , path = require("path") - , url = require("url") - - , shorthands = - { s : ["--loglevel", "silent"] - , d : ["--loglevel", "info"] - , dd : ["--loglevel", "verbose"] - , ddd : ["--loglevel", "silly"] - , noreg : ["--no-registry"] - , reg : ["--registry"] - , "no-reg" : ["--no-registry"] - , silent : ["--loglevel", "silent"] - , verbose : ["--loglevel", "verbose"] - , h : ["--usage"] - , H : ["--usage"] - , "?" : ["--usage"] - , help : ["--usage"] - , v : ["--version"] - , f : ["--force"] - , desc : ["--description"] - , "no-desc" : ["--no-description"] - , "local" : ["--no-global"] - , l : ["--long"] - , p : ["--parseable"] - , porcelain : ["--parseable"] - , g : ["--global"] - } - - , types = - { aoa: Array - , nullstream: [null, Stream] - , date: Date - , str: String - , browser : String - , cache : path - , color : ["always", Boolean] - , depth : Number - , description : Boolean - , dev : Boolean - , editor : path - , force : Boolean - , global : Boolean - , globalconfig : path - , group : [String, Number] - , gzipbin : String - , logfd : [Number, Stream] - , loglevel : ["silent","win","error","warn","info","verbose","silly"] - , long : Boolean - , "node-version" : [false, String] - , npaturl : url - , npat : Boolean - , "onload-script" : [false, String] - , outfd : [Number, Stream] - , parseable : Boolean - , pre: Boolean - , prefix: path - , proxy : url - , "rebuild-bundle" : Boolean - , registry : url - , searchopts : String - , searchexclude: [null, String] - , shell : path - , t: [Array, String] - , tag : String - , tar : String - , tmp : path - , "unsafe-perm" : Boolean - , usage : Boolean - , user : String - , username : String - , userconfig : path - , version : Boolean - , viewer: path - , _exit : Boolean - , path: path - } - - ; [["-v", {version:true}, []] - ,["---v", {version:true}, []] - ,["ls -s --no-reg connect -d", - {loglevel:"info",registry:null},["ls","connect"]] - ,["ls ---s foo",{loglevel:"silent"},["ls","foo"]] - ,["ls --registry blargle", {}, ["ls"]] - ,["--no-registry", {registry:null}, []] - ,["--no-color true", {color:false}, []] - ,["--no-color false", {color:true}, []] - ,["--no-color", {color:false}, []] - ,["--color false", {color:false}, []] - ,["--color --logfd 7", {logfd:7,color:true}, []] - ,["--color=true", {color:true}, []] - ,["--logfd=10", {logfd:10}, []] - ,["--tmp=/tmp -tar=gtar", {tmp: isWin ? "C:\\tmp" : "/tmp",tar:"gtar"},[]] - ,["--tmp=tmp -tar=gtar", - {tmp:path.resolve(process.cwd(), "tmp"),tar:"gtar"},[]] - ,["--logfd x", {}, []] - ,["a -true -- -no-false", {true:true},["a","-no-false"]] - ,["a -no-false", {false:false},["a"]] - ,["a -no-no-true", {true:true}, ["a"]] - ,["a -no-no-no-false", {false:false}, ["a"]] - ,["---NO-no-No-no-no-no-nO-no-no"+ - "-No-no-no-no-no-no-no-no-no"+ - "-no-no-no-no-NO-NO-no-no-no-no-no-no"+ - "-no-body-can-do-the-boogaloo-like-I-do" - ,{"body-can-do-the-boogaloo-like-I-do":false}, []] - ,["we are -no-strangers-to-love "+ - "--you-know=the-rules --and=so-do-i "+ - "---im-thinking-of=a-full-commitment "+ - "--no-you-would-get-this-from-any-other-guy "+ - "--no-gonna-give-you-up "+ - "-no-gonna-let-you-down=true "+ - "--no-no-gonna-run-around false "+ - "--desert-you=false "+ - "--make-you-cry false "+ - "--no-tell-a-lie "+ - "--no-no-and-hurt-you false" - ,{"strangers-to-love":false - ,"you-know":"the-rules" - ,"and":"so-do-i" - ,"you-would-get-this-from-any-other-guy":false - ,"gonna-give-you-up":false - ,"gonna-let-you-down":false - ,"gonna-run-around":false - ,"desert-you":false - ,"make-you-cry":false - ,"tell-a-lie":false - ,"and-hurt-you":false - },["we", "are"]] - ,["-t one -t two -t three" - ,{t: ["one", "two", "three"]} - ,[]] - ,["-t one -t null -t three four five null" - ,{t: ["one", "null", "three"]} - ,["four", "five", "null"]] - ,["-t foo" - ,{t:["foo"]} - ,[]] - ,["--no-t" - ,{t:["false"]} - ,[]] - ,["-no-no-t" - ,{t:["true"]} - ,[]] - ,["-aoa one -aoa null -aoa 100" - ,{aoa:["one", null, '100']} - ,[]] - ,["-str 100" - ,{str:"100"} - ,[]] - ,["--color always" - ,{color:"always"} - ,[]] - ,["--no-nullstream" - ,{nullstream:null} - ,[]] - ,["--nullstream false" - ,{nullstream:null} - ,[]] - ,["--notadate=2011-01-25" - ,{notadate: "2011-01-25"} - ,[]] - ,["--date 2011-01-25" - ,{date: new Date("2011-01-25")} - ,[]] - ,["-cl 1" - ,{config: true, length: 1} - ,[] - ,{config: Boolean, length: Number, clear: Boolean} - ,{c: "--config", l: "--length"}] - ,["--acount bla" - ,{"acount":true} - ,["bla"] - ,{account: Boolean, credentials: Boolean, options: String} - ,{a:"--account", c:"--credentials",o:"--options"}] - ,["--clear" - ,{clear:true} - ,[] - ,{clear:Boolean,con:Boolean,len:Boolean,exp:Boolean,add:Boolean,rep:Boolean} - ,{c:"--con",l:"--len",e:"--exp",a:"--add",r:"--rep"}] - ,["--file -" - ,{"file":"-"} - ,[] - ,{file:String} - ,{}] - ,["--file -" - ,{"file":true} - ,["-"] - ,{file:Boolean} - ,{}] - ,["--path" - ,{"path":null} - ,[]] - ,["--path ." - ,{"path":process.cwd()} - ,[]] - ].forEach(function (test) { - var argv = test[0].split(/\s+/) - , opts = test[1] - , rem = test[2] - , actual = nopt(test[3] || types, test[4] || shorthands, argv, 0) - , parsed = actual.argv - delete actual.argv - for (var i in opts) { - var e = JSON.stringify(opts[i]) - , a = JSON.stringify(actual[i] === undefined ? null : actual[i]) - if (e && typeof e === "object") { - t.deepEqual(e, a) - } else { - t.equal(e, a) - } - } - t.deepEqual(rem, parsed.remain) - }) - t.end() -}) diff --git a/deps/npm/node_modules/npm-registry-fetch/CHANGELOG.md b/deps/npm/node_modules/npm-registry-fetch/CHANGELOG.md index 3599c6b2fcac1b..75b74eec60144d 100644 --- a/deps/npm/node_modules/npm-registry-fetch/CHANGELOG.md +++ b/deps/npm/node_modules/npm-registry-fetch/CHANGELOG.md @@ -2,6 +2,11 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. + +## [4.0.4](https://github.com/npm/registry-fetch/compare/v4.0.3...v4.0.4) (2020-04-28) + + + ## [4.0.3](https://github.com/npm/registry-fetch/compare/v4.0.2...v4.0.3) (2020-02-13) diff --git a/deps/npm/node_modules/npm-registry-fetch/README.md b/deps/npm/node_modules/npm-registry-fetch/README.md index 80ce64cda78efe..9f9c6d0e808fd2 100644 --- a/deps/npm/node_modules/npm-registry-fetch/README.md +++ b/deps/npm/node_modules/npm-registry-fetch/README.md @@ -581,7 +581,7 @@ See also [`opts.ca`](#opts-ca). ##### `opts.timeout` * Type: Milliseconds -* Default: 30000 (30 seconds) +* Default: 0 (no timeout) Time before a hanging request times out. diff --git a/deps/npm/node_modules/npm-registry-fetch/config.js b/deps/npm/node_modules/npm-registry-fetch/config.js index d7be3f9b38a167..c4e8b687412a58 100644 --- a/deps/npm/node_modules/npm-registry-fetch/config.js +++ b/deps/npm/node_modules/npm-registry-fetch/config.js @@ -76,7 +76,7 @@ module.exports = figgyPudding({ 'spec': {}, 'strict-ssl': {}, 'timeout': { - default: 30 * 1000 + default: 0 }, 'user-agent': { default: `${ diff --git a/deps/npm/node_modules/npm-registry-fetch/package.json b/deps/npm/node_modules/npm-registry-fetch/package.json index ca6c5f90c63527..c1582514e36e1e 100644 --- a/deps/npm/node_modules/npm-registry-fetch/package.json +++ b/deps/npm/node_modules/npm-registry-fetch/package.json @@ -1,19 +1,19 @@ { - "_from": "npm-registry-fetch@4.0.3", - "_id": "npm-registry-fetch@4.0.3", + "_from": "npm-registry-fetch@4.0.4", + "_id": "npm-registry-fetch@4.0.4", "_inBundle": false, - "_integrity": "sha512-WGvUx0lkKFhu9MbiGFuT9nG2NpfQ+4dCJwRwwtK2HK5izJEvwDxMeUyqbuMS7N/OkpVCqDorV6rO5E4V9F8lJw==", + "_integrity": "sha512-6jb34hX/iYNQebqWUHtU8YF6Cjb1H6ouTFPClYsyiW6lpFkljTpdeftm53rRojtja1rKAvKNIIiTS5Sjpw4wsA==", "_location": "/npm-registry-fetch", "_phantomChildren": {}, "_requested": { "type": "version", "registry": true, - "raw": "npm-registry-fetch@4.0.3", + "raw": "npm-registry-fetch@4.0.4", "name": "npm-registry-fetch", "escapedName": "npm-registry-fetch", - "rawSpec": "4.0.3", + "rawSpec": "4.0.4", "saveSpec": null, - "fetchSpec": "4.0.3" + "fetchSpec": "4.0.4" }, "_requiredBy": [ "#USER", @@ -28,10 +28,10 @@ "/npm-profile", "/pacote" ], - "_resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-4.0.3.tgz", - "_shasum": "3c2179e39e04f9348b1c2979545951d36bee8766", - "_spec": "npm-registry-fetch@4.0.3", - "_where": "/Users/darcyclarke/Documents/Repos/npm/cli", + "_resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-4.0.4.tgz", + "_shasum": "2da1ecf3f43d419d96abf313664291a4623d3ea5", + "_spec": "npm-registry-fetch@4.0.4", + "_where": "/Users/ruyadorno/Documents/workspace/cli", "author": { "name": "Kat Marchán", "email": "kzm@sykosomatic.org" @@ -102,5 +102,5 @@ "update-coc": "weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'", "update-contrib": "weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'" }, - "version": "4.0.3" + "version": "4.0.4" } diff --git a/deps/npm/package.json b/deps/npm/package.json index d367dc98b5982f..bfbed9ea0bab43 100644 --- a/deps/npm/package.json +++ b/deps/npm/package.json @@ -1,5 +1,5 @@ { - "version": "6.14.4", + "version": "6.14.5", "name": "npm", "description": "a package manager for JavaScript", "keywords": [ @@ -61,7 +61,7 @@ "fs-write-stream-atomic": "~1.0.10", "gentle-fs": "^2.3.0", "glob": "^7.1.6", - "graceful-fs": "^4.2.3", + "graceful-fs": "^4.2.4", "has-unicode": "~2.0.1", "hosted-git-info": "^2.8.8", "iferr": "^1.0.2", @@ -91,10 +91,10 @@ "lru-cache": "^5.1.1", "meant": "~1.0.1", "mississippi": "^3.0.0", - "mkdirp": "^0.5.4", + "mkdirp": "^0.5.5", "move-concurrently": "^1.0.1", "node-gyp": "^5.1.0", - "nopt": "~4.0.1", + "nopt": "^4.0.3", "normalize-package-data": "^2.5.0", "npm-audit-report": "^1.3.2", "npm-cache-filename": "~1.0.2", @@ -104,7 +104,7 @@ "npm-packlist": "^1.4.8", "npm-pick-manifest": "^3.0.2", "npm-profile": "^4.0.4", - "npm-registry-fetch": "^4.0.3", + "npm-registry-fetch": "^4.0.4", "npm-user-validate": "~1.0.0", "npmlog": "~4.1.2", "once": "~1.4.0", diff --git a/deps/npm/scripts/release.sh b/deps/npm/scripts/release.sh index 31fb6fa1941418..75d2115aadf83a 100644 --- a/deps/npm/scripts/release.sh +++ b/deps/npm/scripts/release.sh @@ -7,6 +7,8 @@ unset CDPATH set -e rm -rf release *.tgz || true +rm node_modules/node-gyp/gyp/pylib/gyp/*.pyc || true +rm node_modules/node-gyp/gyp/pylib/gyp/generator/*.pyc || true mkdir release node ./bin/npm-cli.js pack --loglevel error >/dev/null mv *.tgz release diff --git a/deps/npm/test/tap/install-dep-classification.js b/deps/npm/test/tap/install-dep-classification.js index 257fc99fc123ff..1c9995cedc8a04 100644 --- a/deps/npm/test/tap/install-dep-classification.js +++ b/deps/npm/test/tap/install-dep-classification.js @@ -126,7 +126,7 @@ test('optional dependency identification', function (t) { optional: true }, example: { - version: '1.0.0', + version: 'file:../example-1.0.0.tgz', optional: true } } @@ -150,7 +150,7 @@ test('development dependency identification', function (t) { dev: true }, example: { - version: '1.0.0', + version: 'file:../example-1.0.0.tgz', dev: true } } @@ -173,7 +173,7 @@ test('default dependency identification', function (t) { optional: true }, example: { - version: '1.0.0', + version: 'file:../example-1.0.0.tgz', optional: true } } diff --git a/doc/api/async_hooks.md b/doc/api/async_hooks.md index 0b1b22c82996f4..1534ca853611f9 100644 --- a/doc/api/async_hooks.md +++ b/doc/api/async_hooks.md @@ -68,7 +68,7 @@ function before(asyncId) { } // After is called just after the resource's callback has finished. function after(asyncId) { } -// Destroy is called when an AsyncWrap instance is destroyed. +// Destroy is called when the resource is destroyed. function destroy(asyncId) { } // promiseResolve is called only for promise resources, when the @@ -306,11 +306,6 @@ currently not considered public, but using the Embedder API, users can provide and document their own resource objects. For example, such a resource object could contain the SQL query being executed. -In the case of Promises, the `resource` object will have an -`isChainedPromise` property, set to `true` if the promise has a parent promise, -and `false` otherwise. For example, in the case of `b = a.then(handler)`, `a` is -considered a parent `Promise` of `b`. Here, `b` is considered a chained promise. - In some cases the resource object is reused for performance reasons, it is thus not safe to use it as a key in a `WeakMap` or add properties to it. @@ -635,7 +630,7 @@ see the details of the V8 [PromiseHooks][] API. Library developers that handle their own asynchronous resources performing tasks like I/O, connection pooling, or managing callback queues may use the -`AsyncWrap` JavaScript API so that all the appropriate callbacks are called. +`AsyncResource` JavaScript API so that all the appropriate callbacks are called. ### Class: `AsyncResource` @@ -1085,6 +1080,21 @@ In this example, the store is only available in the callback function and the functions called by `foo`. Outside of `run`, calling `getStore` will return `undefined`. +### Troubleshooting + +In most cases your application or library code should have no issues with +`AsyncLocalStorage`. But in rare cases you may face situations when the +current store is lost in one of asynchronous operations. Then you should +consider the following options. + +If your code is callback-based, it is enough to promisify it with +[`util.promisify()`][], so it starts working with native promises. + +If you need to keep using callback-based API, or your code assumes +a custom thenable implementation, you should use [`AsyncResource`][] class +to associate the asynchronous operation with the correct execution context. + +[`AsyncResource`]: #async_hooks_class_asyncresource [`after` callback]: #async_hooks_after_asyncid [`before` callback]: #async_hooks_before_asyncid [`destroy` callback]: #async_hooks_destroy_asyncid @@ -1094,3 +1104,4 @@ functions called by `foo`. Outside of `run`, calling `getStore` will return [PromiseHooks]: https://docs.google.com/document/d/1rda3yKGHimKIhg5YeoAmCOtyURgsbTH_qaYR79FELlk/edit [`Worker`]: worker_threads.html#worker_threads_class_worker [promise execution tracking]: #async_hooks_promise_execution_tracking +[`util.promisify()`]: util.html#util_util_promisify_original diff --git a/doc/api/buffer.md b/doc/api/buffer.md index 52e86430ede831..c32060563faa49 100644 --- a/doc/api/buffer.md +++ b/doc/api/buffer.md @@ -569,7 +569,7 @@ Array entries outside that range will be truncated to fit into it. const buf = Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]); ``` -A `TypeError` will be thrown if `array` is not an `Array` or other type +A `TypeError` will be thrown if `array` is not an `Array` or another type appropriate for `Buffer.from()` variants. `Buffer.from(array)` and [`Buffer.from(string)`][] may also use the internal @@ -623,7 +623,8 @@ console.log(buf.length); ``` A `TypeError` will be thrown if `arrayBuffer` is not an [`ArrayBuffer`][] or a -[`SharedArrayBuffer`][] or other type appropriate for `Buffer.from()` variants. +[`SharedArrayBuffer`][] or another type appropriate for `Buffer.from()` +variants. ### Class Method: `Buffer.from(buffer)` + +Print short summaries of calls to [`Atomics.wait()`][] to stderr. +The output could look like this: + +```text +(node:15701) [Thread 0] Atomics.wait(
+ 0, 1, inf) started +(node:15701) [Thread 0] Atomics.wait(
+ 0, 1, inf) did not wait because the values mismatched +(node:15701) [Thread 0] Atomics.wait(
+ 0, 0, 10) started +(node:15701) [Thread 0] Atomics.wait(
+ 0, 0, 10) timed out +(node:15701) [Thread 0] Atomics.wait(
+ 4, 0, inf) started +(node:15701) [Thread 1] Atomics.wait(
+ 4, -1, inf) started +(node:15701) [Thread 0] Atomics.wait(
+ 4, 0, inf) was woken up by another thread +(node:15701) [Thread 1] Atomics.wait(
+ 4, -1, inf) was woken up by another thread +``` + +The fields here correspond to: + +* The thread id as given by [`worker_threads.threadId`][] +* The base address of the `SharedArrayBuffer` in question, as well as the + byte offset corresponding to the index passed to `Atomics.wait()` +* The expected value that was passed to `Atomics.wait()` +* The timeout passed to `Atomics.wait` + ### `--trace-deprecation` + +Type: Documentation-only (supports [`--pending-deprecation`][]) + +The `repl` module exported the input and output stream twice. Use `.input` +instead of `.inputStream` and `.output` instead of `.outputStream`. + + +### DEP0142: `repl._builtinLibs` + + +Type: Documentation-only + +The `repl` module exports a `_builtinLibs` property that contains an array with +native modules. It was incomplete so far and instead it's better to rely upon +`require('module').builtinModules`. + [`--pending-deprecation`]: cli.html#cli_pending_deprecation [`--throw-deprecation`]: cli.html#cli_throw_deprecation [`Buffer.allocUnsafeSlow(size)`]: buffer.html#buffer_class_method_buffer_allocunsafeslow_size diff --git a/doc/api/errors.md b/doc/api/errors.md index 172eadf7686794..1cf926c84be4a2 100644 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -855,6 +855,15 @@ An unknown Diffie-Hellman group name was given. See The [`fs.Dir`][] was previously closed. + +### `ERR_DIR_CONCURRENT_OPERATION` + + +A synchronous read or close call was attempted on an [`fs.Dir`][] which has +ongoing asynchronous operations. + ### `ERR_DNS_SET_SERVERS_FAILED` @@ -889,6 +898,11 @@ provided. Encoding provided to `TextDecoder()` API was not one of the [WHATWG Supported Encodings][]. + +### `ERR_EVAL_ESM_CANNOT_PRINT` + +`--print` cannot be used with ESM input. + ### `ERR_EXECUTION_ENVIRONMENT_NOT_AVAILABLE` @@ -2031,6 +2045,20 @@ An attempt was made to load a module with an unknown or unsupported format. An invalid or unknown process signal was passed to an API expecting a valid signal (such as [`subprocess.kill()`][]). + +### `ERR_UNSUPPORTED_DIR_IMPORT` + +`import` a directory URL is unsupported. Instead, you can +[self-reference a package using its name][] and [define a custom subpath][] in +the `"exports"` field of the `package.json` file. + + +```js +import './'; // unsupported +import './index.js'; // supported +import 'package-name'; // supported +``` + ### `ERR_UNSUPPORTED_ESM_URL_SCHEME` @@ -2099,6 +2127,11 @@ meaning of the error depends on the specific function. The WASI instance has already started. + +### `ERR_WASI_NOT_STARTED` + +The WASI instance has not been started. + ### `ERR_WORKER_INIT_FAILED` @@ -2585,3 +2618,5 @@ such as `process.stdout.on('data')`. [Subresource Integrity specification]: https://www.w3.org/TR/SRI/#the-integrity-attribute [try-catch]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch [vm]: vm.html +[self-reference a package using its name]: esm.html#esm_self_referencing_a_package_using_its_name +[define a custom subpath]: esm.html#esm_subpath_exports diff --git a/doc/api/esm.md b/doc/api/esm.md index 5047600f988f66..e5c957d03ce6a0 100644 --- a/doc/api/esm.md +++ b/doc/api/esm.md @@ -13,6 +13,27 @@ ECMAScript modules are [the official standard format][] to package JavaScript code for reuse. Modules are defined using a variety of [`import`][] and [`export`][] statements. +The following example of an ES module exports a function: + +```js +// addTwo.mjs +function addTwo(num) { + return num + 2; +} + +export { addTwo }; +``` + +The following example of an ES module imports the function from `addTwo.mjs`: + +```js +// app.mjs +import { addTwo } from './addTwo.mjs'; + +// Prints: 6 +console.log(addTwo(4)); +``` + Node.js fully supports ECMAScript modules as they are currently specified and provides limited interoperability between them and the existing module format, [CommonJS][]. @@ -36,8 +57,8 @@ initial input, or when referenced by `import` statements within ES module code: * Files ending in `.js` when the nearest parent `package.json` file contains a top-level field `"type"` with a value of `"module"`. -* Strings passed in as an argument to `--eval` or `--print`, or piped to - `node` via `STDIN`, with the flag `--input-type=module`. +* Strings passed in as an argument to `--eval`, or piped to `node` via `STDIN`, + with the flag `--input-type=module`. Node.js will treat as CommonJS all other forms of input, such as `.js` files where the nearest parent `package.json` file contains no top-level `"type"` @@ -52,8 +73,8 @@ or when referenced by `import` statements within ES module code: * Files ending in `.js` when the nearest parent `package.json` file contains a top-level field `"type"` with a value of `"commonjs"`. -* Strings passed in as an argument to `--eval` or `--print`, or piped to - `node` via `STDIN`, with the flag `--input-type=commonjs`. +* Strings passed in as an argument to `--eval` or `--print`, or piped to `node` + via `STDIN`, with the flag `--input-type=commonjs`. ### `package.json` `"type"` field @@ -159,9 +180,9 @@ package scope: ### `--input-type` flag -Strings passed in as an argument to `--eval` or `--print` (or `-e` or `-p`), or -piped to `node` via `STDIN`, will be treated as ES modules when the -`--input-type=module` flag is set. +Strings passed in as an argument to `--eval` (or `-e`), or piped to `node` via +`STDIN`, will be treated as ES modules when the `--input-type=module` flag is +set. ```sh node --input-type=module --eval "import { sep } from 'path'; console.log(sep);" @@ -183,25 +204,75 @@ versions of Node.js, but its capabilities are limited: it only defines the main entry point of the package. The `"exports"` field provides an alternative to `"main"` where the package -main entry point can be defined while also encapsulating the package, preventing -any other entry points besides those defined in `"exports"`. If package entry -points are defined in both `"main"` and `"exports"`, the latter takes precedence -in versions of Node.js that support `"exports"`. [Conditional Exports][] can -also be used within `"exports"` to define different package entry points per -environment, including whether the package is referenced via `require` or via -`import`. +main entry point can be defined while also encapsulating the package, +**preventing any other entry points besides those defined in `"exports"`**. +This encapsulation allows module authors to define a public interface for +their package. If both `"exports"` and `"main"` are defined, the `"exports"` field takes -precedence over `"main"`. +precedence over `"main"`. `"exports"` are not specific to ES modules or +CommonJS; `"main"` will be overridden by `"exports"` if it exists. As such +`"main"` cannot be used as a fallback for CommonJS but it can be used as a +fallback for legacy versions of Node.js that do not support the `"exports"` +field. + +[Conditional Exports][] can be used within `"exports"` to define different +package entry points per environment, including whether the package is +referenced via `require` or via `import`. For more information about supporting +both CommonJS and ES Modules in a single package please consult +[the dual CommonJS/ES module packages section][]. -Both `"main"` and `"exports"` entry points are not specific to ES modules or -CommonJS; `"main"` will be overridden by `"exports"` in a `require` so it is -not a CommonJS fallback. +**Warning**: Introducing the `"exports"` field prevents consumers of a package +from using any entry points that are not defined, including the `package.json` +(e.g. `require('your-package/package.json')`. **This will likely be a breaking +change.** -This is important with regard to `require`, since `require` of ES module files -throws an error in all versions of Node.js. To create a package that works both -in modern Node.js via `import` and `require` and also legacy Node.js versions, -see [the dual CommonJS/ES module packages section][]. +To make the introduction of `"exports"` non-breaking, ensure that every +previously supported entry point is exported. It is best to explicitly specify +entry points so that the package’s public API is well-defined. For example, +a project that previous exported `main`, `lib`, +`feature`, and the `package.json` could use the following `package.exports`: + +```json +{ + "name": "my-mod", + "exports": { + ".": "./lib/index.js", + "./lib": "./lib/index.js", + "./lib/index": "./lib/index.js", + "./lib/index.js": "./lib/index.js", + "./feature": "./feature/index.js", + "./feature/index.js": "./feature/index.js", + "./package.json": "./package.json" + } +} +``` + +Alternatively a project could choose to export entire folders: + +```json +{ + "name": "my-mod", + "exports": { + ".": "./lib/index.js", + "./lib": "./lib/index.js", + "./lib/": "./lib/", + "./feature": "./feature/index.js", + "./feature/": "./feature/", + "./package.json": "./package.json" + } +} +``` + +As a last resort, package encapsulation can be disabled entirely by creating an +export for the root of the package `"./": "./"`. This will expose every file in +the package at the cost of disabling the encapsulation and potential tooling +benefits this provides. As the ES Module loader in Node.js enforces the use of +[the full specifier path][], exporting the root rather than being explicit +about entry is less expressive than either of the prior examples. Not only +will encapsulation be lost but module consumers will be unable to +`import feature from 'my-mod/feature'` as they will need to provide the full +path `import feature from 'my-mod/feature/index.js`. #### Main Entry Point Export @@ -1026,6 +1097,32 @@ node --experimental-wasm-modules index.mjs would provide the exports interface for the instantiation of `module.wasm`. +## Experimental Top-Level `await` + +When the `--experimental-top-level-await` flag is provided, `await` may be used +in the top level (outside of async functions) within modules. This implements +the [ECMAScript Top-Level `await` proposal][]. + +Assuming an `a.mjs` with + + +```js +export const five = await Promise.resolve(5); +``` + +And a `b.mjs` with + +```js +import { five } from './a.mjs'; + +console.log(five); // Logs `5` +``` + +```bash +node b.mjs # fails +node --experimental-top-level-await b.mjs # works +``` + ## Experimental Loaders **Note: This API is currently being redesigned and will still change.** @@ -1506,8 +1603,9 @@ The resolver can throw the following errors: > 1. If _resolvedURL_ contains any percent encodings of _"/"_ or _"\\"_ (_"%2f"_ > and _"%5C"_ respectively), then > 1. Throw an _Invalid Module Specifier_ error. -> 1. If _resolvedURL_ does not end with a trailing _"/"_ and the file at -> _resolvedURL_ does not exist, then +> 1. If the file at _resolvedURL_ is a directory, then +> 1. Throw an _Unsupported Directory Import_ error. +> 1. If the file at _resolvedURL_ does not exist, then > 1. Throw a _Module Not Found_ error. > 1. Set _resolvedURL_ to the real path of _resolvedURL_. > 1. Let _format_ be the result of **ESM_FORMAT**(_resolvedURL_). @@ -1729,6 +1827,7 @@ success! [Conditional Exports]: #esm_conditional_exports [Dynamic `import()`]: https://wiki.developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Dynamic_Imports [ECMAScript-modules implementation]: https://github.com/nodejs/modules/blob/master/doc/plan-for-new-modules-implementation.md +[ECMAScript Top-Level `await` proposal]: https://github.com/tc39/proposal-top-level-await/ [ES Module Integration Proposal for Web Assembly]: https://github.com/webassembly/esm-integration [Node.js EP for ES Modules]: https://github.com/nodejs/node-eps/blob/master/002-es-modules.md [Terminology]: #esm_terminology @@ -1746,6 +1845,7 @@ success! [dynamic instantiate hook]: #esm_code_dynamicinstantiate_code_hook [import an ES or CommonJS module for its side effects only]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Import_a_module_for_its_side_effects_only [special scheme]: https://url.spec.whatwg.org/#special-scheme +[the full specifier path]: #esm_mandatory_file_extensions [the official standard format]: https://tc39.github.io/ecma262/#sec-modules [the dual CommonJS/ES module packages section]: #esm_dual_commonjs_es_module_packages [transpiler loader example]: #esm_transpiler_loader diff --git a/doc/api/fs.md b/doc/api/fs.md index 4291e120eeadf4..2fc687d6aad04c 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -579,6 +579,72 @@ added: v0.5.8 Stop watching for changes on the given `fs.FSWatcher`. Once stopped, the `fs.FSWatcher` object is no longer usable. +### `watcher.ref()` + + +* Returns: {fs.FSWatcher} + +When called, requests that the Node.js event loop *not* exit so long as the +`FSWatcher` is active. Calling `watcher.ref()` multiple times will have +no effect. + +By default, all `FSWatcher` objects are "ref'ed", making it normally +unnecessary to call `watcher.ref()` unless `watcher.unref()` had been +called previously. + +### `watcher.unref()` + + +* Returns: {fs.FSWatcher} + +When called, the active `FSWatcher` object will not require the Node.js +event loop to remain active. If there is no other activity keeping the +event loop running, the process may exit before the `FSWatcher` object's +callback is invoked. Calling `watcher.unref()` multiple times will have +no effect. + +## Class: `fs.StatWatcher` + + +* Extends {EventEmitter} + +A successful call to `fs.watchFile()` method will return a new `fs.StatWatcher` +object. + +### `watcher.ref()` + + +* Returns: {fs.StatWatcher} + +When called, requests that the Node.js event loop *not* exit so long as the +`StatWatcher` is active. Calling `watcher.ref()` multiple times will have +no effect. + +By default, all `StatWatcher` objects are "ref'ed", making it normally +unnecessary to call `watcher.ref()` unless `watcher.unref()` had been +called previously. + +### `watcher.unref()` + + +* Returns: {fs.StatWatcher} + +When called, the active `StatWatcher` object will not require the Node.js +event loop to remain active. If there is no other activity keeping the +event loop running, the process may exit before the `StatWatcher` object's +callback is invoked. Calling `watcher.unref()` multiple times will have +no effect. + ## Class: `fs.ReadStream` + +* `name` {string} + +Performs the low-level validations on the provided `name` that are done when +`res.setHeader(name, value)` is called. + +Passing illegal value as `name` will result in a [`TypeError`][] being thrown, +identified by `code: 'ERR_INVALID_HTTP_TOKEN'`. + +It is not necessary to use this method before passing headers to an HTTP request +or response. The HTTP module will automatically validate such headers. +Examples: + +Example: +```js +const { validateHeaderName } = require('http'); + +try { + validateHeaderName(''); +} catch (err) { + err instanceof TypeError; // --> true + err.code; // --> 'ERR_INVALID_HTTP_TOKEN' + err.message; // --> 'Header name must be a valid HTTP token [""]' +} +``` + +## `http.validateHeaderValue(name, value)` + + +* `name` {string} +* `value` {any} + +Performs the low-level validations on the provided `value` that are done when +`res.setHeader(name, value)` is called. + +Passing illegal value as `value` will result in a [`TypeError`][] being thrown. +* Undefined value error is identified by `code: 'ERR_HTTP_INVALID_HEADER_VALUE'`. +* Invalid value character error is identified by `code: 'ERR_INVALID_CHAR'`. + +It is not necessary to use this method before passing headers to an HTTP request +or response. The HTTP module will automatically validate such headers. + +Examples: + +```js +const { validateHeaderValue } = require('http'); + +try { + validateHeaderValue('x-my-header', undefined); +} catch (err) { + err instanceof TypeError; // --> true + err.code === 'ERR_HTTP_INVALID_HEADER_VALUE'; // --> true + err.message; // --> 'Invalid value "undefined" for header "x-my-header"' +} + +try { + validateHeaderValue('x-my-header', 'oʊmɪɡə'); +} catch (err) { + err instanceof TypeError; // --> true + err.code === 'ERR_INVALID_CHAR'; // --> true + err.message; // --> 'Invalid character in header content ["x-my-header"]' +} +``` + [`--insecure-http-parser`]: cli.html#cli_insecure_http_parser [`--max-http-header-size`]: cli.html#cli_max_http_header_size_size [`'checkContinue'`]: #http_event_checkcontinue diff --git a/doc/api/http2.md b/doc/api/http2.md index 6f3b70be3a03f4..5f130b02e99a36 100644 --- a/doc/api/http2.md +++ b/doc/api/http2.md @@ -3114,7 +3114,7 @@ changes: description: This method now returns a reference to `ServerResponse`. --> -* `data` {string|Buffer} +* `data` {string|Buffer|Uint8Array} * `encoding` {string} * `callback` {Function} * Returns: {this} @@ -3396,7 +3396,7 @@ does not indicate whether the data has been flushed, for this use added: v8.4.0 --> -* `chunk` {string|Buffer} +* `chunk` {string|Buffer|Uint8Array} * `encoding` {string} * `callback` {Function} * Returns: {boolean} diff --git a/doc/api/n-api.md b/doc/api/n-api.md index 5552aaf57bfcad..2758c451ebaf6e 100644 --- a/doc/api/n-api.md +++ b/doc/api/n-api.md @@ -369,7 +369,7 @@ Native addons may need to allocate global state of which they make use during their entire life cycle such that the state must be unique to each instance of the addon. -To this env, N-API provides a way to allocate data such that its life cycle is +To this end, N-API provides a way to allocate data such that its life cycle is tied to the life cycle of the Agent. ### napi_set_instance_data @@ -4672,8 +4672,13 @@ napi_status napi_async_init(napi_env env, ``` * `[in] env`: The environment that the API is invoked under. -* `[in] async_resource`: An optional object associated with the async work +* `[in] async_resource`: Object associated with the async work that will be passed to possible `async_hooks` [`init` hooks][]. + In order to retain ABI compatibility with previous versions, + passing `NULL` for `async_resource` will not result in an error, however, + this will result incorrect operation of async hooks for the + napi_async_context created. Potential issues include + loss of async context when using the AsyncLocalStorage API. * `[in] async_resource_name`: Identifier for the kind of resource that is being provided for diagnostic information exposed by the `async_hooks` API. diff --git a/doc/api/net.md b/doc/api/net.md index 28842d0abe9b90..3e16d4a638f330 100644 --- a/doc/api/net.md +++ b/doc/api/net.md @@ -600,6 +600,10 @@ the error passed to the [`'error'`][] listener. The last parameter `connectListener`, if supplied, will be added as a listener for the [`'connect'`][] event **once**. +This function should only be used for reconnecting a socket after +`'close'` has been emitted or otherwise it may lead to undefined +behavior. + #### `socket.connect(options[, connectListener])` * `code` {string} The body of the function to compile. @@ -833,16 +830,6 @@ changes: * `contextExtensions` {Object[]} An array containing a collection of context extensions (objects wrapping the current scope) to be applied while compiling. **Default:** `[]`. - * `importModuleDynamically` {Function} Called during evaluation of this module - when `import()` is called. If this option is not specified, calls to - `import()` will reject with [`ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING`][]. - This option is part of the experimental modules API, and should not be - considered stable. - * `specifier` {string} specifier passed to `import()` - * `function` {Function} - * Returns: {Module Namespace Object|vm.Module} Returning a `vm.Module` is - recommended in order to take advantage of error tracking, and to avoid - issues with namespaces that contain `then` function exports. * Returns: {Function} Compiles the given code into the provided context (if no context is @@ -889,7 +876,6 @@ properties but also having the built-in objects and functions any standard will remain unchanged. ```js -const util = require('util'); const vm = require('vm'); global.globalVar = 3; @@ -994,7 +980,6 @@ The following example compiles and executes different scripts using a single [contextified][] object: ```js -const util = require('util'); const vm = require('vm'); const contextObject = { globalVar: 1 }; @@ -1090,7 +1075,6 @@ The following example compiles and executes code that increments a global variable and sets a new one. These globals are contained in the `contextObject`. ```js -const util = require('util'); const vm = require('vm'); const contextObject = { diff --git a/doc/api/worker_threads.md b/doc/api/worker_threads.md index d70b63bd98558c..a9e6b2af2171b3 100644 --- a/doc/api/worker_threads.md +++ b/doc/api/worker_threads.md @@ -396,6 +396,51 @@ posting without having side effects. For more information on the serialization and deserialization mechanisms behind this API, see the [serialization API of the `v8` module][v8.serdes]. +#### Considerations when transferring TypedArrays and Buffers + +All `TypedArray` and `Buffer` instances are views over an underlying +`ArrayBuffer`. That is, it is the `ArrayBuffer` that actually stores +the raw data while the `TypedArray` and `Buffer` objects provide a +way of viewing and manipulating the data. It is possible and common +for multiple views to be created over the same `ArrayBuffer` instance. +Great care must be taken when using a transfer list to transfer an +`ArrayBuffer` as doing so will cause all `TypedArray` and `Buffer` +instances that share that same `ArrayBuffer` to become unusable. + +```js +const ab = new ArrayBuffer(10); + +const u1 = new Uint8Array(ab); +const u2 = new Uint16Array(ab); + +console.log(u2.length); // prints 5 + +port.postMessage(u1, [u1.buffer]); + +console.log(u2.length); // prints 0 +``` + +For `Buffer` instances, specifically, whether the underlying +`ArrayBuffer` can be transferred or cloned depends entirely on how +instances were created, which often cannot be reliably determined. + +Depending on how a `Buffer` instance was created, it may or may +not own its underlying `ArrayBuffer`. An `ArrayBuffer` must not +be transferred unless it is known that the `Buffer` instance +owns it. In particular, for `Buffer`s created from the internal +`Buffer` pool (using, for instance `Buffer.from()` or `Buffer.alloc()`), +transferring them is not possible and they will always be cloned, +which sends a copy of the entire `Buffer` pool. +This behavior may come with unintended higher memory +usage and possible security concerns. + +See [`Buffer.allocUnsafe()`][] for more details on `Buffer` pooling. + +The `ArrayBuffer`s for `Buffer` instances created using +`Buffer.alloc()` or `Buffer.allocUnsafeSlow()` can always be +transferred but doing so will render all other existing views of +those `ArrayBuffer`s unusable. + ### `port.ref()` + @@ -9,6 +10,7 @@
+14.3.0
14.2.0
14.1.0
14.0.0
@@ -32,6 +34,142 @@ * [io.js](CHANGELOG_IOJS.md) * [Archive](CHANGELOG_ARCHIVE.md) + +## 2020-05-19, Version 14.3.0 (Current), @codebytere + +### Notable Changes + +#### REPL previews improvements with autocompletion + +The output preview is changed to generate previews for autocompleted input +instead of the actual input. + +![image](https://user-images.githubusercontent.com/8822573/82209841-4259e180-990e-11ea-93d7-0ea4b3bfc76f.png) + +Pressing `` during a preview is now going to evaluate the whole string +including the autocompleted part. Pressing `` cancels that behavior. + +#### Support for Top-Level Await + +It's now possible to use the await keyword outside of async functions. + +#### Other Notable Changes + +* [[`7aa581f4ff`](https://github.com/nodejs/node/commit/7aa581f4ff)] - **(SEMVER-MINOR)** **repl**: deprecate repl.\_builtinLibs (Ruben Bridgewater) [#33294](https://github.com/nodejs/node/pull/33294) +* [[`db7bb941a3`](https://github.com/nodejs/node/commit/db7bb941a3)] - **(SEMVER-MINOR)** **repl**: deprecate repl.inputStream and repl.outputStream (Ruben Bridgewater) [#33294](https://github.com/nodejs/node/pull/33294) +* [[`2dc5db8c07`](https://github.com/nodejs/node/commit/2dc5db8c07)] - **(SEMVER-MINOR)** **cli**: add `--trace-atomics-wait` flag (Anna Henningsen) [#33292](https://github.com/nodejs/node/pull/33292) +* [[`6257cf256e`](https://github.com/nodejs/node/commit/6257cf256e)] - **(SEMVER-MINOR)** **repl**: improve repl autocompletion for require calls (Ruben Bridgewater) [#33282](https://github.com/nodejs/node/pull/33282) +* [[`d33dcf1d5f`](https://github.com/nodejs/node/commit/d33dcf1d5f)] - **(SEMVER-MINOR)** **repl**: show reference errors during preview (Ruben Bridgewater) [#33282](https://github.com/nodejs/node/pull/33282) +* [[`1dcf66cf87`](https://github.com/nodejs/node/commit/1dcf66cf87)] - **(SEMVER-MINOR)** **fs**: add .ref() and .unref() methods to watcher classes (rickyes) [#33134](https://github.com/nodejs/node/pull/33134) +* [[`f33e86649e`](https://github.com/nodejs/node/commit/f33e86649e)] - **(SEMVER-MINOR)** **http**: expose http.validate-header-name/value (osher) [#33119](https://github.com/nodejs/node/pull/33119) +* [[`b06165584e`](https://github.com/nodejs/node/commit/b06165584e)] - **(SEMVER-MINOR)** **async_hooks**: move PromiseHook handler to JS (Stephen Belanger) [#32891](https://github.com/nodejs/node/pull/32891) + +### Commits + +* [[`dd4789b8ee`](https://github.com/nodejs/node/commit/dd4789b8ee)] - **async_hooks**: clear async\_id\_stack for terminations in more places (Anna Henningsen) [#33347](https://github.com/nodejs/node/pull/33347) +* [[`b06165584e`](https://github.com/nodejs/node/commit/b06165584e)] - **(SEMVER-MINOR)** **async_hooks**: move PromiseHook handler to JS (Stephen Belanger) [#32891](https://github.com/nodejs/node/pull/32891) +* [[`cae2051b83`](https://github.com/nodejs/node/commit/cae2051b83)] - **buffer**: improve copy() performance (Nikolai Vavilov) [#33214](https://github.com/nodejs/node/pull/33214) +* [[`24faa37a09`](https://github.com/nodejs/node/commit/24faa37a09)] - **buffer,n-api**: release external buffers from BackingStore callback (Anna Henningsen) [#33321](https://github.com/nodejs/node/pull/33321) +* [[`34e7400fc1`](https://github.com/nodejs/node/commit/34e7400fc1)] - **build**: enable `--error-on-warn` for POSIX workflows (Richard Lau) [#33357](https://github.com/nodejs/node/pull/33357) +* [[`7d4db35f84`](https://github.com/nodejs/node/commit/7d4db35f84)] - **build**: fix `--error-on-warn` for macOS (Richard Lau) [#33357](https://github.com/nodejs/node/pull/33357) +* [[`2dc5db8c07`](https://github.com/nodejs/node/commit/2dc5db8c07)] - **(SEMVER-MINOR)** **cli**: add `--trace-atomics-wait` flag (Anna Henningsen) [#33292](https://github.com/nodejs/node/pull/33292) +* [[`331f0b3420`](https://github.com/nodejs/node/commit/331f0b3420)] - **deps**: update to ICU 67.1 (Michaël Zasso) [#33324](https://github.com/nodejs/node/pull/33324) +* [[`ba66b21c37`](https://github.com/nodejs/node/commit/ba66b21c37)] - **deps**: upgrade npm to 6.14.5 (Ruy Adorno) [#33239](https://github.com/nodejs/node/pull/33239) +* [[`cc279490ce`](https://github.com/nodejs/node/commit/cc279490ce)] - **doc**: prepare 14.x changelog for remark update (Rich Trott) [#33412](https://github.com/nodejs/node/pull/33412) +* [[`7f9ccd6d89`](https://github.com/nodejs/node/commit/7f9ccd6d89)] - **doc**: fix extension in esm example (Gus Caplan) [#33408](https://github.com/nodejs/node/pull/33408) +* [[`8f91338f6e`](https://github.com/nodejs/node/commit/8f91338f6e)] - **doc**: fix stream example (Anna Henningsen) [#33426](https://github.com/nodejs/node/pull/33426) +* [[`182aaf5622`](https://github.com/nodejs/node/commit/182aaf5622)] - **doc**: enhance guides by fixing and making grammar more consistent (Chris Holland) [#33152](https://github.com/nodejs/node/pull/33152) +* [[`0ffa0402a5`](https://github.com/nodejs/node/commit/0ffa0402a5)] - **doc**: add examples for implementing ESM (unknown) [#33168](https://github.com/nodejs/node/pull/33168) +* [[`b41affb9e2`](https://github.com/nodejs/node/commit/b41affb9e2)] - **doc**: add note about clientError writable handling (Paolo Insogna) [#33308](https://github.com/nodejs/node/pull/33308) +* [[`4f0cd648bb`](https://github.com/nodejs/node/commit/4f0cd648bb)] - **doc**: fix typo in n-api.md (Daniel Bevenius) [#33319](https://github.com/nodejs/node/pull/33319) +* [[`0cbee57109`](https://github.com/nodejs/node/commit/0cbee57109)] - **doc**: add warning for socket.connect reuse (Robert Nagy) [#33204](https://github.com/nodejs/node/pull/33204) +* [[`a9e4fdbd1b`](https://github.com/nodejs/node/commit/a9e4fdbd1b)] - **doc**: correct description of `decipher.setAuthTag` in crypto.md (Jonathan Buhacoff) +* [[`84974d3f2c`](https://github.com/nodejs/node/commit/84974d3f2c)] - **doc**: mention python3-distutils dependency in BUILDING.md (osher) [#33174](https://github.com/nodejs/node/pull/33174) +* [[`b5dcfbf634`](https://github.com/nodejs/node/commit/b5dcfbf634)] - **doc**: removed unnecessary util imports from vm examples (Karol Walasek) [#33179](https://github.com/nodejs/node/pull/33179) +* [[`e20fe535a5`](https://github.com/nodejs/node/commit/e20fe535a5)] - **doc**: update Buffer(size) documentation (Nikolai Vavilov) [#33198](https://github.com/nodejs/node/pull/33198) +* [[`5b42d812cc`](https://github.com/nodejs/node/commit/5b42d812cc)] - **doc**: add Uint8Array to `end` and `write` (Pranshu Srivastava) [#33217](https://github.com/nodejs/node/pull/33217) +* [[`c6a8cd0fa1`](https://github.com/nodejs/node/commit/c6a8cd0fa1)] - **doc**: fix md issue in src/README.md (Juan José Arboleda) [#33224](https://github.com/nodejs/node/pull/33224) +* [[`2c49dd3d01`](https://github.com/nodejs/node/commit/2c49dd3d01)] - **doc**: specify unit of time passed to `fs.utimes` (Simen Bekkhus) [#33230](https://github.com/nodejs/node/pull/33230) +* [[`6ffec50494`](https://github.com/nodejs/node/commit/6ffec50494)] - **doc**: add troubleshooting guide for AsyncLocalStorage (Andrey Pechkurov) [#33248](https://github.com/nodejs/node/pull/33248) +* [[`dab5c38f98`](https://github.com/nodejs/node/commit/dab5c38f98)] - **doc**: remove AsyncWrap mentions from async\_hooks.md (Andrey Pechkurov) [#33249](https://github.com/nodejs/node/pull/33249) +* [[`05729430bf`](https://github.com/nodejs/node/commit/05729430bf)] - **doc**: add warnings about transferring Buffers and ArrayBuffer (James M Snell) [#33252](https://github.com/nodejs/node/pull/33252) +* [[`cf88ed8664`](https://github.com/nodejs/node/commit/cf88ed8664)] - **doc**: update napi\_async\_init documentation (Michael Dawson) [#33181](https://github.com/nodejs/node/pull/33181) +* [[`25443fa7f2`](https://github.com/nodejs/node/commit/25443fa7f2)] - **doc**: doc and test URLSearchParams discrepancy (James M Snell) [#33236](https://github.com/nodejs/node/pull/33236) +* [[`07372e9d5b`](https://github.com/nodejs/node/commit/07372e9d5b)] - **doc**: explicitly doc package.exports is breaking (Myles Borins) [#33074](https://github.com/nodejs/node/pull/33074) +* [[`c5a38fe6d7`](https://github.com/nodejs/node/commit/c5a38fe6d7)] - **doc**: fix style and grammer in buffer.md (Nikolai Vavilov) [#33194](https://github.com/nodejs/node/pull/33194) +* [[`e53de96a89`](https://github.com/nodejs/node/commit/e53de96a89)] - **esm**: improve commonjs hint on module not found (Antoine du Hamel) [#33220](https://github.com/nodejs/node/pull/33220) +* [[`c7c420ec87`](https://github.com/nodejs/node/commit/c7c420ec87)] - **fs**: forbid concurrent operations on Dir handle (Anna Henningsen) [#33274](https://github.com/nodejs/node/pull/33274) +* [[`12391c7a20`](https://github.com/nodejs/node/commit/12391c7a20)] - **fs**: clean up Dir.read() uv\_fs\_t data before calling into JS (Anna Henningsen) [#33274](https://github.com/nodejs/node/pull/33274) +* [[`1dcf66cf87`](https://github.com/nodejs/node/commit/1dcf66cf87)] - **(SEMVER-MINOR)** **fs**: add .ref() and .unref() methods to watcher classes (rickyes) [#33134](https://github.com/nodejs/node/pull/33134) +* [[`f33e86649e`](https://github.com/nodejs/node/commit/f33e86649e)] - **(SEMVER-MINOR)** **http**: expose http.validate-header-name/value (osher) [#33119](https://github.com/nodejs/node/pull/33119) +* [[`cc5c8e039d`](https://github.com/nodejs/node/commit/cc5c8e039d)] - **http**: don't destroy completed request (Robert Nagy) [#33120](https://github.com/nodejs/node/pull/33120) +* [[`b634d4b000`](https://github.com/nodejs/node/commit/b634d4b000)] - **http**: set IncomingMessage.destroyed (Robert Nagy) [#33131](https://github.com/nodejs/node/pull/33131) +* [[`cc02c73e53`](https://github.com/nodejs/node/commit/cc02c73e53)] - **http**: fixes memory retention issue with FreeList and HTTPParser (John Leidegren) [#33190](https://github.com/nodejs/node/pull/33190) +* [[`41c5524432`](https://github.com/nodejs/node/commit/41c5524432)] - **http2**: add `bytesWritten` test for `Http2Stream` (Pranshu Srivastava) [#33162](https://github.com/nodejs/node/pull/33162) +* [[`a133a88234`](https://github.com/nodejs/node/commit/a133a88234)] - **lib**: fix typo in timers insert function comment (Daniel Bevenius) [#33301](https://github.com/nodejs/node/pull/33301) +* [[`94d0a088ec`](https://github.com/nodejs/node/commit/94d0a088ec)] - **lib**: refactored scheduling policy assignment (Yash Ladha) [#32663](https://github.com/nodejs/node/pull/32663) +* [[`6bca487b8b`](https://github.com/nodejs/node/commit/6bca487b8b)] - **lib**: fix grammar in internal/bootstrap/loaders.js (szTheory) [#33211](https://github.com/nodejs/node/pull/33211) +* [[`0a78925146`](https://github.com/nodejs/node/commit/0a78925146)] - **meta**: add issue template for API reference docs (Derek Lewis) [#32944](https://github.com/nodejs/node/pull/32944) +* [[`35aae31968`](https://github.com/nodejs/node/commit/35aae31968)] - **module**: add specific error for dir import (Antoine du HAMEL) [#33220](https://github.com/nodejs/node/pull/33220) +* [[`c2d2dfc09f`](https://github.com/nodejs/node/commit/c2d2dfc09f)] - **module**: do not check circular dependencies for exported proxies (Ruben Bridgewater) [#33338](https://github.com/nodejs/node/pull/33338) +* [[`ad8680773e`](https://github.com/nodejs/node/commit/ad8680773e)] - **module**: better error for named exports from cjs (Myles Borins) [#33256](https://github.com/nodejs/node/pull/33256) +* [[`27b814c79b`](https://github.com/nodejs/node/commit/27b814c79b)] - **module**: lazy load 'getOptionValue' in initializeLoader (himself65) [#33212](https://github.com/nodejs/node/pull/33212) +* [[`4ae6130010`](https://github.com/nodejs/node/commit/4ae6130010)] - **n-api**: add uint32 test for -1 (Gabriel Schulhof) +* [[`398bdf40e5`](https://github.com/nodejs/node/commit/398bdf40e5)] - **perf_hooks**: fix error message for invalid entryTypes (Michaël Zasso) [#33285](https://github.com/nodejs/node/pull/33285) +* [[`7aa581f4ff`](https://github.com/nodejs/node/commit/7aa581f4ff)] - **(SEMVER-MINOR)** **repl**: deprecate repl.\_builtinLibs (Ruben Bridgewater) [#33294](https://github.com/nodejs/node/pull/33294) +* [[`ed83202307`](https://github.com/nodejs/node/commit/ed83202307)] - **repl**: remove obsolete completer variable (Ruben Bridgewater) [#33294](https://github.com/nodejs/node/pull/33294) +* [[`db7bb941a3`](https://github.com/nodejs/node/commit/db7bb941a3)] - **(SEMVER-MINOR)** **repl**: deprecate repl.inputStream and repl.outputStream (Ruben Bridgewater) [#33294](https://github.com/nodejs/node/pull/33294) +* [[`6257cf256e`](https://github.com/nodejs/node/commit/6257cf256e)] - **repl**: improve repl autocompletion for require calls (Ruben Bridgewater) [#33282](https://github.com/nodejs/node/pull/33282) +* [[`69061dc73e`](https://github.com/nodejs/node/commit/69061dc73e)] - **repl**: replace hard coded core module list with actual list (Ruben Bridgewater) [#33282](https://github.com/nodejs/node/pull/33282) +* [[`d33dcf1d5f`](https://github.com/nodejs/node/commit/d33dcf1d5f)] - **(SEMVER-MINOR)** **repl**: show reference errors during preview (Ruben Bridgewater) [#33282](https://github.com/nodejs/node/pull/33282) +* [[`1a9771a50a`](https://github.com/nodejs/node/commit/1a9771a50a)] - **(SEMVER-MINOR)** **repl**: improve repl preview (Ruben Bridgewater) [#33282](https://github.com/nodejs/node/pull/33282) +* [[`e4ad4642d7`](https://github.com/nodejs/node/commit/e4ad4642d7)] - **src**: add default: case to silence compiler warning (Anna Henningsen) [#33451](https://github.com/nodejs/node/pull/33451) +* [[`099f18e89b`](https://github.com/nodejs/node/commit/099f18e89b)] - **src**: distinguish refed/unrefed threadsafe Immediates (Anna Henningsen) [#33320](https://github.com/nodejs/node/pull/33320) +* [[`5e5aa0bc6c`](https://github.com/nodejs/node/commit/5e5aa0bc6c)] - **src**: add #include \ in json\_utils.h (Cheng Zhao) [#33332](https://github.com/nodejs/node/pull/33332) +* [[`8ada953ef2`](https://github.com/nodejs/node/commit/8ada953ef2)] - **src**: replace to CHECK\_NOT\_NULL in node\_crypto (himself65) [#33383](https://github.com/nodejs/node/pull/33383) +* [[`0257386cd4`](https://github.com/nodejs/node/commit/0257386cd4)] - **src**: remove deprecated FinalizationRegistry hooks (Gus Caplan) [#33373](https://github.com/nodejs/node/pull/33373) +* [[`354ff4f21b`](https://github.com/nodejs/node/commit/354ff4f21b)] - **src**: small modification to NgHeader (James M Snell) [#33289](https://github.com/nodejs/node/pull/33289) +* [[`fd89ef1478`](https://github.com/nodejs/node/commit/fd89ef1478)] - **src**: refactor Reallocate since it introduced in upstream v8 (Jiawen Geng) [#33402](https://github.com/nodejs/node/pull/33402) +* [[`d292633ed4`](https://github.com/nodejs/node/commit/d292633ed4)] - **src**: add primordials to arguments comment (Daniel Bevenius) [#33318](https://github.com/nodejs/node/pull/33318) +* [[`19996073ca`](https://github.com/nodejs/node/commit/19996073ca)] - **src**: remove unused using declarations in node.cc (Daniel Bevenius) [#33261](https://github.com/nodejs/node/pull/33261) +* [[`c9c16c03c4`](https://github.com/nodejs/node/commit/c9c16c03c4)] - **src**: delete unused variables to resolve compile time print warning (rickyes) [#33358](https://github.com/nodejs/node/pull/33358) +* [[`066ca98069`](https://github.com/nodejs/node/commit/066ca98069)] - **src**: use MaybeLocal.ToLocal instead of IsEmpty (Daniel Bevenius) [#33312](https://github.com/nodejs/node/pull/33312) +* [[`f3129b290d`](https://github.com/nodejs/node/commit/f3129b290d)] - **src**: fix typo in comment in async\_wrap.cc (Daniel Bevenius) [#33350](https://github.com/nodejs/node/pull/33350) +* [[`0d77eec4b0`](https://github.com/nodejs/node/commit/0d77eec4b0)] - **src**: add support for TLA (Gus Caplan) [#30370](https://github.com/nodejs/node/pull/30370) +* [[`fd9c7c2118`](https://github.com/nodejs/node/commit/fd9c7c2118)] - **src**: fix compiler warning in async\_wrap.cc (Anna Henningsen) [#33322](https://github.com/nodejs/node/pull/33322) +* [[`3de9dd9c8d`](https://github.com/nodejs/node/commit/3de9dd9c8d)] - **src**: remove unnecessary Isolate::GetCurrent() calls (Anna Henningsen) [#33298](https://github.com/nodejs/node/pull/33298) +* [[`ef2503375b`](https://github.com/nodejs/node/commit/ef2503375b)] - **src**: fix invalid windowBits=8 gzip segfault (Ben Noordhuis) [#33045](https://github.com/nodejs/node/pull/33045) +* [[`548cedd870`](https://github.com/nodejs/node/commit/548cedd870)] - **src**: split out callback queue implementation from Environment (Anna Henningsen) [#33272](https://github.com/nodejs/node/pull/33272) +* [[`ed41494397`](https://github.com/nodejs/node/commit/ed41494397)] - **src**: clean up large pages code (Gabriel Schulhof) [#33255](https://github.com/nodejs/node/pull/33255) +* [[`cf476984f6`](https://github.com/nodejs/node/commit/cf476984f6)] - **src**: use BaseObjectPtr in StreamReq::Dispose (James M Snell) [#33102](https://github.com/nodejs/node/pull/33102) +* [[`5ff31921cc`](https://github.com/nodejs/node/commit/5ff31921cc)] - ***Revert*** "**src**: add test/abort build tasks" (Richard Lau) [#33196](https://github.com/nodejs/node/pull/33196) +* [[`a56b600e93`](https://github.com/nodejs/node/commit/a56b600e93)] - ***Revert*** "**src**: add aliased-buffer-overflow abort test" (Richard Lau) [#33196](https://github.com/nodejs/node/pull/33196) +* [[`a292630baf`](https://github.com/nodejs/node/commit/a292630baf)] - **src**: retrieve binding data from the context (Joyee Cheung) [#33139](https://github.com/nodejs/node/pull/33139) +* [[`b2fb01a68d`](https://github.com/nodejs/node/commit/b2fb01a68d)] - **stream**: make from read one at a time (Robert Nagy) [#33201](https://github.com/nodejs/node/pull/33201) +* [[`b93a723fe6`](https://github.com/nodejs/node/commit/b93a723fe6)] - **test**: regression tests for async\_hooks + Promise + Worker interaction (Anna Henningsen) [#33347](https://github.com/nodejs/node/pull/33347) +* [[`d3e2fc81e8`](https://github.com/nodejs/node/commit/d3e2fc81e8)] - **test**: fix test-dns-idna2008 (Rich Trott) [#33367](https://github.com/nodejs/node/pull/33367) +* [[`95842db17e`](https://github.com/nodejs/node/commit/95842db17e)] - **test**: refactor test/parallel/test-bootstrap-modules.js (Ruben Bridgewater) [#33282](https://github.com/nodejs/node/pull/33282) +* [[`f31b262f50`](https://github.com/nodejs/node/commit/f31b262f50)] - **test**: refactor WPTRunner (Joyee Cheung) [#33297](https://github.com/nodejs/node/pull/33297) +* [[`85cffb8e4c`](https://github.com/nodejs/node/commit/85cffb8e4c)] - **test**: update WPT interfaces and hr-time (Joyee Cheung) [#33297](https://github.com/nodejs/node/pull/33297) +* [[`5b2cd440a1`](https://github.com/nodejs/node/commit/5b2cd440a1)] - **test**: fix test-net-throttle (Rich Trott) [#33329](https://github.com/nodejs/node/pull/33329) +* [[`1d2c81fee9`](https://github.com/nodejs/node/commit/1d2c81fee9)] - **test**: add hr-time Web platform tests (Michaël Zasso) [#33287](https://github.com/nodejs/node/pull/33287) +* [[`6f54c2bbb6`](https://github.com/nodejs/node/commit/6f54c2bbb6)] - **test**: rename test-lookupService-promises (rickyes) [#33100](https://github.com/nodejs/node/pull/33100) +* [[`302408e515`](https://github.com/nodejs/node/commit/302408e515)] - **test**: skip some console tests on dumb terminal (Adam Majer) [#33165](https://github.com/nodejs/node/pull/33165) +* [[`676ef952ab`](https://github.com/nodejs/node/commit/676ef952ab)] - **test**: add tests for options.fs in fs streams (Julian Duque) [#33185](https://github.com/nodejs/node/pull/33185) +* [[`6d2aaaf6b4`](https://github.com/nodejs/node/commit/6d2aaaf6b4)] - **tls**: fix --tls-keylog option (Alba Mendez) [#33366](https://github.com/nodejs/node/pull/33366) +* [[`eedc13174e`](https://github.com/nodejs/node/commit/eedc13174e)] - **tls**: reset secureConnecting on client socket (David Halls) [#33209](https://github.com/nodejs/node/pull/33209) +* [[`453affebb0`](https://github.com/nodejs/node/commit/453affebb0)] - **tools**: update dependencies for markdown linting (Rich Trott) [#33412](https://github.com/nodejs/node/pull/33412) +* [[`91193447fb`](https://github.com/nodejs/node/commit/91193447fb)] - **tools**: enable no-else-return lint rule (Luigi Pinca) [#32667](https://github.com/nodejs/node/pull/32667) +* [[`e1e57a4223`](https://github.com/nodejs/node/commit/e1e57a4223)] - **tools**: update ESLint to 7.0.0 (Colin Ihrig) [#33316](https://github.com/nodejs/node/pull/33316) +* [[`cf03fe5b67`](https://github.com/nodejs/node/commit/cf03fe5b67)] - **tools**: remove obsolete no-restricted-syntax eslint rules (Ruben Bridgewater) [#32161](https://github.com/nodejs/node/pull/32161) +* [[`804982c1b6`](https://github.com/nodejs/node/commit/804982c1b6)] - **tools**: add eslint rule to only pass through 'test' to debuglog (Ruben Bridgewater) [#32161](https://github.com/nodejs/node/pull/32161) +* [[`c2cf9782ab`](https://github.com/nodejs/node/commit/c2cf9782ab)] - ***Revert*** "**vm**: add importModuleDynamically option to compileFunction" (Matteo Collina) [#33364](https://github.com/nodejs/node/pull/33364) +* [[`6a26eee3c5`](https://github.com/nodejs/node/commit/6a26eee3c5)] - **wasi**: fix poll\_oneoff memory interface (Colin Ihrig) [#33250](https://github.com/nodejs/node/pull/33250) +* [[`4465d23c30`](https://github.com/nodejs/node/commit/4465d23c30)] - **wasi**: prevent syscalls before start (Tobias Nießen) [#33235](https://github.com/nodejs/node/pull/33235) +* [[`9d1e577109`](https://github.com/nodejs/node/commit/9d1e577109)] - **worker**: fix crash when .unref() is called during exit (Anna Henningsen) [#33394](https://github.com/nodejs/node/pull/33394) +* [[`b1a7fdac43`](https://github.com/nodejs/node/commit/b1a7fdac43)] - **worker**: call CancelTerminateExecution() before exiting Locker (Anna Henningsen) [#33347](https://github.com/nodejs/node/pull/33347) +* [[`736ca65c2c`](https://github.com/nodejs/node/commit/736ca65c2c)] - **zlib**: reject windowBits=8 when mode=GZIP (Ben Noordhuis) [#33045](https://github.com/nodejs/node/pull/33045) + ## 2020-05-05, Version 14.2.0 (Current), @targos diff --git a/doc/guides/collaborator-guide.md b/doc/guides/collaborator-guide.md index 128f06857b8f0a..11ca506dacee3e 100644 --- a/doc/guides/collaborator-guide.md +++ b/doc/guides/collaborator-guide.md @@ -109,8 +109,8 @@ review by @-mention. See [Who to CC in the issue tracker](#who-to-cc-in-the-issue-tracker). If you are the first Collaborator to approve a pull request that has no CI yet, -please [start one](#testing-and-ci). Please also start a new CI if the PR -creator pushed new code since the last CI run. +please [start one](#testing-and-ci). Please also start a new CI if the +pull request creator pushed new code since the last CI run. ### Consensus Seeking @@ -269,22 +269,22 @@ master branch. Examples of breaking changes include: -* removal or redefinition of existing API arguments -* changing return values -* removing or modifying existing properties on an options argument -* adding or removing errors -* altering expected timing of an event -* changing the side effects of using a particular API +* Removal or redefinition of existing API arguments. +* Changing return values. +* Removing or modifying existing properties on an options argument. +* Adding or removing errors. +* Altering expected timing of an event. +* Changing the side effects of using a particular API. #### Breaking Changes and Deprecations Existing stable public APIs that change in a backward-incompatible way must undergo deprecation. The exceptions to this rule are: -* Adding or removing errors thrown or reported by a public API; -* Changing error messages for errors without error code; -* Altering the timing and non-internal side effects of the public API; -* Changes to errors thrown by dependencies of Node.js, such as V8; +* Adding or removing errors thrown or reported by a public API. +* Changing error messages for errors without error code. +* Altering the timing and non-internal side effects of the public API. +* Changes to errors thrown by dependencies of Node.js, such as V8. * One-time exceptions granted by the TSC. For more information, see [Deprecations](#deprecations). @@ -310,7 +310,7 @@ after-the-fact. Revert commits with `git revert ` or `git revert ..`. The generated commit message will not have a subsystem and may violate line length rules. That is OK. Append the reason for the revert and any `Refs` or `Fixes` -metadata. Raise a Pull Request like any other change. +metadata. Raise a pull request like any other change. ### Introducing New Modules @@ -400,10 +400,10 @@ deprecation level of an API. Collaborators may opt to elevate pull requests or issues to the [TSC][]. Do this if a pull request or issue: -* is labeled `semver-major`, or -* has a significant impact on the codebase, or -* is controversial, or -* is at an impasse among Collaborators who are participating in the discussion. +* Is labeled `semver-major`, or +* Has a significant impact on the codebase, or +* Is controversial, or +* Is at an impasse among Collaborators who are participating in the discussion. @-mention the `@nodejs/tsc` GitHub team if you want to elevate an issue to the [TSC][]. Do not use the GitHub UI on the right-hand side to assign to @@ -573,7 +573,7 @@ for that commit. This is an opportunity to fix commit messages. * The commit message text must conform to the [commit message guidelines][]. * Change the original commit message to include metadata. (The [`git node metadata`][git-node-metadata] command can generate the metadata - for you.) + for you). * Required: A `PR-URL:` line that references the full GitHub URL of the pull request. This makes it easy to trace a commit back to the conversation that @@ -584,7 +584,8 @@ for that commit. This is an opportunity to fix commit messages. background. * Required: A `Reviewed-By: Name ` line for each Collaborator who reviewed the change. - * Useful for @mentions / contact list if something goes wrong in the PR. + * Useful for @mentions / contact list if something goes wrong in the + pull request. * Protects against the assumption that GitHub will be around forever. Other changes may have landed on master since the successful CI run. As a @@ -599,12 +600,13 @@ $ git rev-list upstream/master...HEAD | xargs core-validate-commit Optional: For your own commits, force push the amended commit to the pull request branch. If your branch name is `bugfix`, then: `git push ---force-with-lease origin master:bugfix`. Don't close the PR. It will close -after you push it upstream. It will have the purple merged status rather than -the red closed status. If you close the PR before GitHub adjusts its status, it -will show up as a 0 commit PR with no changed files. The order of operations is -important. If you push upstream before you push to your branch, GitHub will -close the issue with the red closed status. +--force-with-lease origin master:bugfix`. Don't close the pull request. +It will close after you push it upstream. It will have the purple merged +status rather than the red closed status. If you close the pull request +before GitHub adjusts its status, it will show up as a 0 commit pull +request with no changed files. The order of operations is important. +If you push upstream before you push to your branch, GitHub will close +the issue with the red closed status. Time to push it: @@ -645,7 +647,7 @@ git push upstream master ### I Made a Mistake * Ping a TSC member. -* `#node-dev` on freenode +* `#node-dev` on freenode. * With `git`, there's a way to override remote trees by force pushing (`git push -f`). This is generally forbidden as it creates conflicts in other people's forks. It is permissible for simpler slip-ups such as typos in commit @@ -701,8 +703,8 @@ land on the staging branches, the backporter removes the `lts-watch-` label. Likewise, as commits land in an LTS release, the releaser removes the `land-on-` label. -Attach the appropriate `lts-watch-` label to any PR that may impact an LTS -release. +Attach the appropriate `lts-watch-` label to any pull request that +may impact an LTS release. ## Who to CC in the issue tracker diff --git a/doc/guides/cpp-style-guide.md b/doc/guides/cpp-style-guide.md index f937b60edc20d4..32a178ea81256c 100644 --- a/doc/guides/cpp-style-guide.md +++ b/doc/guides/cpp-style-guide.md @@ -40,13 +40,13 @@ runtime features. Coding guidelines are based on the following guides (highest priority first): -1. This document -2. The [Google C++ Style Guide][] -3. The ISO [C++ Core Guidelines][] +1. This document. +2. The [Google C++ Style Guide][]. +3. The ISO [C++ Core Guidelines][]. -In general code should follow the C++ Core Guidelines, unless overridden by the +In general, code should follow the C++ Core Guidelines, unless overridden by the Google C++ Style Guide or this document. At the moment these guidelines are -checked manually by reviewers, with the goal to validate this with automatic +checked manually by reviewers with the goal to validate this with automatic tools. ## Formatting @@ -282,11 +282,11 @@ data[0] = 12345; ### Type casting -* Use `static_cast` if casting is required, and it is valid -* Use `reinterpret_cast` only when it is necessary -* Avoid C-style casts (`(type)value`) +* Use `static_cast` if casting is required, and it is valid. +* Use `reinterpret_cast` only when it is necessary. +* Avoid C-style casts (`(type)value`). * `dynamic_cast` does not work because Node.js is built without - [Run Time Type Information][] + [Run Time Type Information][]. Further reading: @@ -313,13 +313,13 @@ for (const auto& item : some_map) { ### Do not include `*.h` if `*-inl.h` has already been included -Do +Do: ```cpp #include "util-inl.h" // already includes util.h ``` -instead of +Instead of: ```cpp #include "util.h" @@ -383,9 +383,9 @@ exports.foo = function(str) { #### Avoid throwing JavaScript errors in nested C++ methods When you need to throw a JavaScript exception from C++ (i.e. -`isolate()->ThrowException()`) prefer to do it as close to the return to JS as -possible, and not inside of nested C++ calls. Since this changes the JS -execution state doing it closest to where it is consumed reduces the chances of +`isolate()->ThrowException()`), do it as close to the return to JavaScript as +possible, and not inside of nested C++ calls. Since this changes the JavaScript +execution state, doing it closest to where it is consumed reduces the chances of side effects. Node.js is built [without C++ exception handling][], so code using `throw` or diff --git a/doc/guides/cve-management-process.md b/doc/guides/cve-management-process.md index eba94484b53877..fbd7f2cb84a3be 100644 --- a/doc/guides/cve-management-process.md +++ b/doc/guides/cve-management-process.md @@ -63,7 +63,7 @@ than two remaining CVEs a new block must be requested as follows: to the Available list. All changes to the files for managing CVEs in a given year will -be done through Pull Requests so that we have a record of how +be done through pull requests so that we have a record of how the CVEs have been assigned. CVEs are only valid for a specific year. At the beginning of each @@ -122,7 +122,7 @@ following steps are used to assign, announce and report a CVE. verification of the identity of the CVE submitter. For each CVE listed, the additional data must include the following fields - updated with appropriate data for the CVE + updated with appropriate data for the CVE: ```text [CVEID]: CVE-XXXX-XXXX [PRODUCT]: Node.js diff --git a/doc/guides/maintaining-openssl.md b/doc/guides/maintaining-openssl.md index af59486b0f3219..6a584f46024171 100644 --- a/doc/guides/maintaining-openssl.md +++ b/doc/guides/maintaining-openssl.md @@ -3,10 +3,10 @@ This document describes how to update `deps/openssl/`. ## Requirements -* Linux environment +* Linux environment. * `perl` Only Perl version 5 is tested. -* `nasm` () The version of 2.11 or higher is needed. -* GNU `as` in binutils. The version of 2.26 or higher is needed. +* `nasm` () Version 2.11 or higher is needed. +* GNU `as` in binutils. Version 2.26 or higher is needed. ## 0. Check Requirements @@ -39,7 +39,8 @@ them. % git commit openssl ```` -The commit message can be (with the openssl version set to the relevant value): +The commit message can be written as (with the openssl version set +to the relevant value): ```text deps: upgrade openssl sources to 1.1.0h @@ -62,15 +63,15 @@ Use `make` to regenerate all platform dependent files in ## 3. Check diffs -Check diffs if updates are right. Even if no updates in openssl -sources, `buildinf.h` files will be updated for they have a timestamp +Check diffs to ensure updates are right. Even if there are no updates in openssl +sources, `buildinf.h` files will be updated because they have timestamp data in them. ```sh % git diff -- deps/openssl ``` -*Note*: On Windows, OpenSSL Configure generates `makefile` that can be -used for `nmake` command. The `make` command in the step 2 above uses +*Note*: On Windows, OpenSSL Configure generates a `makefile` that can be +used for the `nmake` command. The `make` command in step 2 (above) uses `Makefile_VC-WIN64A` and `Makefile_VC-WIN32` that are manually created. When source files or build options are updated in Windows, it needs to change these two Makefiles by hand. If you are not sure, @@ -79,7 +80,7 @@ please ask @shigeki for details. ## 4. Commit and make test Update all architecture dependent files. Do not forget to git add or remove -files if they are changed before commit: +files if they are changed before committing: ```sh % git add deps/openssl/config/archs % git add deps/openssl/openssl/include/crypto/bn_conf.h @@ -88,7 +89,8 @@ files if they are changed before commit: % git commit ``` -The commit message can be (with the openssl version set to the relevant value): +The commit message can be written as (with the openssl version set +to the relevant value): ```text deps: update archs files for OpenSSL-1.1.0 @@ -102,4 +104,4 @@ The commit message can be (with the openssl version set to the relevant value): $ git commit ``` -Finally, build Node.js and run tests. +Finally, build Node.js and run the tests. diff --git a/doc/node.1 b/doc/node.1 index ec2642170aee6f..278061424c07c6 100644 --- a/doc/node.1 +++ b/doc/node.1 @@ -363,6 +363,10 @@ but the option is supported for compatibility with older Node.js versions. Set default minVersion to 'TLSv1.3'. Use to disable support for TLSv1.2 in favour of TLSv1.3, which is more secure. . +.It Fl -trace-atomics-wait +Print short summaries of calls to +.Sy Atomics.wait() . +. .It Fl -trace-deprecation Print stack traces for deprecations. . diff --git a/lib/_http_client.js b/lib/_http_client.js index c78289138e756a..23e82c807fc6e0 100644 --- a/lib/_http_client.js +++ b/lib/_http_client.js @@ -413,6 +413,8 @@ function socketCloseListener() { // the `socketOnData`. const parser = socket.parser; const res = req.res; + + req.destroyed = true; if (res) { // Socket closed before we emitted 'end' below. if (!res.complete) { @@ -422,10 +424,12 @@ function socketCloseListener() { req.emit('close'); if (!res.aborted && res.readable) { res.on('end', function() { + this.destroyed = true; this.emit('close'); }); res.push(null); } else { + res.destroyed = true; res.emit('close'); } } else { @@ -539,6 +543,7 @@ function socketOnData(d) { socket.readableFlowing = null; req.emit(eventName, res, socket, bodyHead); + req.destroyed = true; req.emit('close'); } else { // Requested Upgrade or used CONNECT method, but have no handler. @@ -664,7 +669,9 @@ function responseKeepAlive(req) { // handlers have a chance to run. defaultTriggerAsyncIdScope(asyncId, process.nextTick, emitFreeNT, req); + req.destroyed = true; if (req.res) { + req.res.destroyed = true; // Detach socket from IncomingMessage to avoid destroying the freed // socket in IncomingMessage.destroy(). req.res.socket = null; diff --git a/lib/_http_common.js b/lib/_http_common.js index eec965d7fcf8f1..2c836221f731e1 100644 --- a/lib/_http_common.js +++ b/lib/_http_common.js @@ -161,12 +161,10 @@ const parsers = new FreeList('parsers', 1000, function parsersCb() { cleanParser(parser); - parser.onIncoming = null; parser[kOnHeaders] = parserOnHeaders; parser[kOnHeadersComplete] = parserOnHeadersComplete; parser[kOnBody] = parserOnBody; parser[kOnMessageComplete] = parserOnMessageComplete; - parser[kOnTimeout] = null; return parser; }); @@ -232,7 +230,9 @@ function cleanParser(parser) { parser.outgoing = null; parser.maxHeaderPairs = MAX_HEADER_PAIRS; parser[kOnExecute] = null; + parser[kOnTimeout] = null; parser._consumed = false; + parser.onIncoming = null; } function prepareError(err, parser, rawPacket) { diff --git a/lib/_http_incoming.js b/lib/_http_incoming.js index f309e32e36dc7b..02b88dfe87ca85 100644 --- a/lib/_http_incoming.js +++ b/lib/_http_incoming.js @@ -119,6 +119,8 @@ IncomingMessage.prototype._read = function _read(n) { // any messages, before ever calling this. In that case, just skip // it, since something else is destroying this connection anyway. IncomingMessage.prototype.destroy = function destroy(error) { + // TODO(ronag): Implement in terms of _destroy + this.destroyed = true; if (this.socket) this.socket.destroy(error); }; @@ -246,9 +248,8 @@ function matchKnownFields(field, lowercased) { } if (lowercased) { return '\u0000' + field; - } else { - return matchKnownFields(field.toLowerCase(), true); } + return matchKnownFields(field.toLowerCase(), true); } // Add the given (field, value) pair to the message // diff --git a/lib/_http_outgoing.js b/lib/_http_outgoing.js index 5fd462b0194387..d9decf22a018a9 100644 --- a/lib/_http_outgoing.js +++ b/lib/_http_outgoing.js @@ -909,6 +909,9 @@ function(err, event) { this.destroy(err); }; +OutgoingMessage.validateHeaderName = validateHeaderName; +OutgoingMessage.validateHeaderValue = validateHeaderValue; + module.exports = { OutgoingMessage }; diff --git a/lib/_http_server.js b/lib/_http_server.js index c8b27dcd42cb5b..9dfeef746636c5 100644 --- a/lib/_http_server.js +++ b/lib/_http_server.js @@ -205,7 +205,10 @@ function onServerResponseClose() { // Ergo, we need to deal with stale 'close' events and handle the case // where the ServerResponse object has already been deconstructed. // Fortunately, that requires only a single if check. :-) - if (this._httpMessage) this._httpMessage.emit('close'); + if (this._httpMessage) { + this._httpMessage.destroyed = true; + this._httpMessage.emit('close'); + } } ServerResponse.prototype.assignSocket = function assignSocket(socket) { @@ -534,6 +537,7 @@ function abortIncoming(incoming) { while (incoming.length) { const req = incoming.shift(); req.aborted = true; + req.destroyed = true; req.emit('aborted'); req.emit('close'); } @@ -660,11 +664,13 @@ function clearIncoming(req) { if (parser && parser.incoming === req) { if (req.readableEnded) { parser.incoming = null; + req.destroyed = true; req.emit('close'); } else { req.on('end', clearIncoming); } } else { + req.destroyed = true; req.emit('close'); } } @@ -708,6 +714,7 @@ function resOnFinish(req, res, socket, state, server) { } function emitCloseNT(self) { + self.destroyed = true; self.emit('close'); } diff --git a/lib/_stream_readable.js b/lib/_stream_readable.js index f39c49867805d3..42429cf63b8207 100644 --- a/lib/_stream_readable.js +++ b/lib/_stream_readable.js @@ -372,8 +372,7 @@ function howMuchToRead(n, state) { // Only flow one buffer at a time. if (state.flowing && state.length) return state.buffer.first().length; - else - return state.length; + return state.length; } if (n <= state.length) return n; diff --git a/lib/_stream_writable.js b/lib/_stream_writable.js index 4b353a52665efa..236e236aa32459 100644 --- a/lib/_stream_writable.js +++ b/lib/_stream_writable.js @@ -298,10 +298,9 @@ Writable.prototype.write = function(chunk, encoding, cb) { process.nextTick(cb, err); errorOrDestroy(this, err, true); return false; - } else { - state.pendingcb++; - return writeOrBuffer(this, state, chunk, encoding, cb); } + state.pendingcb++; + return writeOrBuffer(this, state, chunk, encoding, cb); }; Writable.prototype.cork = function() { diff --git a/lib/_tls_wrap.js b/lib/_tls_wrap.js index 1937f3984d71bc..8b912d805c5114 100644 --- a/lib/_tls_wrap.js +++ b/lib/_tls_wrap.js @@ -372,16 +372,9 @@ function onPskClientCallback(hint, maxPskLen, maxIdentityLen) { return { psk: ret.psk, identity: ret.identity }; } -function onkeylogclient(line) { - debug('client onkeylog'); - this[owner_symbol].emit('keylog', line); -} - function onkeylog(line) { - debug('server onkeylog'); - const owner = this[owner_symbol]; - if (owner.server) - owner.server.emit('keylog', line, owner); + debug('onkeylog'); + this[owner_symbol].emit('keylog', line); } function onocspresponse(resp) { @@ -663,13 +656,26 @@ TLSSocket.prototype._init = function(socket, wrap) { if (requestCert || rejectUnauthorized) ssl.setVerifyMode(requestCert, rejectUnauthorized); + // Only call .onkeylog if there is a keylog listener. + ssl.onkeylog = onkeylog; + this.on('newListener', keylogNewListener); + + function keylogNewListener(event) { + if (event !== 'keylog') + return; + + ssl.enableKeylogCallback(); + + // Remove this listener since it's no longer needed. + this.removeListener('newListener', keylogNewListener); + } + if (options.isServer) { ssl.onhandshakestart = onhandshakestart; ssl.onhandshakedone = onhandshakedone; ssl.onclienthello = loadSession; ssl.oncertcb = loadSNI; ssl.onnewsession = onnewsession; - ssl.onkeylog = onkeylog; ssl.lastHandshakeTime = 0; ssl.handshakes = 0; @@ -679,8 +685,6 @@ TLSSocket.prototype._init = function(socket, wrap) { // Also starts the client hello parser as a side effect. ssl.enableSessionCallbacks(); } - if (this.server.listenerCount('keylog') > 0) - ssl.enableKeylogCallback(); if (this.server.listenerCount('OCSPRequest') > 0) ssl.enableCertCb(); } @@ -709,21 +713,6 @@ TLSSocket.prototype._init = function(socket, wrap) { // Remove this listener since it's no longer needed. this.removeListener('newListener', newListener); } - - ssl.onkeylog = onkeylogclient; - - // Only call .onkeylog if there is a keylog listener. - this.on('newListener', keylogNewListener); - - function keylogNewListener(event) { - if (event !== 'keylog') - return; - - ssl.enableKeylogCallback(); - - // Remove this listener since it's no longer needed. - this.removeListener('newListener', keylogNewListener); - } } if (tlsKeylog) { @@ -731,17 +720,16 @@ TLSSocket.prototype._init = function(socket, wrap) { warnOnTlsKeylog = false; process.emitWarning('Using --tls-keylog makes TLS connections insecure ' + 'by writing secret key material to file ' + tlsKeylog); - ssl.enableKeylogCallback(); - this.on('keylog', (line) => { - appendFile(tlsKeylog, line, { mode: 0o600 }, (err) => { - if (err && warnOnTlsKeylogError) { - warnOnTlsKeylogError = false; - process.emitWarning('Failed to write TLS keylog (this warning ' + - 'will not be repeated): ' + err); - } - }); - }); } + this.on('keylog', (line) => { + appendFile(tlsKeylog, line, { mode: 0o600 }, (err) => { + if (err && warnOnTlsKeylogError) { + warnOnTlsKeylogError = false; + process.emitWarning('Failed to write TLS keylog (this warning ' + + 'will not be repeated): ' + err); + } + }); + }); } ssl.onerror = onerror; @@ -1044,6 +1032,10 @@ function onSocketTLSError(err) { } } +function onSocketKeylog(line) { + this._tlsOptions.server.emit('keylog', line, this); +} + function onSocketClose(err) { // Closed because of error - no need to emit it twice if (err) @@ -1076,6 +1068,9 @@ function tlsConnectionListener(rawSocket) { socket.on('secure', onServerSocketSecure); + if (this.listenerCount('keylog') > 0) + socket.on('keylog', onSocketKeylog); + socket[kErrorEmitted] = false; socket.on('close', onSocketClose); socket.on('_tlsError', onSocketTLSError); @@ -1508,15 +1503,16 @@ function onConnectSecure() { if (options.rejectUnauthorized) { this.destroy(verifyError); return; - } else { - debug('client emit secureConnect. rejectUnauthorized: %s, ' + - 'authorizationError: %s', options.rejectUnauthorized, - this.authorizationError); - this.emit('secureConnect'); } + debug('client emit secureConnect. rejectUnauthorized: %s, ' + + 'authorizationError: %s', options.rejectUnauthorized, + this.authorizationError); + this.secureConnecting = false; + this.emit('secureConnect'); } else { this.authorized = true; debug('client emit secureConnect. authorized:', this.authorized); + this.secureConnecting = false; this.emit('secureConnect'); } diff --git a/lib/async_hooks.js b/lib/async_hooks.js index 0943534790550c..9e287405f8af0b 100644 --- a/lib/async_hooks.js +++ b/lib/async_hooks.js @@ -26,6 +26,7 @@ const { getHookArrays, enableHooks, disableHooks, + updatePromiseHookMode, executionAsyncResource, // Internal Embedder API newAsyncId, @@ -101,6 +102,8 @@ class AsyncHook { enableHooks(); } + updatePromiseHookMode(); + return this; } diff --git a/lib/buffer.js b/lib/buffer.js index 874227f0d44051..a818f41a26ed5b 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -257,7 +257,7 @@ function _copyActual(source, target, targetStart, sourceStart, sourceEnd) { if (nb > sourceLen) nb = sourceLen; - if (sourceStart !== 0 || sourceEnd !== source.length) + if (sourceStart !== 0 || sourceEnd < source.length) source = new Uint8Array(source.buffer, source.byteOffset + sourceStart, nb); target.set(source, targetStart); diff --git a/lib/dns.js b/lib/dns.js index 4243a05e179b88..92b70c73effbf2 100644 --- a/lib/dns.js +++ b/lib/dns.js @@ -261,9 +261,8 @@ function resolve(hostname, rrtype, callback) { if (typeof resolver === 'function') { return resolver.call(this, hostname, callback); - } else { - throw new ERR_INVALID_OPT_VALUE('rrtype', rrtype); } + throw new ERR_INVALID_OPT_VALUE('rrtype', rrtype); } function defaultResolverSetServers(servers) { diff --git a/lib/events.js b/lib/events.js index b138979e138fdf..fc2f969ea37ef6 100644 --- a/lib/events.js +++ b/lib/events.js @@ -577,9 +577,8 @@ EventEmitter.prototype.rawListeners = function rawListeners(type) { EventEmitter.listenerCount = function(emitter, type) { if (typeof emitter.listenerCount === 'function') { return emitter.listenerCount(type); - } else { - return listenerCount.call(emitter, type); } + return listenerCount.call(emitter, type); }; EventEmitter.prototype.listenerCount = listenerCount; diff --git a/lib/fs.js b/lib/fs.js index b0581927514888..5883a082921c90 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -1489,6 +1489,8 @@ function watchFile(filename, options, listener) { stat[watchers.kFSStatWatcherStart](filename, options.persistent, options.interval); statWatchers.set(filename, stat); + } else { + stat[watchers.kFSStatWatcherAddOrCleanRef]('add'); } stat.addListener('change', listener); @@ -1503,9 +1505,13 @@ function unwatchFile(filename, listener) { if (stat === undefined) return; if (typeof listener === 'function') { + const beforeListenerCount = stat.listenerCount('change'); stat.removeListener('change', listener); + if (stat.listenerCount('change') < beforeListenerCount) + stat[watchers.kFSStatWatcherAddOrCleanRef]('clean'); } else { stat.removeAllListeners('change'); + stat[watchers.kFSStatWatcherAddOrCleanRef]('cleanAll'); } if (stat.listenerCount('change') === 0) { @@ -1539,9 +1545,8 @@ function encodeRealpathResult(result, options) { const asBuffer = Buffer.from(result); if (options.encoding === 'buffer') { return asBuffer; - } else { - return asBuffer.toString(options.encoding); } + return asBuffer.toString(options.encoding); } // Finds the next portion of a (partial) path, up to the next path delimiter diff --git a/lib/http.js b/lib/http.js index 55c655763d2647..2b01e1edf5ea19 100644 --- a/lib/http.js +++ b/lib/http.js @@ -30,6 +30,7 @@ const { ClientRequest } = require('_http_client'); const { methods } = require('_http_common'); const { IncomingMessage } = require('_http_incoming'); const { OutgoingMessage } = require('_http_outgoing'); +const { validateHeaderName, validateHeaderValue } = OutgoingMessage; const { _connectionListener, STATUS_CODES, @@ -63,6 +64,8 @@ module.exports = { Server, ServerResponse, createServer, + validateHeaderName, + validateHeaderValue, get, request }; diff --git a/lib/internal/async_hooks.js b/lib/internal/async_hooks.js index 8439260f1af1a6..b7a8c581cccd0b 100644 --- a/lib/internal/async_hooks.js +++ b/lib/internal/async_hooks.js @@ -3,7 +3,9 @@ const { Error, FunctionPrototypeBind, + ObjectPrototypeHasOwnProperty, ObjectDefineProperty, + Promise, Symbol, } = primordials; @@ -86,9 +88,10 @@ const { kInit, kBefore, kAfter, kDestroy, kTotals, kPromiseResolve, kCheck, kExecutionAsyncId, kAsyncIdCounter, kTriggerAsyncId, kDefaultTriggerAsyncId, kStackLength } = async_wrap.constants; +const { async_id_symbol, + trigger_async_id_symbol } = internalBinding('symbols'); + // Used in AsyncHook and AsyncResource. -const async_id_symbol = Symbol('asyncId'); -const trigger_async_id_symbol = Symbol('triggerAsyncId'); const init_symbol = Symbol('init'); const before_symbol = Symbol('before'); const after_symbol = Symbol('after'); @@ -243,27 +246,89 @@ function restoreActiveHooks() { active_hooks.tmp_fields = null; } +function trackPromise(promise, parent, silent) { + const asyncId = getOrSetAsyncId(promise); + + promise[trigger_async_id_symbol] = parent ? getOrSetAsyncId(parent) : + getDefaultTriggerAsyncId(); + + if (!silent && initHooksExist()) { + const triggerId = promise[trigger_async_id_symbol]; + emitInitScript(asyncId, 'PROMISE', triggerId, promise); + } +} + +function fastPromiseHook(type, promise, parent) { + if (type === kInit || !promise[async_id_symbol]) { + const silent = type !== kInit; + if (parent instanceof Promise) { + trackPromise(promise, parent, silent); + } else { + trackPromise(promise, null, silent); + } + + if (!silent) return; + } + + const asyncId = promise[async_id_symbol]; + switch (type) { + case kBefore: + const triggerId = promise[trigger_async_id_symbol]; + emitBeforeScript(asyncId, triggerId, promise); + break; + case kAfter: + if (hasHooks(kAfter)) { + emitAfterNative(asyncId); + } + if (asyncId === executionAsyncId()) { + // This condition might not be true if async_hooks was enabled during + // the promise callback execution. + // Popping it off the stack can be skipped in that case, because it is + // known that it would correspond to exactly one call with + // PromiseHookType::kBefore that was not witnessed by the PromiseHook. + popAsyncContext(asyncId); + } + break; + case kPromiseResolve: + emitPromiseResolveNative(asyncId); + break; + } +} let wantPromiseHook = false; function enableHooks() { async_hook_fields[kCheck] += 1; +} +let promiseHookMode = -1; +function updatePromiseHookMode() { wantPromiseHook = true; - enablePromiseHook(); + if (destroyHooksExist()) { + if (promiseHookMode !== 1) { + promiseHookMode = 1; + enablePromiseHook(); + } + } else if (promiseHookMode !== 0) { + promiseHookMode = 0; + enablePromiseHook(fastPromiseHook); + } } function disableHooks() { async_hook_fields[kCheck] -= 1; wantPromiseHook = false; + // Delay the call to `disablePromiseHook()` because we might currently be // between the `before` and `after` calls of a Promise. enqueueMicrotask(disablePromiseHookIfNecessary); } function disablePromiseHookIfNecessary() { - if (!wantPromiseHook) + if (!wantPromiseHook) { + promiseHookMode = -1; disablePromiseHook(); + } } // Internal Embedder API // @@ -276,7 +341,7 @@ function newAsyncId() { } function getOrSetAsyncId(object) { - if (object.hasOwnProperty(async_id_symbol)) { + if (ObjectPrototypeHasOwnProperty(object, async_id_symbol)) { return object[async_id_symbol]; } @@ -447,6 +512,7 @@ module.exports = { }, enableHooks, disableHooks, + updatePromiseHookMode, clearDefaultTriggerAsyncId, clearAsyncIdStack, hasAsyncIdStack, diff --git a/lib/internal/bootstrap/node.js b/lib/internal/bootstrap/node.js index aa166cc931b94f..fbc80389c3985a 100644 --- a/lib/internal/bootstrap/node.js +++ b/lib/internal/bootstrap/node.js @@ -7,7 +7,7 @@ // This file is expected not to perform any asynchronous operations itself // when being executed - those should be done in either // `lib/internal/bootstrap/pre_execution.js` or in main scripts. The majority -// of the code here focus on setting up the global proxy and the process +// of the code here focuses on setting up the global proxy and the process // object in a synchronous manner. // As special caution is given to the performance of the startup process, // many dependencies are invoked lazily. @@ -34,7 +34,7 @@ // This file is compiled as if it's wrapped in a function with arguments // passed by node::RunBootstrapping() -/* global process, require, internalBinding */ +/* global process, require, internalBinding, primordials */ setupPrepareStackTrace(); diff --git a/lib/internal/cluster/master.js b/lib/internal/cluster/master.js index 9d6d4df6316956..9e2c7cbecb9963 100644 --- a/lib/internal/cluster/master.js +++ b/lib/internal/cluster/master.js @@ -37,16 +37,17 @@ let debugPortOffset = 1; let initialized = false; // XXX(bnoordhuis) Fold cluster.schedulingPolicy into cluster.settings? -let schedulingPolicy = { - 'none': SCHED_NONE, - 'rr': SCHED_RR -}[process.env.NODE_CLUSTER_SCHED_POLICY]; - -if (schedulingPolicy === undefined) { - // FIXME Round-robin doesn't perform well on Windows right now due to the - // way IOCP is wired up. - schedulingPolicy = (process.platform === 'win32') ? SCHED_NONE : SCHED_RR; -} +let schedulingPolicy = process.env.NODE_CLUSTER_SCHED_POLICY; +if (schedulingPolicy === 'rr') + schedulingPolicy = SCHED_RR; +else if (schedulingPolicy === 'none') + schedulingPolicy = SCHED_NONE; +else if (process.platform === 'win32') { + // Round-robin doesn't perform well on + // Windows due to the way IOCP is wired up. + schedulingPolicy = SCHED_NONE; +} else + schedulingPolicy = SCHED_RR; cluster.schedulingPolicy = schedulingPolicy; diff --git a/lib/internal/crypto/keys.js b/lib/internal/crypto/keys.js index 087cef014f0fb1..c0a133d5d429a3 100644 --- a/lib/internal/crypto/keys.js +++ b/lib/internal/crypto/keys.js @@ -277,14 +277,13 @@ function prepareAsymmetricKey(key, ctx) { const isPublic = (ctx === kConsumePrivate || ctx === kCreatePrivate) ? false : undefined; return { data, ...parseKeyEncoding(key, undefined, isPublic) }; - } else { - throw new ERR_INVALID_ARG_TYPE( - 'key', - ['string', 'Buffer', 'TypedArray', 'DataView', - ...(ctx !== kCreatePrivate ? ['KeyObject'] : [])], - key - ); } + throw new ERR_INVALID_ARG_TYPE( + 'key', + ['string', 'Buffer', 'TypedArray', 'DataView', + ...(ctx !== kCreatePrivate ? ['KeyObject'] : [])], + key + ); } function preparePrivateKey(key) { @@ -301,13 +300,12 @@ function prepareSecretKey(key, bufferOnly = false) { if (key.type !== 'secret') throw new ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE(key.type, 'secret'); return key[kHandle]; - } else { - throw new ERR_INVALID_ARG_TYPE( - 'key', - ['Buffer', 'TypedArray', 'DataView', - ...(bufferOnly ? [] : ['string', 'KeyObject'])], - key); } + throw new ERR_INVALID_ARG_TYPE( + 'key', + ['Buffer', 'TypedArray', 'DataView', + ...(bufferOnly ? [] : ['string', 'KeyObject'])], + key); } return key; } diff --git a/lib/internal/crypto/sig.js b/lib/internal/crypto/sig.js index 7e3b7aa7ff394d..a7c7b71e35619d 100644 --- a/lib/internal/crypto/sig.js +++ b/lib/internal/crypto/sig.js @@ -77,8 +77,7 @@ function getDSASignatureEncoding(options) { return kSigEncDER; else if (dsaEncoding === 'ieee-p1363') return kSigEncP1363; - else - throw new ERR_INVALID_OPT_VALUE('dsaEncoding', dsaEncoding); + throw new ERR_INVALID_OPT_VALUE('dsaEncoding', dsaEncoding); } return kSigEncDER; @@ -89,9 +88,8 @@ function getIntOption(name, options) { if (value !== undefined) { if (value === value >> 0) { return value; - } else { - throw new ERR_INVALID_OPT_VALUE(name, value); } + throw new ERR_INVALID_OPT_VALUE(name, value); } return undefined; } diff --git a/lib/internal/errors.js b/lib/internal/errors.js index c4e9fb3d59b4a3..f20577f8bc66af 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -788,6 +788,9 @@ E('ERR_CRYPTO_SIGN_KEY_REQUIRED', 'No key provided to sign', Error); E('ERR_CRYPTO_TIMING_SAFE_EQUAL_LENGTH', 'Input buffers must have the same byte length', RangeError); E('ERR_DIR_CLOSED', 'Directory handle was closed', Error); +E('ERR_DIR_CONCURRENT_OPERATION', + 'Cannot do synchronous work on directory handle with concurrent ' + + 'asynchronous operations', Error); E('ERR_DNS_SET_SERVERS_FAILED', 'c-ares failed to set servers: "%s" [%s]', Error); E('ERR_DOMAIN_CALLBACK_NOT_AVAILABLE', @@ -805,6 +808,7 @@ E('ERR_ENCODING_INVALID_ENCODED_DATA', function(encoding, ret) { }, TypeError); E('ERR_ENCODING_NOT_SUPPORTED', 'The "%s" encoding is not supported', RangeError); +E('ERR_EVAL_ESM_CANNOT_PRINT', '--print cannot be used with ESM input', Error); E('ERR_FALSY_VALUE_REJECTION', function(reason) { this.reason = reason; return 'Promise was rejected with falsy value'; @@ -1086,10 +1090,9 @@ E('ERR_INVALID_MODULE_SPECIFIER', (pkgPath, subpath, base = undefined) => { assert(subpath !== '.'); return `Package subpath '${subpath}' is not a valid module request for ` + `the "exports" resolution of ${pkgPath}${sep}package.json`; - } else { - return `Package subpath '${subpath}' is not a valid module request for ` + - `the "exports" resolution of ${pkgPath} imported from ${base}`; } + return `Package subpath '${subpath}' is not a valid module request for ` + + `the "exports" resolution of ${pkgPath} imported from ${base}`; }, TypeError); E('ERR_INVALID_OPT_VALUE', (name, value) => `The value "${String(value)}" is invalid for option "${name}"`, @@ -1100,8 +1103,7 @@ E('ERR_INVALID_OPT_VALUE_ENCODING', E('ERR_INVALID_PACKAGE_CONFIG', (path, message, hasMessage = true) => { if (hasMessage) return `Invalid package config ${path}${sep}package.json, ${message}`; - else - return `Invalid JSON in ${path} imported from ${message}`; + return `Invalid JSON in ${path} imported from ${message}`; }, Error); E('ERR_INVALID_PACKAGE_TARGET', (pkgPath, key, subpath, target, base = undefined) => { @@ -1112,11 +1114,10 @@ E('ERR_INVALID_PACKAGE_TARGET', return `Invalid "exports" target ${JSONStringify(target)} defined ` + `for '${subpath}' in the package config ${pkgPath} imported from ` + `${base}.${relError ? '; targets must start with "./"' : ''}`; - } else { - return `Invalid "exports" main target ${target} defined in the ` + - `package config ${pkgPath} imported from ${base}${relError ? - '; targets must start with "./"' : ''}`; } + return `Invalid "exports" main target ${target} defined in the ` + + `package config ${pkgPath} imported from ${base}${relError ? + '; targets must start with "./"' : ''}`; } else if (key === '.') { return `Invalid "exports" main target ${JSONStringify(target)} defined ` + `in the package config ${pkgPath}${sep}package.json${relError ? @@ -1126,11 +1127,10 @@ E('ERR_INVALID_PACKAGE_TARGET', StringPrototypeSlice(key, 0, -subpath.length || key.length)}' in the ` + `package config ${pkgPath}${sep}package.json; ` + 'targets must start with "./"'; - } else { - return `Invalid "exports" target ${JSONStringify(target)} defined for '${ - StringPrototypeSlice(key, 0, -subpath.length || key.length)}' in the ` + - `package config ${pkgPath}${sep}package.json`; } + return `Invalid "exports" target ${JSONStringify(target)} defined for '${ + StringPrototypeSlice(key, 0, -subpath.length || key.length)}' in the ` + + `package config ${pkgPath}${sep}package.json`; }, Error); E('ERR_INVALID_PERFORMANCE_MARK', 'The "%s" performance mark has not been set', Error); @@ -1285,10 +1285,9 @@ E('ERR_PACKAGE_PATH_NOT_EXPORTED', (pkgPath, subpath, base = undefined) => { } else if (base === undefined) { return `Package subpath '${subpath}' is not defined by "exports" in ${ pkgPath}${sep}package.json`; - } else { - return `Package subpath '${subpath}' is not defined by "exports" in ${ - pkgPath} imported from ${base}`; } + return `Package subpath '${subpath}' is not defined by "exports" in ${ + pkgPath} imported from ${base}`; }, Error); E('ERR_REQUIRE_ESM', (filename, parentPath = null, packageJsonPath = null) => { @@ -1407,6 +1406,8 @@ E('ERR_UNKNOWN_FILE_EXTENSION', TypeError); E('ERR_UNKNOWN_MODULE_FORMAT', 'Unknown module format: %s', RangeError); E('ERR_UNKNOWN_SIGNAL', 'Unknown signal: %s', TypeError); +E('ERR_UNSUPPORTED_DIR_IMPORT', "Directory import '%s' is not supported " + +'resolving ES modules, imported from %s', Error); E('ERR_UNSUPPORTED_ESM_URL_SCHEME', 'Only file and data URLs are supported ' + 'by the default ESM loader', Error); diff --git a/lib/internal/fs/dir.js b/lib/internal/fs/dir.js index e23b2f7725b2a2..b4cd72d3668e25 100644 --- a/lib/internal/fs/dir.js +++ b/lib/internal/fs/dir.js @@ -12,6 +12,7 @@ const dirBinding = internalBinding('fs_dir'); const { codes: { ERR_DIR_CLOSED, + ERR_DIR_CONCURRENT_OPERATION, ERR_INVALID_CALLBACK, ERR_MISSING_ARGS } @@ -37,6 +38,7 @@ const kDirOptions = Symbol('kDirOptions'); const kDirReadImpl = Symbol('kDirReadImpl'); const kDirReadPromisified = Symbol('kDirReadPromisified'); const kDirClosePromisified = Symbol('kDirClosePromisified'); +const kDirOperationQueue = Symbol('kDirOperationQueue'); class Dir { constructor(handle, path, options) { @@ -46,6 +48,10 @@ class Dir { this[kDirPath] = path; this[kDirClosed] = false; + // Either `null` or an Array of pending operations (= functions to be called + // once the current operation is done). + this[kDirOperationQueue] = null; + this[kDirOptions] = { bufferSize: 32, ...getOptions(options, { @@ -79,6 +85,13 @@ class Dir { throw new ERR_INVALID_CALLBACK(callback); } + if (this[kDirOperationQueue] !== null) { + this[kDirOperationQueue].push(() => { + this[kDirReadImpl](maybeSync, callback); + }); + return; + } + if (this[kDirBufferedEntries].length > 0) { const [ name, type ] = this[kDirBufferedEntries].splice(0, 2); if (maybeSync) @@ -90,6 +103,12 @@ class Dir { const req = new FSReqCallback(); req.oncomplete = (err, result) => { + process.nextTick(() => { + const queue = this[kDirOperationQueue]; + this[kDirOperationQueue] = null; + for (const op of queue) op(); + }); + if (err || result === null) { return callback(err, result); } @@ -98,6 +117,7 @@ class Dir { getDirent(this[kDirPath], result[0], result[1], callback); }; + this[kDirOperationQueue] = []; this[kDirHandle].read( this[kDirOptions].encoding, this[kDirOptions].bufferSize, @@ -110,6 +130,10 @@ class Dir { throw new ERR_DIR_CLOSED(); } + if (this[kDirOperationQueue] !== null) { + throw new ERR_DIR_CONCURRENT_OPERATION(); + } + if (this[kDirBufferedEntries].length > 0) { const [ name, type ] = this[kDirBufferedEntries].splice(0, 2); return getDirent(this[kDirPath], name, type); @@ -143,6 +167,13 @@ class Dir { throw new ERR_INVALID_CALLBACK(callback); } + if (this[kDirOperationQueue] !== null) { + this[kDirOperationQueue].push(() => { + this.close(callback); + }); + return; + } + this[kDirClosed] = true; const req = new FSReqCallback(); req.oncomplete = callback; @@ -154,6 +185,10 @@ class Dir { throw new ERR_DIR_CLOSED(); } + if (this[kDirOperationQueue] !== null) { + throw new ERR_DIR_CONCURRENT_OPERATION(); + } + this[kDirClosed] = true; const ctx = { path: this[kDirPath] }; const result = this[kDirHandle].close(undefined, ctx); diff --git a/lib/internal/fs/streams.js b/lib/internal/fs/streams.js index 2f5f8948eea458..2466432cb03e54 100644 --- a/lib/internal/fs/streams.js +++ b/lib/internal/fs/streams.js @@ -478,9 +478,8 @@ WriteStream.prototype.close = function(cb) { if (this.closed) { process.nextTick(cb); return; - } else { - this.on('close', cb); } + this.on('close', cb); } // If we are not autoClosing, we should call diff --git a/lib/internal/fs/utils.js b/lib/internal/fs/utils.js index b91eaa006c44cf..96be328a8ea2fc 100644 --- a/lib/internal/fs/utils.js +++ b/lib/internal/fs/utils.js @@ -301,10 +301,9 @@ function preprocessSymlinkDestination(path, type, linkPath) { // A relative target is relative to the link's parent directory. path = pathModule.resolve(linkPath, '..', path); return pathModule.toNamespacedPath(path); - } else { - // Windows symlinks don't tolerate forward slashes. - return ('' + path).replace(/\//g, '\\'); } + // Windows symlinks don't tolerate forward slashes. + return ('' + path).replace(/\//g, '\\'); } // Constructor for file stats. diff --git a/lib/internal/fs/watchers.js b/lib/internal/fs/watchers.js index 118f85d9ada181..01db66c551c9d3 100644 --- a/lib/internal/fs/watchers.js +++ b/lib/internal/fs/watchers.js @@ -31,6 +31,9 @@ const kUseBigint = Symbol('kUseBigint'); const kFSWatchStart = Symbol('kFSWatchStart'); const kFSStatWatcherStart = Symbol('kFSStatWatcherStart'); +const KFSStatWatcherRefCount = Symbol('KFSStatWatcherRefCount'); +const KFSStatWatcherMaxRefCount = Symbol('KFSStatWatcherMaxRefCount'); +const kFSStatWatcherAddOrCleanRef = Symbol('kFSStatWatcherAddOrCleanRef'); function emitStop(self) { self.emit('stop'); @@ -42,6 +45,8 @@ function StatWatcher(bigint) { this._handle = null; this[kOldStatus] = -1; this[kUseBigint] = bigint; + this[KFSStatWatcherRefCount] = 1; + this[KFSStatWatcherMaxRefCount] = 1; } ObjectSetPrototypeOf(StatWatcher.prototype, EventEmitter.prototype); ObjectSetPrototypeOf(StatWatcher, EventEmitter); @@ -75,7 +80,7 @@ StatWatcher.prototype[kFSStatWatcherStart] = function(filename, this._handle[owner_symbol] = this; this._handle.onchange = onchange; if (!persistent) - this._handle.unref(); + this.unref(); // uv_fs_poll is a little more powerful than ev_stat but we curb it for // the sake of backwards compatibility. @@ -117,6 +122,41 @@ StatWatcher.prototype.stop = function() { this._handle = null; }; +// Clean up or add ref counters. +StatWatcher.prototype[kFSStatWatcherAddOrCleanRef] = function(operate) { + if (operate === 'add') { + // Add a Ref + this[KFSStatWatcherRefCount]++; + this[KFSStatWatcherMaxRefCount]++; + } else if (operate === 'clean') { + // Clean up a single + this[KFSStatWatcherMaxRefCount]--; + this.unref(); + } else if (operate === 'cleanAll') { + // Clean up all + this[KFSStatWatcherMaxRefCount] = 0; + this[KFSStatWatcherRefCount] = 0; + this._handle && this._handle.unref(); + } +}; + +StatWatcher.prototype.ref = function() { + // Avoid refCount calling ref multiple times causing unref to have no effect. + if (this[KFSStatWatcherRefCount] === this[KFSStatWatcherMaxRefCount]) + return this; + if (this._handle && this[KFSStatWatcherRefCount]++ === 0) + this._handle.ref(); + return this; +}; + +StatWatcher.prototype.unref = function() { + // Avoid refCount calling unref multiple times causing ref to have no effect. + if (this[KFSStatWatcherRefCount] === 0) return this; + if (this._handle && --this[KFSStatWatcherRefCount] === 0) + this._handle.unref(); + return this; +}; + function FSWatcher() { EventEmitter.call(this); @@ -208,6 +248,16 @@ FSWatcher.prototype.close = function() { process.nextTick(emitCloseNT, this); }; +FSWatcher.prototype.ref = function() { + if (this._handle) this._handle.ref(); + return this; +}; + +FSWatcher.prototype.unref = function() { + if (this._handle) this._handle.unref(); + return this; +}; + function emitCloseNT(self) { self.emit('close'); } @@ -223,5 +273,6 @@ module.exports = { FSWatcher, StatWatcher, kFSWatchStart, - kFSStatWatcherStart + kFSStatWatcherStart, + kFSStatWatcherAddOrCleanRef, }; diff --git a/lib/internal/modules/cjs/helpers.js b/lib/internal/modules/cjs/helpers.js index 2f62c8623e27be..2181fc2a42cab3 100644 --- a/lib/internal/modules/cjs/helpers.js +++ b/lib/internal/modules/cjs/helpers.js @@ -2,6 +2,7 @@ const { ObjectDefineProperty, + ObjectPrototypeHasOwnProperty, SafeMap, } = primordials; const { @@ -109,55 +110,17 @@ function stripBOM(content) { return content; } -const builtinLibs = [ - 'assert', - 'async_hooks', - 'buffer', - 'child_process', - 'cluster', - 'crypto', - 'dgram', - 'dns', - 'domain', - 'events', - 'fs', - 'http', - 'http2', - 'https', - 'net', - 'os', - 'path', - 'perf_hooks', - 'punycode', - 'querystring', - 'readline', - 'repl', - 'stream', - 'string_decoder', - 'tls', - 'trace_events', - 'tty', - 'url', - 'util', - 'v8', - 'vm', - 'worker_threads', - 'zlib', -]; - -if (internalBinding('config').experimentalWasi) { - builtinLibs.push('wasi'); - builtinLibs.sort(); -} - -if (typeof internalBinding('inspector').open === 'function') { - builtinLibs.push('inspector'); - builtinLibs.sort(); -} - function addBuiltinLibsToObject(object) { // Make built-in modules available directly (loaded lazily). - builtinLibs.forEach((name) => { + const { builtinModules } = require('internal/modules/cjs/loader').Module; + builtinModules.forEach((name) => { + // Neither add underscored modules, nor ones that contain slashes (e.g., + // 'fs/promises') or ones that are already defined. + if (name.startsWith('_') || + name.includes('/') || + ObjectPrototypeHasOwnProperty(object, name)) { + return; + } // Goals of this mechanism are: // - Lazy loading of built-in modules // - Having all built-in modules available as non-enumerable properties @@ -203,7 +166,6 @@ function normalizeReferrerURL(referrer) { module.exports = { addBuiltinLibsToObject, - builtinLibs, loadNativeModule, makeRequireFunction, normalizeReferrerURL, diff --git a/lib/internal/modules/cjs/loader.js b/lib/internal/modules/cjs/loader.js index f2715d07cb44fb..0c34e3425567ab 100644 --- a/lib/internal/modules/cjs/loader.js +++ b/lib/internal/modules/cjs/loader.js @@ -77,6 +77,7 @@ const preserveSymlinksMain = getOptionValue('--preserve-symlinks-main'); const manifest = getOptionValue('--experimental-policy') ? require('internal/process/policy').manifest : null; +const { compileFunction } = internalBinding('contextify'); // Whether any user-provided CJS modules had been loaded (executed). // Used for internal assertions. @@ -107,6 +108,11 @@ const { CHAR_COLON } = require('internal/constants'); + +const { + isProxy +} = require('internal/util/types'); + const isWindows = process.platform === 'win32'; const relativeResolveCache = ObjectCreate(null); @@ -821,7 +827,7 @@ function emitCircularRequireWarning(prop) { } // A Proxy that can be used as the prototype of a module.exports object and -// warns when non-existend properties are accessed. +// warns when non-existent properties are accessed. const CircularRequirePrototypeWarningProxy = new Proxy({}, { get(target, prop) { // Allow __esModule access in any case because it is used in the output @@ -840,20 +846,22 @@ const CircularRequirePrototypeWarningProxy = new Proxy({}, { } }); -// Object.prototype and ObjectProtoype refer to our 'primordials' versions +// Object.prototype and ObjectPrototype refer to our 'primordials' versions // and are not identical to the versions on the global object. const PublicObjectPrototype = global.Object.prototype; function getExportsForCircularRequire(module) { if (module.exports && + !isProxy(module.exports) && ObjectGetPrototypeOf(module.exports) === PublicObjectPrototype && // Exclude transpiled ES6 modules / TypeScript code because those may - // employ unusual patterns for accessing 'module.exports'. That should be - // okay because ES6 modules have a different approach to circular + // employ unusual patterns for accessing 'module.exports'. That should + // be okay because ES6 modules have a different approach to circular // dependencies anyway. !module.exports.__esModule) { // This is later unset once the module is done loading. - ObjectSetPrototypeOf(module.exports, CircularRequirePrototypeWarningProxy); + ObjectSetPrototypeOf( + module.exports, CircularRequirePrototypeWarningProxy); } return module.exports; @@ -943,6 +951,7 @@ Module._load = function(request, parent, isMain) { } } } else if (module.exports && + !isProxy(module.exports) && ObjectGetPrototypeOf(module.exports) === CircularRequirePrototypeWarningProxy) { ObjectSetPrototypeOf(module.exports, PublicObjectPrototype); @@ -1102,25 +1111,40 @@ function wrapSafe(filename, content, cjsModuleInstance) { }, }); } + let compiled; try { - return vm.compileFunction(content, [ - 'exports', - 'require', - 'module', - '__filename', - '__dirname', - ], { + compiled = compileFunction( + content, filename, - importModuleDynamically(specifier) { - const loader = asyncESM.ESMLoader; - return loader.import(specifier, normalizeReferrerURL(filename)); - }, - }); + 0, + 0, + undefined, + false, + undefined, + [], + [ + 'exports', + 'require', + 'module', + '__filename', + '__dirname', + ] + ); } catch (err) { if (process.mainModule === cjsModuleInstance) enrichCJSError(err); throw err; } + + const { callbackMap } = internalBinding('module_wrap'); + callbackMap.set(compiled.cacheKey, { + importModuleDynamically: async (specifier) => { + const loader = asyncESM.ESMLoader; + return loader.import(specifier, normalizeReferrerURL(filename)); + } + }); + + return compiled.function; } // Run the file contents in the correct scope or sandbox. Expose diff --git a/lib/internal/modules/esm/get_source.js b/lib/internal/modules/esm/get_source.js index 18af566df90ae3..7b2a2f42eabed9 100644 --- a/lib/internal/modules/esm/get_source.js +++ b/lib/internal/modules/esm/get_source.js @@ -28,8 +28,7 @@ async function defaultGetSource(url, { format } = {}, defaultGetSource) { return { source: Buffer.from(body, base64 ? 'base64' : 'utf8') }; - } else { - throw new ERR_INVALID_URL_SCHEME(['file', 'data']); } + throw new ERR_INVALID_URL_SCHEME(['file', 'data']); } exports.defaultGetSource = defaultGetSource; diff --git a/lib/internal/modules/esm/loader.js b/lib/internal/modules/esm/loader.js index be5868553fa8df..135c541813d49c 100644 --- a/lib/internal/modules/esm/loader.js +++ b/lib/internal/modules/esm/loader.js @@ -167,10 +167,9 @@ class Loader { }; const job = new ModuleJob(this, url, evalInstance, false, false); this.moduleMap.set(url, job); - const { module, result } = await job.run(); + const { module } = await job.run(); return { namespace: module.getNamespace(), - result }; } diff --git a/lib/internal/modules/esm/module_job.js b/lib/internal/modules/esm/module_job.js index 08ba06101ca92c..b00a4fb2a58a7f 100644 --- a/lib/internal/modules/esm/module_job.js +++ b/lib/internal/modules/esm/module_job.js @@ -1,10 +1,14 @@ 'use strict'; const { + ArrayPrototypeJoin, ObjectSetPrototypeOf, PromiseAll, SafeSet, SafePromise, + StringPrototypeIncludes, + StringPrototypeMatch, + StringPrototypeSplit, } = primordials; const { ModuleWrap } = internalBinding('module_wrap'); @@ -27,21 +31,26 @@ class ModuleJob { this.isMain = isMain; this.inspectBrk = inspectBrk; - // This is a Promise<{ module, reflect }>, whose fields will be copied - // onto `this` by `link()` below once it has been resolved. - this.modulePromise = moduleProvider.call(loader, url, isMain); this.module = undefined; + // Expose the promise to the ModuleWrap directly for linking below. + // `this.module` is also filled in below. + this.modulePromise = moduleProvider.call(loader, url, isMain); // Wait for the ModuleWrap instance being linked with all dependencies. const link = async () => { this.module = await this.modulePromise; assert(this.module instanceof ModuleWrap); + // Explicitly keeping track of dependency jobs is needed in order + // to flatten out the dependency graph below in `_instantiate()`, + // so that circular dependencies can't cause a deadlock by two of + // these `link` callbacks depending on each other. const dependencyJobs = []; const promises = this.module.link(async (specifier) => { const jobPromise = this.loader.getModuleJob(specifier, url); dependencyJobs.push(jobPromise); - return (await jobPromise).modulePromise; + const job = await jobPromise; + return job.modulePromise; }); if (promises !== undefined) @@ -55,25 +64,20 @@ class ModuleJob { // 'unhandled rejection' warnings. this.linked.catch(noop); - // instantiated == deep dependency jobs wrappers instantiated, - // module wrapper instantiated + // instantiated == deep dependency jobs wrappers are instantiated, + // and module wrapper is instantiated. this.instantiated = undefined; } - async instantiate() { - if (!this.instantiated) { - return this.instantiated = this._instantiate(); + instantiate() { + if (this.instantiated === undefined) { + this.instantiated = this._instantiate(); } - await this.instantiated; - return this.module; + return this.instantiated; } - // This method instantiates the module associated with this job and its - // entire dependency graph, i.e. creates all the module namespaces and the - // exported/imported variables. async _instantiate() { const jobsInGraph = new SafeSet(); - const addJobsToDependencyGraph = async (moduleJob) => { if (jobsInGraph.has(moduleJob)) { return; @@ -83,6 +87,7 @@ class ModuleJob { return PromiseAll(dependencyJobs.map(addJobsToDependencyGraph)); }; await addJobsToDependencyGraph(this); + try { if (!hasPausedEntry && this.inspectBrk) { hasPausedEntry = true; @@ -93,21 +98,45 @@ class ModuleJob { } } catch (e) { decorateErrorStack(e); + if (StringPrototypeIncludes(e.message, + ' does not provide an export named')) { + const splitStack = StringPrototypeSplit(e.stack, '\n'); + const parentFileUrl = splitStack[0]; + const childSpecifier = StringPrototypeMatch(e.message, /module '(.*)' does/)[1]; + const childFileURL = + await this.loader.resolve(childSpecifier, parentFileUrl); + const format = await this.loader.getFormat(childFileURL); + if (format === 'commonjs') { + const importStatement = splitStack[1]; + const namedImports = StringPrototypeMatch(importStatement, /{.*}/)[0]; + e.message = `The requested module '${childSpecifier}' is expected ` + + 'to be of type CommonJS, which does not support named exports. ' + + 'CommonJS modules can be imported by importing the default ' + + 'export.\n' + + 'For example:\n' + + `import pkg from '${childSpecifier}';\n` + + `const ${namedImports} = pkg;`; + const newStack = StringPrototypeSplit(e.stack, '\n'); + newStack[3] = `SyntaxError: ${e.message}`; + e.stack = ArrayPrototypeJoin(newStack, '\n'); + } + } throw e; } + for (const dependencyJob of jobsInGraph) { // Calling `this.module.instantiate()` instantiates not only the // ModuleWrap in this module, but all modules in the graph. dependencyJob.instantiated = resolvedPromise; } - return this.module; } async run() { - const module = await this.instantiate(); + await this.instantiate(); const timeout = -1; const breakOnSigint = false; - return { module, result: module.evaluate(timeout, breakOnSigint) }; + await this.module.evaluate(timeout, breakOnSigint); + return { module: this.module }; } } ObjectSetPrototypeOf(ModuleJob.prototype, null); diff --git a/lib/internal/modules/esm/resolve.js b/lib/internal/modules/esm/resolve.js index c66e0554ad2746..29235a6785f1bc 100644 --- a/lib/internal/modules/esm/resolve.js +++ b/lib/internal/modules/esm/resolve.js @@ -12,6 +12,7 @@ const { RegExp, SafeMap, SafeSet, + String, StringPrototypeEndsWith, StringPrototypeIncludes, StringPrototypeIndexOf, @@ -48,6 +49,7 @@ const { ERR_INVALID_PACKAGE_TARGET, ERR_MODULE_NOT_FOUND, ERR_PACKAGE_PATH_NOT_EXPORTED, + ERR_UNSUPPORTED_DIR_IMPORT, ERR_UNSUPPORTED_ESM_URL_SCHEME, } = require('internal/errors').codes; @@ -270,10 +272,15 @@ function finalizeResolution(resolved, base) { resolved.pathname, fileURLToPath(base), 'module'); } - if (StringPrototypeEndsWith(resolved.pathname, '/')) return resolved; const path = fileURLToPath(resolved); - - if (!tryStatSync(path).isFile()) { + const stats = tryStatSync(path); + + if (stats.isDirectory()) { + const err = new ERR_UNSUPPORTED_DIR_IMPORT( + path || resolved.pathname, fileURLToPath(base)); + err.url = String(resolved); + throw err; + } else if (!stats.isFile()) { throw new ERR_MODULE_NOT_FOUND( path || resolved.pathname, fileURLToPath(base), 'module'); } @@ -448,10 +455,9 @@ function packageMainResolve(packageJSONUrl, packageConfig, base, conditions) { if (packageConfig.main !== undefined) { return finalizeResolution( new URL(packageConfig.main, packageJSONUrl), base); - } else { - return finalizeResolution( - new URL('index', packageJSONUrl), base); } + return finalizeResolution( + new URL('index', packageJSONUrl), base); } return legacyMainResolve(packageJSONUrl, packageConfig); } @@ -571,10 +577,9 @@ function packageResolve(specifier, base, conditions) { } else if (packageSubpath === '') { return packageMainResolve(packageJSONUrl, packageConfig, base, conditions); - } else { - return packageExportsResolve( - packageJSONUrl, packageSubpath, packageConfig, base, conditions); } + return packageExportsResolve( + packageJSONUrl, packageSubpath, packageConfig, base, conditions); } } @@ -604,10 +609,9 @@ function packageResolve(specifier, base, conditions) { } else if (packageConfig.exports !== undefined) { return packageExportsResolve( packageJSONUrl, packageSubpath, packageConfig, base, conditions); - } else { - return finalizeResolution( - new URL(packageSubpath, packageJSONUrl), base); } + return finalizeResolution( + new URL(packageSubpath, packageJSONUrl), base); // Cross-platform root check. } while (packageJSONPath.length !== lastPath.length); @@ -749,7 +753,11 @@ function defaultResolve(specifier, context = {}, defaultResolveUnused) { } catch (error) { // Try to give the user a hint of what would have been the // resolved CommonJS module - if (error.code === 'ERR_MODULE_NOT_FOUND') { + if (error.code === 'ERR_MODULE_NOT_FOUND' || + error.code === 'ERR_UNSUPPORTED_DIR_IMPORT') { + if (StringPrototypeStartsWith(specifier, 'file://')) { + specifier = fileURLToPath(specifier); + } const found = resolveAsCommonJS(specifier, parentURL); if (found) { // Modify the stack and message string to include the hint diff --git a/lib/internal/modules/esm/translators.js b/lib/internal/modules/esm/translators.js index 497f90ed94475b..a7252c1c99f954 100644 --- a/lib/internal/modules/esm/translators.js +++ b/lib/internal/modules/esm/translators.js @@ -5,6 +5,8 @@ const { JSONParse, ObjectKeys, + PromisePrototypeCatch, + PromiseReject, SafeMap, StringPrototypeReplace, } = primordials; @@ -58,7 +60,12 @@ function createImportMetaResolve(defaultParentUrl) { if (!esmLoader) { esmLoader = require('internal/process/esm_loader').ESMLoader; } - return esmLoader.resolve(specifier, parentUrl); + return PromisePrototypeCatch( + esmLoader.resolve(specifier, parentUrl), + (error) => ( + error.code === 'ERR_UNSUPPORTED_DIR_IMPORT' ? + error.url : PromiseReject(error)) + ); }; } diff --git a/lib/internal/policy/manifest.js b/lib/internal/policy/manifest.js index 02cf0743d728cd..ae5e6cd3f43dfd 100644 --- a/lib/internal/policy/manifest.js +++ b/lib/internal/policy/manifest.js @@ -145,32 +145,31 @@ class Manifest { const dependencyRedirectList = (toSpecifier) => { if (toSpecifier in dependencyMap !== true) { return null; - } else { - const to = dependencyMap[toSpecifier]; - if (to === true) { - return true; - } - if (parsedURLs.has(to)) { - return parsedURLs.get(to); - } else if (canBeRequiredByUsers(to)) { - const href = `node:${to}`; - const resolvedURL = new URL(href); - parsedURLs.set(to, resolvedURL); - parsedURLs.set(href, resolvedURL); - return resolvedURL; - } else if (RegExpPrototypeTest(kRelativeURLStringPattern, to)) { - const resolvedURL = new URL(to, manifestURL); - const href = resourceURL.href; - parsedURLs.set(to, resolvedURL); - parsedURLs.set(href, resolvedURL); - return resolvedURL; - } - const resolvedURL = new URL(to); + } + const to = dependencyMap[toSpecifier]; + if (to === true) { + return true; + } + if (parsedURLs.has(to)) { + return parsedURLs.get(to); + } else if (canBeRequiredByUsers(to)) { + const href = `node:${to}`; + const resolvedURL = new URL(href); + parsedURLs.set(to, resolvedURL); + parsedURLs.set(href, resolvedURL); + return resolvedURL; + } else if (RegExpPrototypeTest(kRelativeURLStringPattern, to)) { + const resolvedURL = new URL(to, manifestURL); const href = resourceURL.href; parsedURLs.set(to, resolvedURL); parsedURLs.set(href, resolvedURL); return resolvedURL; } + const resolvedURL = new URL(to); + const href = resourceURL.href; + parsedURLs.set(to, resolvedURL); + parsedURLs.set(href, resolvedURL); + return resolvedURL; }; dependencies.set(resourceHREF, dependencyRedirectList); } else if (dependencyMap === true) { diff --git a/lib/internal/process/esm_loader.js b/lib/internal/process/esm_loader.js index 996532a930496f..fe47098fde2f63 100644 --- a/lib/internal/process/esm_loader.js +++ b/lib/internal/process/esm_loader.js @@ -8,8 +8,6 @@ const { pathToFileURL } = require('internal/url'); const { getModuleFromWrap, } = require('internal/vm/module'); -const { getOptionValue } = require('internal/options'); -const userLoader = getOptionValue('--experimental-loader'); exports.initializeImportMetaObject = function(wrap, meta) { const { callbackMap } = internalBinding('module_wrap'); @@ -38,6 +36,8 @@ exports.ESMLoader = ESMLoader; exports.initializeLoader = initializeLoader; async function initializeLoader() { + const { getOptionValue } = require('internal/options'); + const userLoader = getOptionValue('--experimental-loader'); if (!userLoader) return; let cwd; diff --git a/lib/internal/process/execution.js b/lib/internal/process/execution.js index a6d6d2325a7f79..bbefcd47c74617 100644 --- a/lib/internal/process/execution.js +++ b/lib/internal/process/execution.js @@ -10,8 +10,9 @@ const path = require('path'); const { codes: { ERR_INVALID_ARG_TYPE, - ERR_UNCAUGHT_EXCEPTION_CAPTURE_ALREADY_SET - } + ERR_UNCAUGHT_EXCEPTION_CAPTURE_ALREADY_SET, + ERR_EVAL_ESM_CANNOT_PRINT, + }, } = require('internal/errors'); const { @@ -39,6 +40,9 @@ function tryGetCwd() { } function evalModule(source, print) { + if (print) { + throw new ERR_EVAL_ESM_CANNOT_PRINT(); + } const { log, error } = require('internal/console/global'); const { decorateErrorStack } = require('internal/util'); const asyncESM = require('internal/process/esm_loader'); diff --git a/lib/internal/repl/utils.js b/lib/internal/repl/utils.js index 476760a08d5934..160417491fe804 100644 --- a/lib/internal/repl/utils.js +++ b/lib/internal/repl/utils.js @@ -48,6 +48,8 @@ const previewOptions = { showHidden: false }; +const REPL_MODE_STRICT = Symbol('repl-strict'); + // If the error is that we've unexpectedly ended the input, // then let the user try to recover by adding more input. // Note: `e` (the original exception) is not used by the current implementation, @@ -136,8 +138,12 @@ function setupPreview(repl, contextSymbol, bufferSymbol, active) { let previewCompletionCounter = 0; let completionPreview = null; + let hasCompletions = false; + let wrapped = false; + let escaped = null; + function getPreviewPos() { const displayPos = repl._getDisplayPos(`${repl._prompt}${repl.line}`); const cursorPos = repl.line.length !== repl.cursor ? @@ -146,7 +152,13 @@ function setupPreview(repl, contextSymbol, bufferSymbol, active) { return { displayPos, cursorPos }; } - const clearPreview = () => { + function isCursorAtInputEnd() { + const { cursorPos, displayPos } = getPreviewPos(); + return cursorPos.rows === displayPos.rows && + cursorPos.cols === displayPos.cols; + } + + const clearPreview = (key) => { if (inputPreview !== null) { const { displayPos, cursorPos } = getPreviewPos(); const rows = displayPos.rows - cursorPos.rows + 1; @@ -179,8 +191,23 @@ function setupPreview(repl, contextSymbol, bufferSymbol, active) { cursorTo(repl.output, pos.cursorPos.cols); moveCursor(repl.output, 0, -rows); } + if (!key.ctrl && !key.shift) { + if (key.name === 'escape') { + if (escaped === null && key.meta) { + escaped = repl.line; + } + } else if ((key.name === 'return' || key.name === 'enter') && + !key.meta && + escaped !== repl.line && + isCursorAtInputEnd()) { + repl._insertString(completionPreview); + } + } completionPreview = null; } + if (escaped !== repl.line) { + escaped = null; + } }; function showCompletionPreview(line, insertPreview) { @@ -206,6 +233,8 @@ function setupPreview(repl, contextSymbol, bufferSymbol, active) { return; } + hasCompletions = true; + // If there is a common prefix to all matches, then apply that portion. const completions = rawCompletions.filter((e) => e); const prefix = commonPrefix(completions); @@ -242,6 +271,12 @@ function setupPreview(repl, contextSymbol, bufferSymbol, active) { }); } + function isInStrictMode(repl) { + return repl.replMode === REPL_MODE_STRICT || process.execArgv + .map((e) => e.toLowerCase().replace(/_/g, '-')) + .includes('--use-strict'); + } + // This returns a code preview for arbitrary input code. function getInputPreview(input, callback) { // For similar reasons as `defaultEval`, wrap expressions starting with a @@ -269,8 +304,11 @@ function setupPreview(repl, contextSymbol, bufferSymbol, active) { // may be inspected. } else if (preview.exceptionDetails && (result.className === 'EvalError' || - result.className === 'SyntaxError' || - result.className === 'ReferenceError')) { + result.className === 'SyntaxError' || + // Report ReferenceError in case the strict mode is active + // for input that has no completions. + (result.className === 'ReferenceError' && + (hasCompletions || !isInStrictMode(repl))))) { callback(null, null); } else if (result.objectId) { // The writer options might change and have influence on the inspect @@ -316,14 +354,9 @@ function setupPreview(repl, contextSymbol, bufferSymbol, active) { return; } + hasCompletions = false; + // Add the autocompletion preview. - // TODO(BridgeAR): Trigger the input preview after the completion preview. - // That way it's possible to trigger the input prefix including the - // potential completion suffix. To do so, we also have to change the - // behavior of `enter` and `escape`: - // Enter should automatically add the suffix to the current line as long as - // escape was not pressed. We might even remove the preview in case any - // cursor movement is triggered. const insertPreview = false; showCompletionPreview(repl.line, insertPreview); @@ -397,9 +430,17 @@ function setupPreview(repl, contextSymbol, bufferSymbol, active) { moveCursor(repl.output, 0, -rows - 1); }; - getInputPreview(line, inputPreviewCallback); + let previewLine = line; + + if (completionPreview !== null && + isCursorAtInputEnd() && + escaped !== repl.line) { + previewLine += completionPreview; + } + + getInputPreview(previewLine, inputPreviewCallback); if (wrapped) { - getInputPreview(line, inputPreviewCallback); + getInputPreview(previewLine, inputPreviewCallback); } wrapped = false; }; @@ -679,6 +720,8 @@ function setupReverseSearch(repl) { } module.exports = { + REPL_MODE_SLOPPY: Symbol('repl-sloppy'), + REPL_MODE_STRICT, isRecoverableError, kStandaloneREPL: Symbol('kStandaloneREPL'), setupPreview, diff --git a/lib/internal/source_map/source_map.js b/lib/internal/source_map/source_map.js index 35ec3ae740e887..2cd70c5c944e19 100644 --- a/lib/internal/source_map/source_map.js +++ b/lib/internal/source_map/source_map.js @@ -196,15 +196,14 @@ class SourceMap { return {}; } else if (!entry) { return {}; - } else { - return { - generatedLine: entry[0], - generatedColumn: entry[1], - originalSource: entry[2], - originalLine: entry[3], - originalColumn: entry[4] - }; } + return { + generatedLine: entry[0], + generatedColumn: entry[1], + originalSource: entry[2], + originalLine: entry[3], + originalColumn: entry[4] + }; } /** diff --git a/lib/internal/source_map/source_map_cache.js b/lib/internal/source_map/source_map_cache.js index b64af7eed6e097..06b1a2a5f52289 100644 --- a/lib/internal/source_map/source_map_cache.js +++ b/lib/internal/source_map/source_map_cache.js @@ -192,9 +192,8 @@ function sourceMapCacheToObject() { if (ObjectKeys(obj).length === 0) { return undefined; - } else { - return obj; } + return obj; } // Since WeakMap can't be iterated over, we use Module._cache's @@ -243,9 +242,8 @@ function findSourceMap(uri, error) { } if (sourceMap && sourceMap.data) { return new SourceMap(sourceMap.data); - } else { - return undefined; } + return undefined; } module.exports = { diff --git a/lib/internal/streams/from.js b/lib/internal/streams/from.js index 6752679ae3bc2b..13e8a73980ddd1 100644 --- a/lib/internal/streams/from.js +++ b/lib/internal/streams/from.js @@ -33,6 +33,8 @@ function from(Readable, iterable, opts) { const readable = new Readable({ objectMode: true, + highWaterMark: 1, + // TODO(ronag): What options should be allowed? ...opts }); diff --git a/lib/internal/streams/pipeline.js b/lib/internal/streams/pipeline.js index cf9d7868916a9e..4786b906f4324c 100644 --- a/lib/internal/streams/pipeline.js +++ b/lib/internal/streams/pipeline.js @@ -107,10 +107,9 @@ function makeAsyncIterable(val) { } else if (isReadable(val)) { // Legacy streams are not Iterable. return fromReadable(val); - } else { - throw new ERR_INVALID_ARG_TYPE( - 'val', ['Readable', 'Iterable', 'AsyncIterable'], val); } + throw new ERR_INVALID_ARG_TYPE( + 'val', ['Readable', 'Iterable', 'AsyncIterable'], val); } async function* fromReadable(val) { diff --git a/lib/internal/timers.js b/lib/internal/timers.js index bb80f57ee295c5..1577e31779ddc6 100644 --- a/lib/internal/timers.js +++ b/lib/internal/timers.js @@ -338,7 +338,7 @@ function insertGuarded(item, refed, start) { } function insert(item, msecs, start = getLibuvNow()) { - // Truncate so that accuracy of sub-milisecond timers is not assumed. + // Truncate so that accuracy of sub-millisecond timers is not assumed. msecs = MathTrunc(msecs); item._idleStart = start; diff --git a/lib/internal/url.js b/lib/internal/url.js index efb842a074d750..78f5b32745a043 100644 --- a/lib/internal/url.js +++ b/lib/internal/url.js @@ -228,9 +228,8 @@ class URLSearchParams { return `${this.constructor.name} {\n ${output.join(',\n ')} }`; } else if (output.length) { return `${this.constructor.name} { ${output.join(separator)} }`; - } else { - return `${this.constructor.name} {}`; } + return `${this.constructor.name} {}`; } } @@ -1315,16 +1314,15 @@ function getPathFromURLWin32(url) { // already taken care of that for us. Note that this only // causes IDNs with an appropriate `xn--` prefix to be decoded. return `\\\\${domainToUnicode(hostname)}${pathname}`; - } else { - // Otherwise, it's a local path that requires a drive letter - const letter = pathname.codePointAt(1) | 0x20; - const sep = pathname[2]; - if (letter < CHAR_LOWERCASE_A || letter > CHAR_LOWERCASE_Z || // a..z A..Z - (sep !== ':')) { - throw new ERR_INVALID_FILE_URL_PATH('must be absolute'); - } - return pathname.slice(1); } + // Otherwise, it's a local path that requires a drive letter + const letter = pathname.codePointAt(1) | 0x20; + const sep = pathname[2]; + if (letter < CHAR_LOWERCASE_A || letter > CHAR_LOWERCASE_Z || // a..z A..Z + (sep !== ':')) { + throw new ERR_INVALID_FILE_URL_PATH('must be absolute'); + } + return pathname.slice(1); } function getPathFromURLPosix(url) { diff --git a/lib/internal/vm/module.js b/lib/internal/vm/module.js index 992753ef680dbb..1d26e7a601b5bc 100644 --- a/lib/internal/vm/module.js +++ b/lib/internal/vm/module.js @@ -219,8 +219,7 @@ class Module { 'must be one of linked, evaluated, or errored' ); } - const result = this[kWrap].evaluate(timeout, breakOnSigint); - return { __proto__: null, result }; + await this[kWrap].evaluate(timeout, breakOnSigint); } [customInspectSymbol](depth, options) { diff --git a/lib/net.js b/lib/net.js index ee0ffebe0ec45e..ff9a37be360467 100644 --- a/lib/net.js +++ b/lib/net.js @@ -541,9 +541,8 @@ ObjectDefineProperty(Socket.prototype, 'readyState', { return 'readOnly'; } else if (!this.readable && this.writable) { return 'writeOnly'; - } else { - return 'closed'; } + return 'closed'; } }); @@ -1520,9 +1519,8 @@ Server.prototype.address = function() { return out; } else if (this._pipeName) { return this._pipeName; - } else { - return null; } + return null; }; function onconnection(err, clientHandle) { diff --git a/lib/perf_hooks.js b/lib/perf_hooks.js index efc92ca8c4aee4..2ce0d29464a9bd 100644 --- a/lib/perf_hooks.js +++ b/lib/perf_hooks.js @@ -341,11 +341,12 @@ class PerformanceObserver extends AsyncResource { if (typeof options !== 'object' || options === null) { throw new ERR_INVALID_ARG_TYPE('options', 'Object', options); } - if (!ArrayIsArray(options.entryTypes)) { - throw new ERR_INVALID_OPT_VALUE('entryTypes', options); + const { entryTypes } = options; + if (!ArrayIsArray(entryTypes)) { + throw new ERR_INVALID_OPT_VALUE('entryTypes', entryTypes); } - const entryTypes = options.entryTypes.filter(filterTypes).map(mapTypes); - if (entryTypes.length === 0) { + const filteredEntryTypes = entryTypes.filter(filterTypes).map(mapTypes); + if (filteredEntryTypes.length === 0) { throw new ERR_VALID_PERFORMANCE_ENTRY_TYPE(); } this.disconnect(); @@ -353,7 +354,7 @@ class PerformanceObserver extends AsyncResource { this[kBuffer][kEntries] = []; L.init(this[kBuffer][kEntries]); this[kBuffering] = Boolean(options.buffered); - for (const entryType of entryTypes) { + for (const entryType of filteredEntryTypes) { const list = getObserversList(entryType); if (this[kTypes][entryType]) continue; const item = { obs: this }; diff --git a/lib/repl.js b/lib/repl.js index 3186e0a31b8c86..41aaf126e39b94 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -63,7 +63,6 @@ const { } = primordials; const { - builtinLibs, makeRequireFunction, addBuiltinLibsToObject } = require('internal/modules/cjs/helpers'); @@ -86,6 +85,8 @@ const { } = require('internal/readline/utils'); const { Console } = require('console'); const CJSModule = require('internal/modules/cjs/loader').Module; +let _builtinLibs = [...CJSModule.builtinModules] + .filter((e) => !e.startsWith('_')); const domain = require('domain'); const debug = require('internal/util/debuglog').debuglog('repl'); const { @@ -99,10 +100,14 @@ const { overrideStackTrace, } = require('internal/errors'); const { sendInspectorCommand } = require('internal/util/inspector'); -const experimentalREPLAwait = require('internal/options').getOptionValue( +const { getOptionValue } = require('internal/options'); +const experimentalREPLAwait = getOptionValue( '--experimental-repl-await' ); +const pendingDeprecation = getOptionValue('--pending-deprecation'); const { + REPL_MODE_SLOPPY, + REPL_MODE_STRICT, isRecoverableError, kStandaloneREPL, setupPreview, @@ -153,11 +158,9 @@ module.paths = CJSModule._nodeModulePaths(module.filename); // This is the default "writer" value, if none is passed in the REPL options, // and it can be overridden by custom print functions, such as `probe` or // `eyes.js`. -const writer = exports.writer = (obj) => inspect(obj, writer.options); +const writer = (obj) => inspect(obj, writer.options); writer.options = { ...inspect.defaultOptions, showProxy: true }; -exports._builtinLibs = builtinLibs; - function REPLServer(prompt, stream, eval_, @@ -217,13 +220,44 @@ function REPLServer(prompt, const preview = options.terminal && (options.preview !== undefined ? !!options.preview : !eval_); - this.inputStream = options.input; - this.outputStream = options.output; + ObjectDefineProperty(this, 'inputStream', { + get: pendingDeprecation ? + deprecate(() => this.input, + 'repl.inputStream and repl.outputStream is deprecated. ' + + 'Use repl.input and repl.output instead', + 'DEP0141') : + () => this.input, + set: pendingDeprecation ? + deprecate((val) => this.input = val, + 'repl.inputStream and repl.outputStream is deprecated. ' + + 'Use repl.input and repl.output instead', + 'DEP0141') : + (val) => this.input = val, + enumerable: false, + configurable: true + }); + ObjectDefineProperty(this, 'outputStream', { + get: pendingDeprecation ? + deprecate(() => this.output, + 'repl.inputStream and repl.outputStream is deprecated. ' + + 'Use repl.input and repl.output instead', + 'DEP0141') : + () => this.output, + set: pendingDeprecation ? + deprecate((val) => this.output = val, + 'repl.inputStream and repl.outputStream is deprecated. ' + + 'Use repl.input and repl.output instead', + 'DEP0141') : + (val) => this.output = val, + enumerable: false, + configurable: true + }); + this.useColors = !!options.useColors; this._domain = options.domain || domain.create(); this.useGlobal = !!useGlobal; this.ignoreUndefined = !!ignoreUndefined; - this.replMode = replMode || exports.REPL_MODE_SLOPPY; + this.replMode = replMode || module.exports.REPL_MODE_SLOPPY; this.underscoreAssigned = false; this.last = undefined; this.underscoreErrAssigned = false; @@ -242,7 +276,7 @@ function REPLServer(prompt, if (options[kStandaloneREPL]) { // It is possible to introspect the running REPL accessing this variable // from inside the REPL. This is useful for anyone working on the REPL. - exports.repl = this; + module.exports.repl = this; } else if (!addedNewListener) { // Add this listener only once and use a WeakSet that contains the REPLs // domains. Otherwise we'd have to add a single listener to each REPL @@ -363,8 +397,8 @@ function REPLServer(prompt, } while (true) { try { - if (!/^\s*$/.test(code) && - self.replMode === exports.REPL_MODE_STRICT) { + if (self.replMode === module.exports.REPL_MODE_STRICT && + !/^\s*$/.test(code)) { // "void 0" keeps the repl from returning "use strict" as the result // value for statements and declarations that don't return a value. code = `'use strict'; void 0;\n${code}`; @@ -544,7 +578,7 @@ function REPLServer(prompt, e.stack = e.stack .replace(/^repl:\d+\r?\n/, '') .replace(/^\s+at\s.*\n?/gm, ''); - } else if (self.replMode === exports.REPL_MODE_STRICT) { + } else if (self.replMode === module.exports.REPL_MODE_STRICT) { e.stack = e.stack.replace(/(\s+at\s+repl:)(\d+)/, (_, pre, line) => pre + (line - 1)); } @@ -594,16 +628,13 @@ function REPLServer(prompt, } // Normalize line endings. errStack += errStack.endsWith('\n') ? '' : '\n'; - self.outputStream.write(errStack); + self.output.write(errStack); self.clearBufferedCommand(); self.lines.level = []; self.displayPrompt(); } }); - self.resetContext(); - self.lines.level = []; - self.clearBufferedCommand(); ObjectDefineProperty(this, 'bufferedCommand', { get: deprecate(() => self[kBufferedCommandSymbol], @@ -615,29 +646,27 @@ function REPLServer(prompt, enumerable: true }); - // Figure out which "complete" function to use. - self.completer = (typeof options.completer === 'function') ? - options.completer : completer; - function completer(text, cb) { complete.call(self, text, self.editorMode ? self.completeOnEditorMode(cb) : cb); } Interface.call(this, { - input: self.inputStream, - output: self.outputStream, - completer: self.completer, + input: options.input, + output: options.output, + completer: options.completer || completer, terminal: options.terminal, historySize: options.historySize, prompt }); + self.resetContext(); + this.commands = ObjectCreate(null); defineDefaultCommands(this); // Figure out which "writer" function to use - self.writer = options.writer || exports.writer; + self.writer = options.writer || module.exports.writer; if (self.writer === writer) { // Conditionally turn on ANSI coloring. @@ -750,7 +779,7 @@ function REPLServer(prompt, return; } if (!self[kBufferedCommandSymbol]) { - self.outputStream.write('Invalid REPL keyword\n'); + self.output.write('Invalid REPL keyword\n'); finish(null); return; } @@ -767,7 +796,7 @@ function REPLServer(prompt, _memory.call(self, cmd); if (e && !self[kBufferedCommandSymbol] && cmd.trim().startsWith('npm ')) { - self.outputStream.write('npm should be run outside of the ' + + self.output.write('npm should be run outside of the ' + 'node repl, in your normal shell.\n' + '(Press Control-D to exit.)\n'); self.displayPrompt(); @@ -784,9 +813,8 @@ function REPLServer(prompt, self[kBufferedCommandSymbol] += cmd + '\n'; self.displayPrompt(); return; - } else { - self._domain.emit('error', e.err || e); } + self._domain.emit('error', e.err || e); } // Clear buffer if no SyntaxErrors @@ -803,7 +831,7 @@ function REPLServer(prompt, if (!self.underscoreAssigned) { self.last = ret; } - self.outputStream.write(self.writer(ret) + '\n'); + self.output.write(self.writer(ret) + '\n'); } // Display prompt again @@ -813,10 +841,10 @@ function REPLServer(prompt, self.on('SIGCONT', function onSigCont() { if (self.editorMode) { - self.outputStream.write(`${self._initialPrompt}.editor\n`); - self.outputStream.write( + self.output.write(`${self._initialPrompt}.editor\n`); + self.output.write( '// Entering editor mode (^D to finish, ^C to cancel)\n'); - self.outputStream.write(`${self[kBufferedCommandSymbol]}\n`); + self.output.write(`${self[kBufferedCommandSymbol]}\n`); self.prompt(true); } else { self.displayPrompt(true); @@ -849,7 +877,7 @@ function REPLServer(prompt, self.cursor === 0 && self.line.length === 0) { self.clearLine(); } - clearPreview(); + clearPreview(key); if (!reverseSearch(d, key)) { ttyWrite(d, key); showPreview(); @@ -894,22 +922,12 @@ function REPLServer(prompt, ObjectSetPrototypeOf(REPLServer.prototype, Interface.prototype); ObjectSetPrototypeOf(REPLServer, Interface); -exports.REPLServer = REPLServer; - -exports.REPL_MODE_SLOPPY = Symbol('repl-sloppy'); -exports.REPL_MODE_STRICT = Symbol('repl-strict'); - // Prompt is a string to print on each line for the prompt, // source is a stream to use for I/O, defaulting to stdin/stdout. -exports.start = function(prompt, - source, - eval_, - useGlobal, - ignoreUndefined, - replMode) { +function start(prompt, source, eval_, useGlobal, ignoreUndefined, replMode) { return new REPLServer( prompt, source, eval_, useGlobal, ignoreUndefined, replMode); -}; +} REPLServer.prototype.setupHistory = function setupHistory(historyFile, cb) { history(this, historyFile, cb); @@ -956,7 +974,7 @@ REPLServer.prototype.createContext = function() { } } context.global = context; - const _console = new Console(this.outputStream); + const _console = new Console(this.output); ObjectDefineProperty(context, 'console', { configurable: true, writable: true, @@ -964,18 +982,18 @@ REPLServer.prototype.createContext = function() { }); } - const module = new CJSModule(''); - module.paths = CJSModule._resolveLookupPaths('', parentModule); + const replModule = new CJSModule(''); + replModule.paths = CJSModule._resolveLookupPaths('', parentModule); ObjectDefineProperty(context, 'module', { configurable: true, writable: true, - value: module + value: replModule }); ObjectDefineProperty(context, 'require', { configurable: true, writable: true, - value: makeRequireFunction(module) + value: makeRequireFunction(replModule) }); addBuiltinLibsToObject(context); @@ -987,6 +1005,7 @@ REPLServer.prototype.resetContext = function() { this.context = this.createContext(); this.underscoreAssigned = false; this.underscoreErrAssigned = false; + // TODO(BridgeAR): Deprecate the lines. this.lines = []; this.lines.level = []; @@ -997,7 +1016,7 @@ REPLServer.prototype.resetContext = function() { this.last = value; if (!this.underscoreAssigned) { this.underscoreAssigned = true; - this.outputStream.write('Expression assignment to _ now disabled.\n'); + this.output.write('Expression assignment to _ now disabled.\n'); } } }); @@ -1009,7 +1028,7 @@ REPLServer.prototype.resetContext = function() { this.lastError = value; if (!this.underscoreErrAssigned) { this.underscoreErrAssigned = true; - this.outputStream.write( + this.output.write( 'Expression assignment to _error now disabled.\n'); } } @@ -1044,7 +1063,7 @@ REPLServer.prototype.turnOffEditorMode = deprecate( 'REPLServer.turnOffEditorMode() is deprecated', 'DEP0078'); -const requireRE = /\brequire\s*\(['"](([\w@./-]+\/)?(?:[\w@./-]*))/; +const requireRE = /\brequire\s*\(\s*['"`](([\w@./-]+\/)?(?:[\w@./-]*))(?![^'"`])$/; const fsAutoCompleteRE = /fs(?:\.promises)?\.\s*[a-z][a-zA-Z]+\(\s*["'](.*)/; const simpleExpressionRE = /(?:[a-zA-Z_$](?:\w|\$)*\.)*[a-zA-Z_$](?:\w|\$)*\.?$/; @@ -1092,8 +1111,13 @@ REPLServer.prototype.complete = function() { this.completer.apply(this, arguments); }; -// TODO: Native module names should be auto-resolved. -// That improves the auto completion. +function gracefulOperation(fn, args, alternative) { + try { + return fn(...args); + } catch { + return alternative; + } +} // Provide a list of completions for the given leading text. This is // given to the readline interface for handling tab completion. @@ -1115,26 +1139,25 @@ function complete(line, callback) { // REPL commands (e.g. ".break"). let filter; - let match = line.match(/^\s*\.(\w*)$/); - if (match) { + if (/^\s*\.(\w*)$/.test(line)) { completionGroups.push(ObjectKeys(this.commands)); - completeOn = match[1]; - if (match[1].length) { - filter = match[1]; + completeOn = line.match(/^\s*\.(\w*)$/)[1]; + if (completeOn.length) { + filter = completeOn; } completionGroupsLoaded(); - } else if (match = line.match(requireRE)) { + } else if (requireRE.test(line)) { // require('...') - const exts = ObjectKeys(this.context.require.extensions); - const indexRe = new RegExp('^index(?:' + exts.map(regexpEscape).join('|') + - ')$'); + const extensions = ObjectKeys(this.context.require.extensions); + const indexes = extensions.map((extension) => `index${extension}`); + indexes.push('package.json', 'index'); const versionedFileNamesRe = /-\d+\.\d+/; + const match = line.match(requireRE); completeOn = match[1]; const subdir = match[2] || ''; - filter = match[1]; - let dir, files, subfiles, isDirectory; + filter = completeOn; group = []; let paths = []; @@ -1148,41 +1171,34 @@ function complete(line, callback) { paths = module.paths.concat(CJSModule.globalPaths); } - for (let i = 0; i < paths.length; i++) { - dir = path.resolve(paths[i], subdir); - try { - files = fs.readdirSync(dir); - } catch { - continue; - } - for (let f = 0; f < files.length; f++) { - const name = files[f]; - const ext = path.extname(name); - const base = name.slice(0, -ext.length); - if (versionedFileNamesRe.test(base) || name === '.npm') { + for (let dir of paths) { + dir = path.resolve(dir, subdir); + const dirents = gracefulOperation( + fs.readdirSync, + [dir, { withFileTypes: true }], + [] + ); + for (const dirent of dirents) { + if (versionedFileNamesRe.test(dirent.name) || dirent.name === '.npm') { // Exclude versioned names that 'npm' installs. continue; } - const abs = path.resolve(dir, name); - try { - isDirectory = fs.statSync(abs).isDirectory(); - } catch { + const extension = path.extname(dirent.name); + const base = dirent.name.slice(0, -extension.length); + if (!dirent.isDirectory()) { + if (extensions.includes(extension) && (!subdir || base !== 'index')) { + group.push(`${subdir}${base}`); + } continue; } - if (isDirectory) { - group.push(subdir + name + '/'); - try { - subfiles = fs.readdirSync(abs); - } catch { - continue; - } - for (let s = 0; s < subfiles.length; s++) { - if (indexRe.test(subfiles[s])) { - group.push(subdir + name); - } + group.push(`${subdir}${dirent.name}/`); + const absolute = path.resolve(dir, dirent.name); + const subfiles = gracefulOperation(fs.readdirSync, [absolute], []); + for (const subfile of subfiles) { + if (indexes.includes(subfile)) { + group.push(`${subdir}${dirent.name}`); + break; } - } else if (exts.includes(ext) && (!subdir || base !== 'index')) { - group.push(subdir + base); } } } @@ -1191,15 +1207,14 @@ function complete(line, callback) { } if (!subdir) { - completionGroups.push(exports._builtinLibs); + completionGroups.push(_builtinLibs); } completionGroupsLoaded(); - } else if (match = line.match(fsAutoCompleteRE)) { - - let filePath = match[1]; - let fileList; + } else if (fsAutoCompleteRE.test(line)) { filter = ''; + let filePath = line.match(fsAutoCompleteRE)[1]; + let fileList; try { fileList = fs.readdirSync(filePath, { withFileTypes: true }); @@ -1230,7 +1245,7 @@ function complete(line, callback) { // foo<|> # all scope vars with filter 'foo' // foo.<|> # completions for 'foo' with filter '' } else if (line.length === 0 || /\w|\.|\$/.test(line[line.length - 1])) { - match = simpleExpressionRE.exec(line); + const match = simpleExpressionRE.exec(line); if (line.length !== 0 && !match) { completionGroupsLoaded(); return; @@ -1498,7 +1513,7 @@ function defineDefaultCommands(repl) { action: function() { this.clearBufferedCommand(); if (!this.useGlobal) { - this.outputStream.write('Clearing context...\n'); + this.output.write('Clearing context...\n'); this.resetContext(); } this.displayPrompt(); @@ -1525,9 +1540,9 @@ function defineDefaultCommands(repl) { const cmd = this.commands[name]; const spaces = ' '.repeat(longestNameLength - name.length + 3); const line = `.${name}${cmd.help ? spaces + cmd.help : ''}\n`; - this.outputStream.write(line); + this.output.write(line); } - this.outputStream.write('\nPress ^C to abort current expression, ' + + this.output.write('\nPress ^C to abort current expression, ' + '^D to exit the repl\n'); this.displayPrompt(); } @@ -1538,9 +1553,9 @@ function defineDefaultCommands(repl) { action: function(file) { try { fs.writeFileSync(file, this.lines.join('\n')); - this.outputStream.write(`Session saved to: ${file}\n`); + this.output.write(`Session saved to: ${file}\n`); } catch { - this.outputStream.write(`Failed to save: ${file}\n`); + this.output.write(`Failed to save: ${file}\n`); } this.displayPrompt(); } @@ -1558,12 +1573,12 @@ function defineDefaultCommands(repl) { _turnOffEditorMode(this); this.write('\n'); } else { - this.outputStream.write( + this.output.write( `Failed to load: ${file} is not a valid file\n` ); } } catch { - this.outputStream.write(`Failed to load: ${file}\n`); + this.output.write(`Failed to load: ${file}\n`); } this.displayPrompt(); } @@ -1573,20 +1588,39 @@ function defineDefaultCommands(repl) { help: 'Enter editor mode', action() { _turnOnEditorMode(this); - this.outputStream.write( + this.output.write( '// Entering editor mode (^D to finish, ^C to cancel)\n'); } }); } } -function regexpEscape(s) { - return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); -} - function Recoverable(err) { this.err = err; } ObjectSetPrototypeOf(Recoverable.prototype, SyntaxError.prototype); ObjectSetPrototypeOf(Recoverable, SyntaxError); -exports.Recoverable = Recoverable; + +module.exports = { + start, + writer, + REPLServer, + REPL_MODE_SLOPPY, + REPL_MODE_STRICT, + Recoverable +}; + +ObjectDefineProperty(module.exports, '_builtinLibs', { + get: pendingDeprecation ? deprecate( + () => _builtinLibs, + 'repl._builtinLibs is deprecated. Check module.builtinModules instead', + 'DEP0142' + ) : () => _builtinLibs, + set: pendingDeprecation ? deprecate( + (val) => _builtinLibs = val, + 'repl._builtinLibs is deprecated. Check module.builtinModules instead', + 'DEP0142' + ) : (val) => _builtinLibs = val, + enumerable: false, + configurable: true +}); diff --git a/lib/v8.js b/lib/v8.js index 11ca7fa640f27b..56e3e6056214ca 100644 --- a/lib/v8.js +++ b/lib/v8.js @@ -240,14 +240,13 @@ class DefaultDeserializer extends Deserializer { return new ctor(this.buffer.buffer, offset, byteLength / BYTES_PER_ELEMENT); - } else { - // Copy to an aligned buffer first. - const buffer_copy = Buffer.allocUnsafe(byteLength); - copy(this.buffer, buffer_copy, 0, byteOffset, byteOffset + byteLength); - return new ctor(buffer_copy.buffer, - buffer_copy.byteOffset, - byteLength / BYTES_PER_ELEMENT); } + // Copy to an aligned buffer first. + const buffer_copy = Buffer.allocUnsafe(byteLength); + copy(this.buffer, buffer_copy, 0, byteOffset, byteOffset + byteLength); + return new ctor(buffer_copy.buffer, + buffer_copy.byteOffset, + byteLength / BYTES_PER_ELEMENT); } } diff --git a/lib/vm.js b/lib/vm.js index fd81e9da8b0515..ddd70fcbe5abce 100644 --- a/lib/vm.js +++ b/lib/vm.js @@ -127,9 +127,8 @@ class Script extends ContextifyScript { const { breakOnSigint, args } = getRunInContextArgs(options); if (breakOnSigint && process.listenerCount('SIGINT') > 0) { return sigintHandlersWrap(super.runInThisContext, this, args); - } else { - return super.runInThisContext(...args); } + return super.runInThisContext(...args); } runInContext(contextifiedObject, options) { @@ -138,9 +137,8 @@ class Script extends ContextifyScript { if (breakOnSigint && process.listenerCount('SIGINT') > 0) { return sigintHandlersWrap(super.runInContext, this, [contextifiedObject, ...args]); - } else { - return super.runInContext(contextifiedObject, ...args); } + return super.runInContext(contextifiedObject, ...args); } runInNewContext(contextObject, options) { @@ -313,7 +311,6 @@ function compileFunction(code, params, options = {}) { produceCachedData = false, parsingContext = undefined, contextExtensions = [], - importModuleDynamically, } = options; validateString(filename, 'options.filename'); @@ -361,22 +358,6 @@ function compileFunction(code, params, options = {}) { result.function.cachedData = result.cachedData; } - if (importModuleDynamically !== undefined) { - if (typeof importModuleDynamically !== 'function') { - throw new ERR_INVALID_ARG_TYPE('options.importModuleDynamically', - 'function', - importModuleDynamically); - } - const { importModuleDynamicallyWrap } = - require('internal/vm/module'); - const { callbackMap } = internalBinding('module_wrap'); - const wrapped = importModuleDynamicallyWrap(importModuleDynamically); - const func = result.function; - callbackMap.set(result.cacheKey, { - importModuleDynamically: (s, _k) => wrapped(s, func), - }); - } - return result.function; } diff --git a/lib/zlib.js b/lib/zlib.js index 502ee61aa3bd9d..1c317af46d1f20 100644 --- a/lib/zlib.js +++ b/lib/zlib.js @@ -613,9 +613,11 @@ function Zlib(opts, mode) { mode === UNZIP)) { windowBits = 0; } else { + // `{ windowBits: 8 }` is valid for deflate but not gzip. + const min = Z_MIN_WINDOWBITS + (mode === GZIP ? 1 : 0); windowBits = checkRangesOrGetDefault( opts.windowBits, 'options.windowBits', - Z_MIN_WINDOWBITS, Z_MAX_WINDOWBITS, Z_DEFAULT_WINDOWBITS); + min, Z_MAX_WINDOWBITS, Z_DEFAULT_WINDOWBITS); } level = checkRangesOrGetDefault( @@ -760,15 +762,14 @@ function createConvenienceMethod(ctor, sync) { return function syncBufferWrapper(buffer, opts) { return zlibBufferSync(new ctor(opts), buffer); }; - } else { - return function asyncBufferWrapper(buffer, opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - return zlibBuffer(new ctor(opts), buffer, callback); - }; } + return function asyncBufferWrapper(buffer, opts, callback) { + if (typeof opts === 'function') { + callback = opts; + opts = {}; + } + return zlibBuffer(new ctor(opts), buffer, callback); + }; } const kMaxBrotliParam = MathMax(...ObjectKeys(constants).map((key) => { diff --git a/node.gyp b/node.gyp index 3dadad15c9e193..2c1a26c28cc79f 100644 --- a/node.gyp +++ b/node.gyp @@ -378,6 +378,9 @@ 'conditions': [ [ 'error_on_warn=="true"', { 'cflags': ['-Werror'], + 'xcode_settings': { + 'WARNING_CFLAGS': [ '-Werror' ], + }, }], [ 'node_intermediate_lib_type=="static_library" and ' 'node_shared=="true" and OS=="aix"', { @@ -642,6 +645,8 @@ 'src/base_object.h', 'src/base_object-inl.h', 'src/base64.h', + 'src/callback_queue.h', + 'src/callback_queue-inl.h', 'src/connect_wrap.h', 'src/connection_wrap.h', 'src/debug_utils.h', @@ -755,6 +760,9 @@ 'conditions': [ [ 'error_on_warn=="true"', { 'cflags': ['-Werror'], + 'xcode_settings': { + 'WARNING_CFLAGS': [ '-Werror' ], + }, }], [ 'node_builtin_modules_path!=""', { 'defines': [ 'NODE_BUILTIN_MODULES_PATH="<(node_builtin_modules_path)"' ] diff --git a/src/README.md b/src/README.md index e2b256fba20de8..6d6e33ab275e8f 100644 --- a/src/README.md +++ b/src/README.md @@ -395,21 +395,28 @@ void Initialize(Local target, NODE_MODULE_CONTEXT_AWARE_INTERNAL(cares_wrap, Initialize) ``` - + #### Per-binding state Some internal bindings, such as the HTTP parser, maintain internal state that only affects that particular binding. In that case, one common way to store -that state is through the use of `Environment::BindingScope`, which gives all -new functions created within it access to an object for storing such state. +that state is through the use of `Environment::AddBindingData`, which gives +binding functions access to an object for storing such state. That object is always a [`BaseObject`][]. +Its class needs to have a static `binding_data_name` field that based on a +constant string, in order to disambiguate it from other classes of this type, +and which could e.g. match the binding’s name (in the example above, that would +be `cares_wrap`). + ```c++ // In the HTTP parser source code file: class BindingData : public BaseObject { public: BindingData(Environment* env, Local obj) : BaseObject(env, obj) {} + static constexpr FastStringKey binding_data_name { "http_parser" }; + std::vector parser_buffer; bool parser_buffer_in_use = false; @@ -418,22 +425,21 @@ class BindingData : public BaseObject { // Available for binding functions, e.g. the HTTP Parser constructor: static void New(const FunctionCallbackInfo& args) { - BindingData* binding_data = Unwrap(args.Data()); + BindingData* binding_data = Environment::GetBindingData(args); new Parser(binding_data, args.This()); } -// ... because the initialization function told the Environment to use this -// BindingData class for all functions created by it: +// ... because the initialization function told the Environment to store the +// BindingData object: void InitializeHttpParser(Local target, Local unused, Local context, void* priv) { Environment* env = Environment::GetCurrent(context); - Environment::BindingScope binding_scope(env); - if (!binding_scope) return; - BindingData* binding_data = binding_scope.data; + BindingData* const binding_data = + env->AddBindingData(context, target); + if (binding_data == nullptr) return; - // Created within the Environment::BindingScope Local t = env->NewFunctionTemplate(Parser::New); ... } diff --git a/src/api/callback.cc b/src/api/callback.cc index f7e7ddedfae377..c8934e1cd33a36 100644 --- a/src/api/callback.cc +++ b/src/api/callback.cc @@ -84,9 +84,13 @@ void InternalCallbackScope::Close() { closed_ = true; if (!env_->can_call_into_js()) return; - if (failed_ && !env_->is_main_thread() && env_->is_stopping()) { - env_->async_hooks()->clear_async_id_stack(); - } + auto perform_stopping_check = [&]() { + if (env_->is_stopping()) { + MarkAsFailed(); + env_->async_hooks()->clear_async_id_stack(); + } + }; + perform_stopping_check(); if (!failed_ && async_context_.async_id != 0 && !skip_hooks_) { AsyncWrap::EmitAfter(env_, async_context_.async_id); @@ -109,6 +113,8 @@ void InternalCallbackScope::Close() { if (!tick_info->has_tick_scheduled()) { MicrotasksScope::PerformCheckpoint(env_->isolate()); + + perform_stopping_check(); } // Make sure the stack unwound properly. If there are nested MakeCallback's @@ -136,6 +142,7 @@ void InternalCallbackScope::Close() { if (tick_callback->Call(env_->context(), process, 0, nullptr).IsEmpty()) { failed_ = true; } + perform_stopping_check(); } MaybeLocal InternalMakeCallback(Environment* env, diff --git a/src/api/environment.cc b/src/api/environment.cc index b9ca6ca7451926..2b7a7023b5f33c 100644 --- a/src/api/environment.cc +++ b/src/api/environment.cc @@ -16,7 +16,6 @@ using errors::TryCatchScope; using v8::Array; using v8::Context; using v8::EscapableHandleScope; -using v8::FinalizationGroup; using v8::Function; using v8::FunctionCallbackInfo; using v8::HandleScope; @@ -82,15 +81,6 @@ static MaybeLocal PrepareStackTraceCallback(Local context, return result; } -static void HostCleanupFinalizationGroupCallback( - Local context, Local group) { - Environment* env = Environment::GetCurrent(context); - if (env == nullptr) { - return; - } - env->RegisterFinalizationGroupForCleanup(group); -} - void* NodeArrayBufferAllocator::Allocate(size_t size) { void* ret; if (zero_fill_field_ || per_process::cli_options->zero_fill_all_buffers) @@ -259,11 +249,6 @@ void SetIsolateMiscHandlers(v8::Isolate* isolate, const IsolateSettings& s) { s.promise_reject_callback : task_queue::PromiseRejectCallback; isolate->SetPromiseRejectCallback(promise_reject_cb); - auto* host_cleanup_cb = s.host_cleanup_finalization_group_callback ? - s.host_cleanup_finalization_group_callback : - HostCleanupFinalizationGroupCallback; - isolate->SetHostCleanupFinalizationGroupCallback(host_cleanup_cb); - if (s.flags & DETAILED_SOURCE_POSITIONS_FOR_PROFILING) v8::CpuProfiler::UseDetailedSourcePositionsForProfiling(isolate); } diff --git a/src/async_wrap.cc b/src/async_wrap.cc index 42837e09818ec2..602b0e9f5d5841 100644 --- a/src/async_wrap.cc +++ b/src/async_wrap.cc @@ -39,7 +39,9 @@ using v8::HandleScope; using v8::Integer; using v8::Isolate; using v8::Local; +using v8::Maybe; using v8::MaybeLocal; +using v8::Name; using v8::Number; using v8::Object; using v8::ObjectTemplate; @@ -189,46 +191,107 @@ void AsyncWrap::EmitAfter(Environment* env, double async_id) { class PromiseWrap : public AsyncWrap { public: - enum InternalFields { - kIsChainedPromiseField = AsyncWrap::kInternalFieldCount, - kInternalFieldCount - }; PromiseWrap(Environment* env, Local object, bool silent) : AsyncWrap(env, object, PROVIDER_PROMISE, kInvalidAsyncId, silent) { MakeWeak(); } + PromiseWrap(Environment* env, Local object, double asyncId, + double triggerAsyncId) + : AsyncWrap(env, object, PROVIDER_PROMISE, asyncId, triggerAsyncId) { + MakeWeak(); + } + SET_NO_MEMORY_INFO() SET_MEMORY_INFO_NAME(PromiseWrap) SET_SELF_SIZE(PromiseWrap) static PromiseWrap* New(Environment* env, Local promise, - PromiseWrap* parent_wrap, bool silent); - static void getIsChainedPromise(Local property, - const PropertyCallbackInfo& info); + static void GetAsyncId(Local property, + const PropertyCallbackInfo& args); + static void GetTriggerAsyncId(Local property, + const PropertyCallbackInfo& args); + + static void Initialize(Environment* env); }; PromiseWrap* PromiseWrap::New(Environment* env, Local promise, - PromiseWrap* parent_wrap, bool silent) { + Local context = env->context(); + Local obj; - if (!env->promise_wrap_template()->NewInstance(env->context()).ToLocal(&obj)) + if (!env->promise_wrap_template()->NewInstance(context).ToLocal(&obj)) return nullptr; - obj->SetInternalField(PromiseWrap::kIsChainedPromiseField, - parent_wrap != nullptr ? v8::True(env->isolate()) - : v8::False(env->isolate())); + CHECK_NULL(promise->GetAlignedPointerFromInternalField(0)); promise->SetInternalField(0, obj); + + // Skip for init events + if (silent) { + Local maybeAsyncId = promise + ->Get(context, env->async_id_symbol()) + .ToLocalChecked(); + + Local maybeTriggerAsyncId = promise + ->Get(context, env->trigger_async_id_symbol()) + .ToLocalChecked(); + + if (maybeAsyncId->IsNumber() && maybeTriggerAsyncId->IsNumber()) { + double asyncId = maybeAsyncId->NumberValue(context).ToChecked(); + double triggerAsyncId = maybeTriggerAsyncId->NumberValue(context) + .ToChecked(); + return new PromiseWrap(env, obj, asyncId, triggerAsyncId); + } + } + return new PromiseWrap(env, obj, silent); } -void PromiseWrap::getIsChainedPromise(Local property, - const PropertyCallbackInfo& info) { - info.GetReturnValue().Set( - info.Holder()->GetInternalField(PromiseWrap::kIsChainedPromiseField)); +void PromiseWrap::GetAsyncId(Local property, + const PropertyCallbackInfo& info) { + Isolate* isolate = info.GetIsolate(); + HandleScope scope(isolate); + + PromiseWrap* wrap = Unwrap(info.Holder()); + double value = wrap->get_async_id(); + + info.GetReturnValue().Set(Number::New(isolate, value)); +} + +void PromiseWrap::GetTriggerAsyncId(Local property, + const PropertyCallbackInfo& info) { + Isolate* isolate = info.GetIsolate(); + HandleScope scope(isolate); + + PromiseWrap* wrap = Unwrap(info.Holder()); + double value = wrap->get_trigger_async_id(); + + info.GetReturnValue().Set(Number::New(isolate, value)); +} + +void PromiseWrap::Initialize(Environment* env) { + Isolate* isolate = env->isolate(); + HandleScope scope(isolate); + + Local ctor = FunctionTemplate::New(isolate); + ctor->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "PromiseWrap")); + + Local promise_wrap_template = ctor->InstanceTemplate(); + env->set_promise_wrap_template(promise_wrap_template); + + promise_wrap_template->SetInternalFieldCount( + PromiseWrap::kInternalFieldCount); + + promise_wrap_template->SetAccessor( + env->async_id_symbol(), + PromiseWrap::GetAsyncId); + + promise_wrap_template->SetAccessor( + env->trigger_async_id_symbol(), + PromiseWrap::GetTriggerAsyncId); } static PromiseWrap* extractPromiseWrap(Local promise) { @@ -240,8 +303,36 @@ static PromiseWrap* extractPromiseWrap(Local promise) { return obj->IsObject() ? Unwrap(obj.As()) : nullptr; } -static void PromiseHook(PromiseHookType type, Local promise, - Local parent) { +static uint16_t ToAsyncHooksType(PromiseHookType type) { + switch (type) { + case PromiseHookType::kInit: return AsyncHooks::kInit; + case PromiseHookType::kBefore: return AsyncHooks::kBefore; + case PromiseHookType::kAfter: return AsyncHooks::kAfter; + case PromiseHookType::kResolve: return AsyncHooks::kPromiseResolve; + } + UNREACHABLE(); +} + +// Simplified JavaScript hook fast-path for when there is no destroy hook +static void FastPromiseHook(PromiseHookType type, Local promise, + Local parent) { + Local context = promise->CreationContext(); + Environment* env = Environment::GetCurrent(context); + if (env == nullptr) return; + + Local argv[] = { + Integer::New(env->isolate(), ToAsyncHooksType(type)), + promise, + parent + }; + + TryCatchScope try_catch(env, TryCatchScope::CatchMode::kFatal); + Local promise_hook = env->promise_hook_handler(); + USE(promise_hook->Call(context, Undefined(env->isolate()), 3, argv)); +} + +static void FullPromiseHook(PromiseHookType type, Local promise, + Local parent) { Local context = promise->CreationContext(); Environment* env = Environment::GetCurrent(context); @@ -261,14 +352,14 @@ static void PromiseHook(PromiseHookType type, Local promise, Local parent_promise = parent.As(); PromiseWrap* parent_wrap = extractPromiseWrap(parent_promise); if (parent_wrap == nullptr) { - parent_wrap = PromiseWrap::New(env, parent_promise, nullptr, true); + parent_wrap = PromiseWrap::New(env, parent_promise, true); if (parent_wrap == nullptr) return; } AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(parent_wrap); - wrap = PromiseWrap::New(env, promise, parent_wrap, silent); + wrap = PromiseWrap::New(env, promise, silent); } else { - wrap = PromiseWrap::New(env, promise, nullptr, silent); + wrap = PromiseWrap::New(env, promise, silent); } } @@ -295,7 +386,6 @@ static void PromiseHook(PromiseHookType type, Local promise, } } - static void SetupHooks(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); @@ -324,34 +414,28 @@ static void SetupHooks(const FunctionCallbackInfo& args) { SET_HOOK_FN(destroy); SET_HOOK_FN(promise_resolve); #undef SET_HOOK_FN - - { - Local ctor = - FunctionTemplate::New(env->isolate()); - ctor->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "PromiseWrap")); - Local promise_wrap_template = ctor->InstanceTemplate(); - promise_wrap_template->SetInternalFieldCount( - PromiseWrap::kInternalFieldCount); - promise_wrap_template->SetAccessor( - FIXED_ONE_BYTE_STRING(env->isolate(), "isChainedPromise"), - PromiseWrap::getIsChainedPromise); - env->set_promise_wrap_template(promise_wrap_template); - } } - static void EnablePromiseHook(const FunctionCallbackInfo& args) { - args.GetIsolate()->SetPromiseHook(PromiseHook); + Environment* env = Environment::GetCurrent(args); + + if (args[0]->IsFunction()) { + env->set_promise_hook_handler(args[0].As()); + args.GetIsolate()->SetPromiseHook(FastPromiseHook); + } else { + args.GetIsolate()->SetPromiseHook(FullPromiseHook); + } } static void DisablePromiseHook(const FunctionCallbackInfo& args) { - Isolate* isolate = args.GetIsolate(); + Environment* env = Environment::GetCurrent(args); + env->set_promise_hook_handler(Local()); // The per-Isolate API provides no way of knowing whether there are multiple // users of the PromiseHook. That hopefully goes away when V8 introduces // a per-context API. - isolate->SetPromiseHook(nullptr); + args.GetIsolate()->SetPromiseHook(nullptr); } @@ -577,6 +661,9 @@ void AsyncWrap::Initialize(Local target, FIXED_ONE_BYTE_STRING(env->isolate(), "AsyncWrap"), AsyncWrapObject::GetConstructorTemplate(env) ->GetFunction(env->context()).ToLocalChecked()).Check(); + + // TODO(qard): maybe this should be GetConstructorTemplate instead? + PromiseWrap::Initialize(env); } @@ -600,13 +687,22 @@ AsyncWrap::AsyncWrap(Environment* env, init_hook_ran_ = true; } +AsyncWrap::AsyncWrap(Environment* env, + Local object, + ProviderType provider, + double execution_async_id, + double trigger_async_id) + : AsyncWrap(env, object, provider, execution_async_id, true) { + trigger_async_id_ = trigger_async_id; +} + AsyncWrap::AsyncWrap(Environment* env, Local object) : BaseObject(env, object) { } // This method is necessary to work around one specific problem: // Before the init() hook runs, if there is one, the BaseObject() constructor -// registers this object with the Environment for finilization and debugging +// registers this object with the Environment for finalization and debugging // purposes. // If the Environment decides to inspect this object for debugging, it tries to // call virtual methods on this object that are only (meaningfully) implemented diff --git a/src/async_wrap.h b/src/async_wrap.h index 34e84fde6d4823..dac86d694ac28e 100644 --- a/src/async_wrap.h +++ b/src/async_wrap.h @@ -209,6 +209,11 @@ class AsyncWrap : public BaseObject { ProviderType provider, double execution_async_id, bool silent); + AsyncWrap(Environment* env, + v8::Local promise, + ProviderType provider, + double execution_async_id, + double trigger_async_id); ProviderType provider_type_ = PROVIDER_NONE; bool init_hook_ran_ = false; // Because the values may be Reset(), cannot be made const. diff --git a/src/callback_queue-inl.h b/src/callback_queue-inl.h new file mode 100644 index 00000000000000..e83c81cd0dd802 --- /dev/null +++ b/src/callback_queue-inl.h @@ -0,0 +1,97 @@ +#ifndef SRC_CALLBACK_QUEUE_INL_H_ +#define SRC_CALLBACK_QUEUE_INL_H_ + +#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#include "callback_queue.h" + +namespace node { + +template +template +std::unique_ptr::Callback> +CallbackQueue::CreateCallback(Fn&& fn, bool refed) { + return std::make_unique>(std::move(fn), refed); +} + +template +std::unique_ptr::Callback> +CallbackQueue::Shift() { + std::unique_ptr ret = std::move(head_); + if (ret) { + head_ = ret->get_next(); + if (!head_) + tail_ = nullptr; // The queue is now empty. + } + size_--; + return ret; +} + +template +void CallbackQueue::Push(std::unique_ptr cb) { + Callback* prev_tail = tail_; + + size_++; + tail_ = cb.get(); + if (prev_tail != nullptr) + prev_tail->set_next(std::move(cb)); + else + head_ = std::move(cb); +} + +template +void CallbackQueue::ConcatMove(CallbackQueue&& other) { + size_ += other.size_; + if (tail_ != nullptr) + tail_->set_next(std::move(other.head_)); + else + head_ = std::move(other.head_); + tail_ = other.tail_; + other.tail_ = nullptr; + other.size_ = 0; +} + +template +size_t CallbackQueue::size() const { + return size_.load(); +} + +template +CallbackQueue::Callback::Callback(bool refed) + : refed_(refed) {} + +template +bool CallbackQueue::Callback::is_refed() const { + return refed_; +} + +template +std::unique_ptr::Callback> +CallbackQueue::Callback::get_next() { + return std::move(next_); +} + +template +void CallbackQueue::Callback::set_next( + std::unique_ptr next) { + next_ = std::move(next); +} + +template +template +CallbackQueue::CallbackImpl::CallbackImpl( + Fn&& callback, bool refed) + : Callback(refed), + callback_(std::move(callback)) {} + +template +template +R CallbackQueue::CallbackImpl::Call(Args... args) { + return callback_(std::forward(args)...); +} + +} // namespace node + +#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#endif // SRC_CALLBACK_QUEUE_INL_H_ diff --git a/src/callback_queue.h b/src/callback_queue.h new file mode 100644 index 00000000000000..ebf975e6391d13 --- /dev/null +++ b/src/callback_queue.h @@ -0,0 +1,70 @@ +#ifndef SRC_CALLBACK_QUEUE_H_ +#define SRC_CALLBACK_QUEUE_H_ + +#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#include + +namespace node { + +// A queue of C++ functions that take Args... as arguments and return R +// (this is similar to the signature of std::function). +// New entries are added using `CreateCallback()`/`Push()`, and removed using +// `Shift()`. +// The `refed` flag is left for easier use in situations in which some of these +// should be run even if nothing else is keeping the event loop alive. +template +class CallbackQueue { + public: + class Callback { + public: + explicit inline Callback(bool refed); + + virtual ~Callback() = default; + virtual R Call(Args... args) = 0; + + inline bool is_refed() const; + + private: + inline std::unique_ptr get_next(); + inline void set_next(std::unique_ptr next); + + bool refed_; + std::unique_ptr next_; + + friend class CallbackQueue; + }; + + template + inline std::unique_ptr CreateCallback(Fn&& fn, bool refed); + + inline std::unique_ptr Shift(); + inline void Push(std::unique_ptr cb); + // ConcatMove adds elements from 'other' to the end of this list, and clears + // 'other' afterwards. + inline void ConcatMove(CallbackQueue&& other); + + // size() is atomic and may be called from any thread. + inline size_t size() const; + + private: + template + class CallbackImpl final : public Callback { + public: + CallbackImpl(Fn&& callback, bool refed); + R Call(Args... args) override; + + private: + Fn callback_; + }; + + std::atomic size_ {0}; + std::unique_ptr head_; + Callback* tail_ = nullptr; +}; + +} // namespace node + +#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#endif // SRC_CALLBACK_QUEUE_H_ diff --git a/src/env-inl.h b/src/env-inl.h index 9ba5bebe00cb27..3971f479aa1e23 100644 --- a/src/env-inl.h +++ b/src/env-inl.h @@ -25,6 +25,7 @@ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #include "aliased_buffer.h" +#include "callback_queue-inl.h" #include "env.h" #include "node.h" #include "util-inl.h" @@ -287,6 +288,10 @@ inline void Environment::AssignToContext(v8::Local context, // Used by Environment::GetCurrent to know that we are on a node context. context->SetAlignedPointerInEmbedderData( ContextEmbedderIndex::kContextTag, Environment::kNodeContextTagPtr); + // Used to retrieve bindings + context->SetAlignedPointerInEmbedderData( + ContextEmbedderIndex::kBindingListIndex, &(this->bindings_)); + #if HAVE_INSPECTOR inspector_agent()->ContextCreated(context, info); #endif // HAVE_INSPECTOR @@ -318,55 +323,55 @@ inline Environment* Environment::GetCurrent(v8::Local context) { inline Environment* Environment::GetCurrent( const v8::FunctionCallbackInfo& info) { - return GetFromCallbackData(info.Data()); + return GetCurrent(info.GetIsolate()->GetCurrentContext()); } template inline Environment* Environment::GetCurrent( const v8::PropertyCallbackInfo& info) { - return GetFromCallbackData(info.Data()); + return GetCurrent(info.GetIsolate()->GetCurrentContext()); } -Environment* Environment::GetFromCallbackData(v8::Local val) { - DCHECK(val->IsObject()); - v8::Local obj = val.As(); - DCHECK_GE(obj->InternalFieldCount(), - BaseObject::kInternalFieldCount); - Environment* env = Unwrap(obj)->env(); - DCHECK(env->as_callback_data_template()->HasInstance(obj)); - return env; +template +inline T* Environment::GetBindingData(const v8::PropertyCallbackInfo& info) { + return GetBindingData(info.GetIsolate()->GetCurrentContext()); } template -Environment::BindingScope::BindingScope(Environment* env) : env(env) { - v8::Local callback_data; - if (!env->MakeBindingCallbackData().ToLocal(&callback_data)) - return; - data = Unwrap(callback_data); - - // No nesting allowed currently. - CHECK_EQ(env->current_callback_data(), env->as_callback_data()); - env->set_current_callback_data(callback_data); +inline T* Environment::GetBindingData( + const v8::FunctionCallbackInfo& info) { + return GetBindingData(info.GetIsolate()->GetCurrentContext()); } template -Environment::BindingScope::~BindingScope() { - env->set_current_callback_data(env->as_callback_data()); +inline T* Environment::GetBindingData(v8::Local context) { + BindingDataStore* map = static_cast( + context->GetAlignedPointerFromEmbedderData( + ContextEmbedderIndex::kBindingListIndex)); + DCHECK_NOT_NULL(map); + auto it = map->find(T::binding_data_name); + if (UNLIKELY(it == map->end())) return nullptr; + T* result = static_cast(it->second.get()); + DCHECK_NOT_NULL(result); + DCHECK_EQ(result->env(), GetCurrent(context)); + return result; } template -v8::MaybeLocal Environment::MakeBindingCallbackData() { - v8::Local ctor; - v8::Local obj; - if (!as_callback_data_template()->GetFunction(context()).ToLocal(&ctor) || - !ctor->NewInstance(context()).ToLocal(&obj)) { - return v8::MaybeLocal(); - } - T* data = new T(this, obj); +inline T* Environment::AddBindingData( + v8::Local context, + v8::Local target) { + DCHECK_EQ(GetCurrent(context), this); // This won't compile if T is not a BaseObject subclass. - CHECK_EQ(data, static_cast(data)); - data->MakeWeak(); - return obj; + BaseObjectPtr item = MakeDetachedBaseObject(this, target); + BindingDataStore* map = static_cast( + context->GetAlignedPointerFromEmbedderData( + ContextEmbedderIndex::kBindingListIndex)); + DCHECK_NOT_NULL(map); + auto result = map->emplace(T::binding_data_name, item); + CHECK(result.second); + DCHECK_EQ(GetBindingData(context), item.get()); + return item.get(); } inline Environment* Environment::GetThreadLocalEnv() { @@ -701,50 +706,9 @@ inline void IsolateData::set_options( options_ = std::move(options); } -std::unique_ptr -Environment::NativeImmediateQueue::Shift() { - std::unique_ptr ret = std::move(head_); - if (ret) { - head_ = ret->get_next(); - if (!head_) - tail_ = nullptr; // The queue is now empty. - } - size_--; - return ret; -} - -void Environment::NativeImmediateQueue::Push( - std::unique_ptr cb) { - NativeImmediateCallback* prev_tail = tail_; - - size_++; - tail_ = cb.get(); - if (prev_tail != nullptr) - prev_tail->set_next(std::move(cb)); - else - head_ = std::move(cb); -} - -void Environment::NativeImmediateQueue::ConcatMove( - NativeImmediateQueue&& other) { - size_ += other.size_; - if (tail_ != nullptr) - tail_->set_next(std::move(other.head_)); - else - head_ = std::move(other.head_); - tail_ = other.tail_; - other.tail_ = nullptr; - other.size_ = 0; -} - -size_t Environment::NativeImmediateQueue::size() const { - return size_.load(); -} - template void Environment::CreateImmediate(Fn&& cb, bool ref) { - auto callback = std::make_unique>( - std::move(cb), ref); + auto callback = native_immediates_.CreateCallback(std::move(cb), ref); native_immediates_.Push(std::move(callback)); } @@ -763,9 +727,9 @@ void Environment::SetUnrefImmediate(Fn&& cb) { } template -void Environment::SetImmediateThreadsafe(Fn&& cb) { - auto callback = std::make_unique>( - std::move(cb), false); +void Environment::SetImmediateThreadsafe(Fn&& cb, bool refed) { + auto callback = + native_immediates_threadsafe_.CreateCallback(std::move(cb), refed); { Mutex::ScopedLock lock(native_immediates_threadsafe_mutex_); native_immediates_threadsafe_.Push(std::move(callback)); @@ -776,8 +740,8 @@ void Environment::SetImmediateThreadsafe(Fn&& cb) { template void Environment::RequestInterrupt(Fn&& cb) { - auto callback = std::make_unique>( - std::move(cb), false); + auto callback = + native_immediates_interrupts_.CreateCallback(std::move(cb), false); { Mutex::ScopedLock lock(native_immediates_threadsafe_mutex_); native_immediates_interrupts_.Push(std::move(callback)); @@ -787,34 +751,6 @@ void Environment::RequestInterrupt(Fn&& cb) { RequestInterruptFromV8(); } -Environment::NativeImmediateCallback::NativeImmediateCallback(bool refed) - : refed_(refed) {} - -bool Environment::NativeImmediateCallback::is_refed() const { - return refed_; -} - -std::unique_ptr -Environment::NativeImmediateCallback::get_next() { - return std::move(next_); -} - -void Environment::NativeImmediateCallback::set_next( - std::unique_ptr next) { - next_ = std::move(next); -} - -template -Environment::NativeImmediateCallbackImpl::NativeImmediateCallbackImpl( - Fn&& callback, bool refed) - : NativeImmediateCallback(refed), - callback_(std::move(callback)) {} - -template -void Environment::NativeImmediateCallbackImpl::Call(Environment* env) { - callback_(env); -} - inline bool Environment::can_call_into_js() const { return can_call_into_js_ && !is_stopping(); } @@ -1077,8 +1013,7 @@ inline v8::Local v8::Local signature, v8::ConstructorBehavior behavior, v8::SideEffectType side_effect_type) { - v8::Local external = current_callback_data(); - return v8::FunctionTemplate::New(isolate(), callback, external, + return v8::FunctionTemplate::New(isolate(), callback, v8::Local(), signature, 0, behavior, side_effect_type); } @@ -1177,13 +1112,6 @@ void Environment::RemoveCleanupHook(void (*fn)(void*), void* arg) { cleanup_hooks_.erase(search); } -inline void Environment::RegisterFinalizationGroupForCleanup( - v8::Local group) { - cleanup_finalization_groups_.emplace_back(isolate(), group); - DCHECK(task_queues_async_initialized_); - uv_async_send(&task_queues_async_); -} - size_t CleanupHookCallback::Hash::operator()( const CleanupHookCallback& cb) const { return std::hash()(cb.arg_); @@ -1270,9 +1198,10 @@ void Environment::set_process_exit_handler( ENVIRONMENT_STRONG_PERSISTENT_VALUES(V) #undef V - inline v8::Local Environment::context() const { - return PersistentToLocal::Strong(context_); - } +v8::Local Environment::context() const { + return PersistentToLocal::Strong(context_); +} + } // namespace node // These two files depend on each other. Including base_object-inl.h after this diff --git a/src/env.cc b/src/env.cc index f966bfba1ee7e6..feb648a2b66aaf 100644 --- a/src/env.cc +++ b/src/env.cc @@ -31,7 +31,6 @@ using v8::ArrayBuffer; using v8::Boolean; using v8::Context; using v8::EmbedderGraph; -using v8::FinalizationGroup; using v8::Function; using v8::FunctionTemplate; using v8::HandleScope; @@ -261,29 +260,17 @@ void TrackingTraceStateObserver::UpdateTraceCategoryState() { USE(cb->Call(env_->context(), Undefined(isolate), arraysize(args), args)); } -class NoBindingData : public BaseObject { - public: - NoBindingData(Environment* env, Local obj) : BaseObject(env, obj) {} - - SET_NO_MEMORY_INFO() - SET_MEMORY_INFO_NAME(NoBindingData) - SET_SELF_SIZE(NoBindingData) -}; - void Environment::CreateProperties() { HandleScope handle_scope(isolate_); Local ctx = context(); + { Context::Scope context_scope(ctx); Local templ = FunctionTemplate::New(isolate()); templ->InstanceTemplate()->SetInternalFieldCount( BaseObject::kInternalFieldCount); - set_as_callback_data_template(templ); - Local obj = MakeBindingCallbackData() - .ToLocalChecked(); - set_as_callback_data(obj); - set_current_callback_data(obj); + set_binding_data_ctor_template(templ); } // Store primordials setup by the per-context script in the environment. @@ -535,7 +522,6 @@ void Environment::InitializeLibuv(bool start_profiler_idle_notifier) { [](uv_async_t* async) { Environment* env = ContainerOf( &Environment::task_queues_async_, async); - env->CleanupFinalizationGroups(); env->RunAndClearNativeImmediates(); }); uv_unref(reinterpret_cast(&idle_prepare_handle_)); @@ -674,6 +660,8 @@ void Environment::RunCleanup() { started_cleanup_ = true; TraceEventScope trace_scope(TRACING_CATEGORY_NODE1(environment), "RunCleanup", this); + bindings_.clear(); + initial_base_object_count_ = 0; CleanupHandles(); while (!cleanup_hooks_.empty()) { @@ -739,7 +727,7 @@ void Environment::RunAndClearInterrupts() { } DebugSealHandleScope seal_handle_scope(isolate()); - while (std::unique_ptr head = queue.Shift()) + while (auto head = queue.Shift()) head->Call(this); } } @@ -753,20 +741,10 @@ void Environment::RunAndClearNativeImmediates(bool only_refed) { // exceptions, so we do not need to handle that. RunAndClearInterrupts(); - // It is safe to check .size() first, because there is a causal relationship - // between pushes to the threadsafe and this function being called. - // For the common case, it's worth checking the size first before establishing - // a mutex lock. - if (native_immediates_threadsafe_.size() > 0) { - Mutex::ScopedLock lock(native_immediates_threadsafe_mutex_); - native_immediates_.ConcatMove(std::move(native_immediates_threadsafe_)); - } - - auto drain_list = [&]() { + auto drain_list = [&](NativeImmediateQueue* queue) { TryCatchScope try_catch(this); DebugSealHandleScope seal_handle_scope(isolate()); - while (std::unique_ptr head = - native_immediates_.Shift()) { + while (auto head = queue->Shift()) { if (head->is_refed()) ref_count++; @@ -784,12 +762,26 @@ void Environment::RunAndClearNativeImmediates(bool only_refed) { } return false; }; - while (drain_list()) {} + while (drain_list(&native_immediates_)) {} immediate_info()->ref_count_dec(ref_count); if (immediate_info()->ref_count() == 0) ToggleImmediateRef(false); + + // It is safe to check .size() first, because there is a causal relationship + // between pushes to the threadsafe immediate list and this function being + // called. For the common case, it's worth checking the size first before + // establishing a mutex lock. + // This is intentionally placed after the `ref_count` handling, because when + // refed threadsafe immediates are created, they are not counted towards the + // count in immediate_info() either. + NativeImmediateQueue threadsafe_immediates; + if (native_immediates_threadsafe_.size() > 0) { + Mutex::ScopedLock lock(native_immediates_threadsafe_mutex_); + threadsafe_immediates.ConcatMove(std::move(native_immediates_threadsafe_)); + } + while (drain_list(&threadsafe_immediates)) {} } void Environment::RequestInterruptFromV8() { @@ -1169,26 +1161,6 @@ void Environment::RunWeakRefCleanup() { isolate()->ClearKeptObjects(); } -void Environment::CleanupFinalizationGroups() { - HandleScope handle_scope(isolate()); - Context::Scope context_scope(context()); - TryCatchScope try_catch(this); - - while (!cleanup_finalization_groups_.empty() && can_call_into_js()) { - Local fg = - cleanup_finalization_groups_.front().Get(isolate()); - cleanup_finalization_groups_.pop_front(); - if (!FinalizationGroup::Cleanup(fg).FromMaybe(false)) { - if (try_catch.HasCaught() && !try_catch.HasTerminated()) - errors::TriggerUncaughtException(isolate(), try_catch); - // Re-schedule the execution of the remainder of the queue. - CHECK(task_queues_async_initialized_); - uv_async_send(&task_queues_async_); - return; - } - } -} - // Not really any better place than env.cc at this moment. void BaseObject::DeleteMe(void* data) { BaseObject* self = static_cast(data); diff --git a/src/env.h b/src/env.h index 48f8a83aadae22..72ca9449236ae3 100644 --- a/src/env.h +++ b/src/env.h @@ -29,6 +29,7 @@ #include "inspector_agent.h" #include "inspector_profiler.h" #endif +#include "callback_queue.h" #include "debug_utils.h" #include "handle_wrap.h" #include "node.h" @@ -155,11 +156,13 @@ constexpr size_t kFsStatsBufferLength = // Symbols are per-isolate primitives but Environment proxies them // for the sake of convenience. #define PER_ISOLATE_SYMBOL_PROPERTIES(V) \ + V(async_id_symbol, "async_id_symbol") \ V(handle_onclose_symbol, "handle_onclose") \ V(no_message_symbol, "no_message_symbol") \ V(oninit_symbol, "oninit") \ V(owner_symbol, "owner") \ V(onpskexchange_symbol, "onpskexchange") \ + V(trigger_async_id_symbol, "trigger_async_id_symbol") \ // Strings are per-isolate primitives but Environment proxies them // for the sake of convenience. Strings should be ASCII-only. @@ -390,9 +393,9 @@ constexpr size_t kFsStatsBufferLength = V(zero_return_string, "ZERO_RETURN") #define ENVIRONMENT_STRONG_PERSISTENT_TEMPLATES(V) \ - V(as_callback_data_template, v8::FunctionTemplate) \ V(async_wrap_ctor_template, v8::FunctionTemplate) \ V(async_wrap_object_ctor_template, v8::FunctionTemplate) \ + V(binding_data_ctor_template, v8::FunctionTemplate) \ V(compiled_fn_entry_template, v8::ObjectTemplate) \ V(dir_instance_template, v8::ObjectTemplate) \ V(fd_constructor_template, v8::ObjectTemplate) \ @@ -420,7 +423,6 @@ constexpr size_t kFsStatsBufferLength = V(worker_heap_snapshot_taker_template, v8::ObjectTemplate) #define ENVIRONMENT_STRONG_PERSISTENT_VALUES(V) \ - V(as_callback_data, v8::Object) \ V(async_hooks_after_function, v8::Function) \ V(async_hooks_before_function, v8::Function) \ V(async_hooks_binding, v8::Object) \ @@ -429,7 +431,6 @@ constexpr size_t kFsStatsBufferLength = V(async_hooks_promise_resolve_function, v8::Function) \ V(buffer_prototype_object, v8::Object) \ V(crypto_key_object_constructor, v8::Function) \ - V(current_callback_data, v8::Object) \ V(domain_callback, v8::Function) \ V(domexception_function, v8::Function) \ V(enhance_fatal_stack_after_inspector, v8::Function) \ @@ -458,6 +459,7 @@ constexpr size_t kFsStatsBufferLength = V(prepare_stack_trace_callback, v8::Function) \ V(process_object, v8::Object) \ V(primordials, v8::Object) \ + V(promise_hook_handler, v8::Function) \ V(promise_reject_callback, v8::Function) \ V(script_data_constructor_function, v8::Function) \ V(source_map_cache_getter, v8::Function) \ @@ -864,25 +866,24 @@ class Environment : public MemoryRetainer { static inline Environment* GetCurrent( const v8::PropertyCallbackInfo& info); - static inline Environment* GetFromCallbackData(v8::Local val); - // Methods created using SetMethod(), SetPrototypeMethod(), etc. inside // this scope can access the created T* object using - // Unwrap(args.Data()) later. + // GetBindingData(args) later. template - struct BindingScope { - explicit inline BindingScope(Environment* env); - inline ~BindingScope(); - - T* data = nullptr; - Environment* env; - - inline operator bool() const { return data != nullptr; } - inline bool operator !() const { return data == nullptr; } - }; - + T* AddBindingData(v8::Local context, + v8::Local target); + template + static inline T* GetBindingData(const v8::PropertyCallbackInfo& info); + template + static inline T* GetBindingData( + const v8::FunctionCallbackInfo& info); template - inline v8::MaybeLocal MakeBindingCallbackData(); + static inline T* GetBindingData(v8::Local context); + + typedef std::unordered_map< + FastStringKey, + BaseObjectPtr, + FastStringKey::Hash> BindingDataStore; static uv_key_t thread_local_env; static inline Environment* GetThreadLocalEnv(); @@ -1104,9 +1105,7 @@ class Environment : public MemoryRetainer { void AtExit(void (*cb)(void* arg), void* arg); void RunAtExitCallbacks(); - void RegisterFinalizationGroupForCleanup(v8::Local fg); void RunWeakRefCleanup(); - void CleanupFinalizationGroups(); // Strings and private symbols are shared across shared contexts // The getters simply proxy to the per-isolate primitive. @@ -1168,7 +1167,7 @@ class Environment : public MemoryRetainer { inline void SetUnrefImmediate(Fn&& cb); template // This behaves like SetImmediate() but can be called from any thread. - inline void SetImmediateThreadsafe(Fn&& cb); + inline void SetImmediateThreadsafe(Fn&& cb, bool refed = true); // This behaves like V8's Isolate::RequestInterrupt(), but also accounts for // the event loop (i.e. combines the V8 function with SetImmediate()). // The passed callback may not throw exceptions. @@ -1330,8 +1329,6 @@ class Environment : public MemoryRetainer { uint64_t thread_id_; std::unordered_set sub_worker_contexts_; - std::deque> cleanup_finalization_groups_; - static void* const kNodeContextTagPtr; static int const kNodeContextTag; @@ -1368,49 +1365,7 @@ class Environment : public MemoryRetainer { std::list at_exit_functions_; - class NativeImmediateCallback { - public: - explicit inline NativeImmediateCallback(bool refed); - - virtual ~NativeImmediateCallback() = default; - virtual void Call(Environment* env) = 0; - - inline bool is_refed() const; - inline std::unique_ptr get_next(); - inline void set_next(std::unique_ptr next); - - private: - bool refed_; - std::unique_ptr next_; - }; - - template - class NativeImmediateCallbackImpl final : public NativeImmediateCallback { - public: - NativeImmediateCallbackImpl(Fn&& callback, bool refed); - void Call(Environment* env) override; - - private: - Fn callback_; - }; - - class NativeImmediateQueue { - public: - inline std::unique_ptr Shift(); - inline void Push(std::unique_ptr cb); - // ConcatMove adds elements from 'other' to the end of this list, and clears - // 'other' afterwards. - inline void ConcatMove(NativeImmediateQueue&& other); - - // size() is atomic and may be called from any thread. - inline size_t size() const; - - private: - std::atomic size_ {0}; - std::unique_ptr head_; - NativeImmediateCallback* tail_ = nullptr; - }; - + typedef CallbackQueue NativeImmediateQueue; NativeImmediateQueue native_immediates_; Mutex native_immediates_threadsafe_mutex_; NativeImmediateQueue native_immediates_threadsafe_; @@ -1425,6 +1380,8 @@ class Environment : public MemoryRetainer { void RequestInterruptFromV8(); static void CheckImmediate(uv_check_t* handle); + BindingDataStore bindings_; + // Use an unordered_set, so that we have efficient insertion and removal. std::unordered_set target, FSEventWrap::kInternalFieldCount); t->SetClassName(fsevent_string); - t->Inherit(AsyncWrap::GetConstructorTemplate(env)); + t->Inherit(HandleWrap::GetConstructorTemplate(env)); env->SetProtoMethod(t, "start", Start); - env->SetProtoMethod(t, "close", Close); Local get_initialized_templ = FunctionTemplate::New(env->isolate(), GetInitialized, - env->current_callback_data(), + Local(), Signature::New(env->isolate(), t)); t->PrototypeTemplate()->SetAccessorProperty( diff --git a/src/js_native_api_v8.cc b/src/js_native_api_v8.cc index 4255c3e7ec3fff..a09969b9adf28f 100644 --- a/src/js_native_api_v8.cc +++ b/src/js_native_api_v8.cc @@ -371,39 +371,6 @@ class Reference : public RefBase { v8impl::Persistent _persistent; }; -class ArrayBufferReference final : public Reference { - public: - // Same signatures for ctor and New() as Reference, except this only works - // with ArrayBuffers: - template - explicit ArrayBufferReference(napi_env env, - v8::Local value, - Args&&... args) - : Reference(env, value, std::forward(args)...) {} - - template - static ArrayBufferReference* New(napi_env env, - v8::Local value, - Args&&... args) { - return new ArrayBufferReference(env, value, std::forward(args)...); - } - - private: - inline void Finalize(bool is_env_teardown) override { - if (is_env_teardown) { - v8::HandleScope handle_scope(_env->isolate); - v8::Local obj = Get(); - CHECK(!obj.IsEmpty()); - CHECK(obj->IsArrayBuffer()); - v8::Local ab = obj.As(); - if (ab->IsDetachable()) - ab->Detach(); - } - - Reference::Finalize(is_env_teardown); - } -}; - enum UnwrapAction { KeepWrap, RemoveWrap @@ -2710,37 +2677,27 @@ napi_status napi_create_external_arraybuffer(napi_env env, napi_finalize finalize_cb, void* finalize_hint, napi_value* result) { - NAPI_PREAMBLE(env); - CHECK_ARG(env, result); - - v8::Isolate* isolate = env->isolate; - // The buffer will be freed with v8impl::ArrayBufferReference::New() - // below, hence this BackingStore does not need to free the buffer. - std::unique_ptr backing = - v8::ArrayBuffer::NewBackingStore(external_data, - byte_length, - [](void*, size_t, void*){}, - nullptr); - v8::Local buffer = - v8::ArrayBuffer::New(isolate, std::move(backing)); - v8::Maybe marked = env->mark_arraybuffer_as_untransferable(buffer); - CHECK_MAYBE_NOTHING(env, marked, napi_generic_failure); - - if (finalize_cb != nullptr) { - // Create a self-deleting weak reference that invokes the finalizer - // callback and detaches the ArrayBuffer if it still exists on Environment - // teardown. - v8impl::ArrayBufferReference::New(env, - buffer, - 0, - true, - finalize_cb, - external_data, - finalize_hint); - } - - *result = v8impl::JsValueFromV8LocalValue(buffer); - return GET_RETURN_STATUS(env); + // The API contract here is that the cleanup function runs on the JS thread, + // and is able to use napi_env. Implementing that properly is hard, so use the + // `Buffer` variant for easier implementation. + napi_value buffer; + napi_status status; + status = napi_create_external_buffer( + env, + byte_length, + external_data, + finalize_cb, + finalize_hint, + &buffer); + if (status != napi_ok) return status; + return napi_get_typedarray_info( + env, + buffer, + nullptr, + nullptr, + nullptr, + result, + nullptr); } napi_status napi_get_arraybuffer_info(napi_env env, diff --git a/src/json_utils.h b/src/json_utils.h index 21e204328058ee..3ece077a91705d 100644 --- a/src/json_utils.h +++ b/src/json_utils.h @@ -6,6 +6,7 @@ #include #include #include +#include namespace node { diff --git a/src/large_pages/node_large_page.cc b/src/large_pages/node_large_page.cc index 853a56f5bd5e4c..a4b109d1b0ef69 100644 --- a/src/large_pages/node_large_page.cc +++ b/src/large_pages/node_large_page.cc @@ -106,18 +106,18 @@ namespace node { namespace { struct text_region { - char* from; - char* to; - int total_hugepages; - bool found_text_region; + char* from = nullptr; + char* to = nullptr; + bool found_text_region = false; }; static const size_t hps = 2L * 1024 * 1024; template -inline void Debug(Args&&... args) { +inline void Debug(std::string fmt, Args&&... args) { node::Debug(&per_process::enabled_debug_list, DebugCategory::HUGEPAGES, + (std::string("Hugepages info: ") + fmt).c_str(), std::forward(args)...); } @@ -145,9 +145,9 @@ inline uintptr_t hugepage_align_down(uintptr_t addr) { #endif // defined(__FreeBSD__) struct dl_iterate_params { - uintptr_t start; - uintptr_t end; - uintptr_t reference_sym; + uintptr_t start = 0; + uintptr_t end = 0; + uintptr_t reference_sym = reinterpret_cast(&__node_text_start); std::string exename; }; @@ -175,11 +175,8 @@ int FindMapping(struct dl_phdr_info* info, size_t, void* data) { struct text_region FindNodeTextRegion() { struct text_region nregion; - nregion.found_text_region = false; #if defined(__linux__) || defined(__FreeBSD__) - dl_iterate_params dl_params = { - 0, 0, reinterpret_cast(&__node_text_start), "" - }; + dl_iterate_params dl_params; uintptr_t lpstub_start = reinterpret_cast(&__start_lpstub); #if defined(__FreeBSD__) @@ -196,14 +193,14 @@ struct text_region FindNodeTextRegion() { #endif // defined(__FreeBSD__) if (dl_iterate_phdr(FindMapping, &dl_params) == 1) { - Debug("Hugepages info: start: %p - sym: %p - end: %p\n", + Debug("start: %p - sym: %p - end: %p\n", reinterpret_cast(dl_params.start), reinterpret_cast(dl_params.reference_sym), reinterpret_cast(dl_params.end)); dl_params.start = dl_params.reference_sym; if (lpstub_start > dl_params.start && lpstub_start <= dl_params.end) { - Debug("Hugepages info: Trimming end for lpstub: %p\n", + Debug("Trimming end for lpstub: %p\n", reinterpret_cast(lpstub_start)); dl_params.end = lpstub_start; } @@ -211,14 +208,13 @@ struct text_region FindNodeTextRegion() { if (dl_params.start < dl_params.end) { char* from = reinterpret_cast(hugepage_align_up(dl_params.start)); char* to = reinterpret_cast(hugepage_align_down(dl_params.end)); - Debug("Hugepages info: Aligned range is %p - %p\n", from, to); + Debug("Aligned range is %p - %p\n", from, to); if (from < to) { size_t pagecount = (to - from) / hps; if (pagecount > 0) { nregion.found_text_region = true; nregion.from = from; nregion.to = to; - nregion.total_hugepages = pagecount; } } } @@ -242,14 +238,12 @@ struct text_region FindNodeTextRegion() { } else { char* start = reinterpret_cast(hugepage_align_up(addr)); char* end = reinterpret_cast(hugepage_align_down(addr+size)); - size_t esize = end - start; if (end > start && (map.protection & VM_PROT_READ) != 0 && (map.protection & VM_PROT_EXECUTE) != 0) { nregion.found_text_region = true; nregion.from = start; nregion.to = end; - nregion.total_hugepages = esize / hps; break; } @@ -258,7 +252,7 @@ struct text_region FindNodeTextRegion() { } } #endif - Debug("Hugepages info: Found %d huge pages\n", nregion.total_hugepages); + Debug("Found %d huge pages\n", (nregion.to - nregion.from) / hps); return nregion; } diff --git a/src/module_wrap.cc b/src/module_wrap.cc index 13dd331e6b23e1..59ef9daf727ed5 100644 --- a/src/module_wrap.cc +++ b/src/module_wrap.cc @@ -375,7 +375,13 @@ void ModuleWrap::Evaluate(const FunctionCallbackInfo& args) { return; } - args.GetReturnValue().Set(result.ToLocalChecked()); + // If TLA is enabled, `result` is the evaluation's promise. + // Otherwise, `result` is the last evaluated value of the module, + // which could be a promise, which would result in it being incorrectly + // unwrapped when the higher level code awaits the evaluation. + if (env->isolate_data()->options()->experimental_top_level_await) { + args.GetReturnValue().Set(result.ToLocalChecked()); + } } void ModuleWrap::GetNamespace(const FunctionCallbackInfo& args) { @@ -387,13 +393,17 @@ void ModuleWrap::GetNamespace(const FunctionCallbackInfo& args) { Local module = obj->module_.Get(isolate); switch (module->GetStatus()) { - default: + case v8::Module::Status::kUninstantiated: + case v8::Module::Status::kInstantiating: return env->ThrowError( - "cannot get namespace, Module has not been instantiated"); + "cannot get namespace, module has not been instantiated"); case v8::Module::Status::kInstantiated: case v8::Module::Status::kEvaluating: case v8::Module::Status::kEvaluated: + case v8::Module::Status::kErrored: break; + default: + UNREACHABLE(); } Local result = module->GetModuleNamespace(); @@ -616,19 +626,19 @@ MaybeLocal ModuleWrap::SyntheticModuleEvaluationStepsCallback( TryCatchScope try_catch(env); Local synthetic_evaluation_steps = obj->synthetic_evaluation_steps_.Get(isolate); + obj->synthetic_evaluation_steps_.Reset(); MaybeLocal ret = synthetic_evaluation_steps->Call(context, obj->object(), 0, nullptr); if (ret.IsEmpty()) { CHECK(try_catch.HasCaught()); } - obj->synthetic_evaluation_steps_.Reset(); if (try_catch.HasCaught() && !try_catch.HasTerminated()) { CHECK(!try_catch.Message().IsEmpty()); CHECK(!try_catch.Exception().IsEmpty()); try_catch.ReThrow(); return MaybeLocal(); } - return ret; + return Undefined(isolate); } void ModuleWrap::SetSyntheticExport(const FunctionCallbackInfo& args) { diff --git a/src/node.cc b/src/node.cc index 649ac43fbe7f80..bc8017bdd06029 100644 --- a/src/node.cc +++ b/src/node.cc @@ -124,10 +124,8 @@ using native_module::NativeModuleEnv; using v8::EscapableHandleScope; using v8::Function; using v8::FunctionCallbackInfo; -using v8::HandleScope; using v8::Isolate; using v8::Local; -using v8::Maybe; using v8::MaybeLocal; using v8::Object; using v8::String; @@ -171,11 +169,11 @@ MaybeLocal ExecuteBootstrapper(Environment* env, MaybeLocal maybe_fn = NativeModuleEnv::LookupAndCompile(env->context(), id, parameters, env); - if (maybe_fn.IsEmpty()) { + Local fn; + if (!maybe_fn.ToLocal(&fn)) { return MaybeLocal(); } - Local fn = maybe_fn.ToLocalChecked(); MaybeLocal result = fn->Call(env->context(), Undefined(env->isolate()), arguments->size(), @@ -229,11 +227,56 @@ int Environment::InitializeInspector( } #endif // HAVE_INSPECTOR && NODE_USE_V8_PLATFORM +#define ATOMIC_WAIT_EVENTS(V) \ + V(kStartWait, "started") \ + V(kWokenUp, "was woken up by another thread") \ + V(kTimedOut, "timed out") \ + V(kTerminatedExecution, "was stopped by terminated execution") \ + V(kAPIStopped, "was stopped through the embedder API") \ + V(kNotEqual, "did not wait because the values mismatched") \ + +static void AtomicsWaitCallback(Isolate::AtomicsWaitEvent event, + Local array_buffer, + size_t offset_in_bytes, int64_t value, + double timeout_in_ms, + Isolate::AtomicsWaitWakeHandle* stop_handle, + void* data) { + Environment* env = static_cast(data); + + const char* message = "(unknown event)"; + switch (event) { +#define V(key, msg) \ + case Isolate::AtomicsWaitEvent::key: \ + message = msg; \ + break; + ATOMIC_WAIT_EVENTS(V) +#undef V + } + + fprintf(stderr, + "(node:%d) [Thread %" PRIu64 "] Atomics.wait(%p + %zx, %" PRId64 + ", %.f) %s\n", + static_cast(uv_os_getpid()), + env->thread_id(), + array_buffer->GetBackingStore()->Data(), + offset_in_bytes, + value, + timeout_in_ms, + message); +} + void Environment::InitializeDiagnostics() { isolate_->GetHeapProfiler()->AddBuildEmbedderGraphCallback( Environment::BuildEmbedderGraph, this); if (options_->trace_uncaught) isolate_->SetCaptureStackTraceForUncaughtExceptions(true); + if (options_->trace_atomics_wait) { + isolate_->SetAtomicsWaitCallback(AtomicsWaitCallback, this); + AddCleanupHook([](void* data) { + Environment* env = static_cast(data); + env->isolate()->SetAtomicsWaitCallback(nullptr, nullptr); + }, this); + } #if defined HAVE_DTRACE || defined HAVE_ETW InitDTrace(this); @@ -331,8 +374,7 @@ MaybeLocal Environment::BootstrapNode() { Local env_string = FIXED_ONE_BYTE_STRING(isolate_, "env"); Local env_var_proxy; - if (!CreateEnvVarProxy(context(), isolate_, current_callback_data()) - .ToLocal(&env_var_proxy) || + if (!CreateEnvVarProxy(context(), isolate_).ToLocal(&env_var_proxy) || process_object()->Set(context(), env_string, env_var_proxy).IsNothing()) { return MaybeLocal(); } diff --git a/src/node.h b/src/node.h index 7fbbdb7ea23601..610d72ba8bf6ba 100644 --- a/src/node.h +++ b/src/node.h @@ -351,8 +351,6 @@ struct IsolateSettings { v8::PromiseRejectCallback promise_reject_callback = nullptr; v8::AllowWasmCodeGenerationCallback allow_wasm_code_generation_callback = nullptr; - v8::HostCleanupFinalizationGroupCallback - host_cleanup_finalization_group_callback = nullptr; }; // Overriding IsolateSettings may produce unexpected behavior diff --git a/src/node_binding.cc b/src/node_binding.cc index 592d0ca2a397e2..fdd84c39a20b01 100644 --- a/src/node_binding.cc +++ b/src/node_binding.cc @@ -230,6 +230,7 @@ namespace node { using v8::Context; using v8::Exception; +using v8::Function; using v8::FunctionCallbackInfo; using v8::Local; using v8::NewStringType; @@ -556,8 +557,11 @@ inline struct node_module* FindModule(struct node_module* list, static Local InitModule(Environment* env, node_module* mod, Local module) { - Local exports = Object::New(env->isolate()); // Internal bindings don't have a "module" object, only exports. + Local ctor = env->binding_data_ctor_template() + ->GetFunction(env->context()) + .ToLocalChecked(); + Local exports = ctor->NewInstance(env->context()).ToLocalChecked(); CHECK_NULL(mod->nm_register_func); CHECK_NOT_NULL(mod->nm_context_register_func); Local unused = Undefined(env->isolate()); diff --git a/src/node_buffer.cc b/src/node_buffer.cc index 1ff60ad721753e..fd20415936e169 100644 --- a/src/node_buffer.cc +++ b/src/node_buffer.cc @@ -69,109 +69,130 @@ using v8::Uint32; using v8::Uint32Array; using v8::Uint8Array; using v8::Value; -using v8::WeakCallbackInfo; namespace { class CallbackInfo { public: - ~CallbackInfo(); - - static inline void Free(char* data, void* hint); - static inline CallbackInfo* New(Environment* env, - Local object, - FreeCallback callback, - char* data, - void* hint = nullptr); + static inline Local CreateTrackedArrayBuffer( + Environment* env, + char* data, + size_t length, + FreeCallback callback, + void* hint); CallbackInfo(const CallbackInfo&) = delete; CallbackInfo& operator=(const CallbackInfo&) = delete; private: static void CleanupHook(void* data); - static void WeakCallback(const WeakCallbackInfo&); - inline void WeakCallback(Isolate* isolate); + inline void OnBackingStoreFree(); + inline void CallAndResetCallback(); inline CallbackInfo(Environment* env, - Local object, FreeCallback callback, char* data, void* hint); Global persistent_; - FreeCallback const callback_; + Mutex mutex_; // Protects callback_. + FreeCallback callback_; char* const data_; void* const hint_; Environment* const env_; }; -void CallbackInfo::Free(char* data, void*) { - ::free(data); -} - +Local CallbackInfo::CreateTrackedArrayBuffer( + Environment* env, + char* data, + size_t length, + FreeCallback callback, + void* hint) { + CHECK_NOT_NULL(callback); + CHECK_IMPLIES(data == nullptr, length == 0); + + CallbackInfo* self = new CallbackInfo(env, callback, data, hint); + std::unique_ptr bs = + ArrayBuffer::NewBackingStore(data, length, [](void*, size_t, void* arg) { + static_cast(arg)->OnBackingStoreFree(); + }, self); + Local ab = ArrayBuffer::New(env->isolate(), std::move(bs)); + + // V8 simply ignores the BackingStore deleter callback if data == nullptr, + // but our API contract requires it being called. + if (data == nullptr) { + ab->Detach(); + self->OnBackingStoreFree(); // This calls `callback` asynchronously. + } else { + // Store the ArrayBuffer so that we can detach it later. + self->persistent_.Reset(env->isolate(), ab); + self->persistent_.SetWeak(); + } -CallbackInfo* CallbackInfo::New(Environment* env, - Local object, - FreeCallback callback, - char* data, - void* hint) { - return new CallbackInfo(env, object, callback, data, hint); + return ab; } CallbackInfo::CallbackInfo(Environment* env, - Local object, FreeCallback callback, char* data, void* hint) - : persistent_(env->isolate(), object), - callback_(callback), + : callback_(callback), data_(data), hint_(hint), env_(env) { - std::shared_ptr obj_backing = object->GetBackingStore(); - CHECK_EQ(data_, static_cast(obj_backing->Data())); - if (object->ByteLength() != 0) - CHECK_NOT_NULL(data_); - - persistent_.SetWeak(this, WeakCallback, v8::WeakCallbackType::kParameter); env->AddCleanupHook(CleanupHook, this); env->isolate()->AdjustAmountOfExternalAllocatedMemory(sizeof(*this)); } - -CallbackInfo::~CallbackInfo() { - persistent_.Reset(); - env_->RemoveCleanupHook(CleanupHook, this); -} - - void CallbackInfo::CleanupHook(void* data) { CallbackInfo* self = static_cast(data); { HandleScope handle_scope(self->env_->isolate()); Local ab = self->persistent_.Get(self->env_->isolate()); - CHECK(!ab.IsEmpty()); - if (ab->IsDetachable()) + if (!ab.IsEmpty() && ab->IsDetachable()) { ab->Detach(); + self->persistent_.Reset(); + } } - self->WeakCallback(self->env_->isolate()); + // Call the callback in this case, but don't delete `this` yet because the + // BackingStore deleter callback will do so later. + self->CallAndResetCallback(); } +void CallbackInfo::CallAndResetCallback() { + FreeCallback callback; + { + Mutex::ScopedLock lock(mutex_); + callback = callback_; + callback_ = nullptr; + } + if (callback != nullptr) { + // Clean up all Environment-related state and run the callback. + env_->RemoveCleanupHook(CleanupHook, this); + int64_t change_in_bytes = -static_cast(sizeof(*this)); + env_->isolate()->AdjustAmountOfExternalAllocatedMemory(change_in_bytes); -void CallbackInfo::WeakCallback( - const WeakCallbackInfo& data) { - CallbackInfo* self = data.GetParameter(); - self->WeakCallback(data.GetIsolate()); + callback(data_, hint_); + } } - -void CallbackInfo::WeakCallback(Isolate* isolate) { - callback_(data_, hint_); - int64_t change_in_bytes = -static_cast(sizeof(*this)); - isolate->AdjustAmountOfExternalAllocatedMemory(change_in_bytes); - delete this; +void CallbackInfo::OnBackingStoreFree() { + // This method should always release the memory for `this`. + std::unique_ptr self { this }; + Mutex::ScopedLock lock(mutex_); + // If callback_ == nullptr, that means that the callback has already run from + // the cleanup hook, and there is nothing left to do here besides to clean + // up the memory involved. In particular, the underlying `Environment` may + // be gone at this point, so don’t attempt to call SetImmediateThreadsafe(). + if (callback_ == nullptr) return; + + env_->SetImmediateThreadsafe([self = std::move(self)](Environment* env) { + CHECK_EQ(self->env_, env); // Consistency check. + + self->CallAndResetCallback(); + }); } @@ -408,26 +429,15 @@ MaybeLocal New(Environment* env, return Local(); } - - // The buffer will be released by a CallbackInfo::New() below, - // hence this BackingStore callback is empty. - std::unique_ptr backing = - ArrayBuffer::NewBackingStore(data, - length, - [](void*, size_t, void*){}, - nullptr); - Local ab = ArrayBuffer::New(env->isolate(), - std::move(backing)); + Local ab = + CallbackInfo::CreateTrackedArrayBuffer(env, data, length, callback, hint); if (ab->SetPrivate(env->context(), env->arraybuffer_untransferable_private_symbol(), True(env->isolate())).IsNothing()) { - callback(data, hint); return Local(); } MaybeLocal ui = Buffer::New(env, ab, 0, length); - CallbackInfo::New(env, ab, callback, data, hint); - if (ui.IsEmpty()) return MaybeLocal(); diff --git a/src/node_context_data.h b/src/node_context_data.h index 807ba56c7c69fb..912e65b42707fa 100644 --- a/src/node_context_data.h +++ b/src/node_context_data.h @@ -25,11 +25,16 @@ namespace node { #define NODE_CONTEXT_TAG 35 #endif +#ifndef NODE_BINDING_LIST +#define NODE_BINDING_LIST_INDEX 36 +#endif + enum ContextEmbedderIndex { kEnvironment = NODE_CONTEXT_EMBEDDER_DATA_INDEX, kSandboxObject = NODE_CONTEXT_SANDBOX_OBJECT_INDEX, kAllowWasmCodeGeneration = NODE_CONTEXT_ALLOW_WASM_CODE_GENERATION_INDEX, kContextTag = NODE_CONTEXT_TAG, + kBindingListIndex = NODE_BINDING_LIST_INDEX }; } // namespace node diff --git a/src/node_crypto.cc b/src/node_crypto.cc index afdb2e3c270348..d2f67808ce9bde 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -505,7 +505,7 @@ void SecureContext::Initialize(Environment* env, Local target) { Local ctx_getter_templ = FunctionTemplate::New(env->isolate(), CtxGetter, - env->current_callback_data(), + Local(), Signature::New(env->isolate(), t)); @@ -2923,7 +2923,7 @@ ByteSource ByteSource::NullTerminatedCopy(Environment* env, ByteSource ByteSource::FromSymmetricKeyObject(Local handle) { CHECK(handle->IsObject()); KeyObject* key = Unwrap(handle.As()); - CHECK(key); + CHECK_NOT_NULL(key); return Foreign(key->GetSymmetricKey(), key->GetSymmetricKeySize()); } @@ -3129,7 +3129,7 @@ static ManagedEVPPKey GetPublicOrPrivateKeyFromJs( } else { CHECK(args[*offset]->IsObject()); KeyObject* key = Unwrap(args[*offset].As()); - CHECK(key); + CHECK_NOT_NULL(key); CHECK_NE(key->GetKeyType(), kKeyTypeSecret); (*offset) += 4; return key->GetAsymmetricKey(); @@ -3271,7 +3271,7 @@ MaybeLocal KeyObject::Create(Environment* env, } KeyObject* key = Unwrap(obj); - CHECK(key); + CHECK_NOT_NULL(key); if (key_type == kKeyTypePublic) key->InitPublic(pkey); else @@ -5103,7 +5103,7 @@ void DiffieHellman::Initialize(Environment* env, Local target) { Local verify_error_getter_templ = FunctionTemplate::New(env->isolate(), DiffieHellman::VerifyErrorGetter, - env->current_callback_data(), + Local(), Signature::New(env->isolate(), t), /* length */ 0, ConstructorBehavior::kThrow, diff --git a/src/node_dir.cc b/src/node_dir.cc index c4aaf4bcd3e8ba..b0904c3d39ddd0 100644 --- a/src/node_dir.cc +++ b/src/node_dir.cc @@ -197,8 +197,8 @@ static MaybeLocal DirentListToArray( } static void AfterDirRead(uv_fs_t* req) { - FSReqBase* req_wrap = FSReqBase::from_req(req); - FSReqAfterScope after(req_wrap, req); + BaseObjectPtr req_wrap { FSReqBase::from_req(req) }; + FSReqAfterScope after(req_wrap.get(), req); if (!after.Proceed()) { return; @@ -210,12 +210,12 @@ static void AfterDirRead(uv_fs_t* req) { if (req->result == 0) { // Done Local done = Null(isolate); + after.Clear(); req_wrap->Resolve(done); return; } uv_dir_t* dir = static_cast(req->ptr); - req->ptr = nullptr; Local error; Local js_array; @@ -224,9 +224,13 @@ static void AfterDirRead(uv_fs_t* req) { req->result, req_wrap->encoding(), &error).ToLocal(&js_array)) { + // Clear libuv resources *before* delivering results to JS land because + // that can schedule another operation on the same uv_dir_t. Ditto below. + after.Clear(); return req_wrap->Reject(error); } + after.Clear(); req_wrap->Resolve(js_array); } diff --git a/src/node_env_var.cc b/src/node_env_var.cc index 8eaf79538a26e7..23eaad48586130 100644 --- a/src/node_env_var.cc +++ b/src/node_env_var.cc @@ -377,13 +377,11 @@ static void EnvEnumerator(const PropertyCallbackInfo& info) { env->env_vars()->Enumerate(env->isolate())); } -MaybeLocal CreateEnvVarProxy(Local context, - Isolate* isolate, - Local data) { +MaybeLocal CreateEnvVarProxy(Local context, Isolate* isolate) { EscapableHandleScope scope(isolate); Local env_proxy_template = ObjectTemplate::New(isolate); env_proxy_template->SetHandler(NamedPropertyHandlerConfiguration( - EnvGetter, EnvSetter, EnvQuery, EnvDeleter, EnvEnumerator, data, + EnvGetter, EnvSetter, EnvQuery, EnvDeleter, EnvEnumerator, Local(), PropertyHandlerFlags::kHasNoSideEffect)); return scope.EscapeMaybe(env_proxy_template->NewInstance(context)); } diff --git a/src/node_errors.h b/src/node_errors.h index 3c57f4b8b02fee..f79b87afd2d525 100644 --- a/src/node_errors.h +++ b/src/node_errors.h @@ -54,6 +54,7 @@ void OnFatalError(const char* location, const char* message); V(ERR_TRANSFERRING_EXTERNALIZED_SHAREDARRAYBUFFER, TypeError) \ V(ERR_TLS_PSK_SET_IDENTIY_HINT_FAILED, Error) \ V(ERR_VM_MODULE_CACHED_DATA_REJECTED, Error) \ + V(ERR_WASI_NOT_STARTED, Error) \ V(ERR_WORKER_INIT_FAILED, Error) \ V(ERR_PROTO_ACCESS, Error) @@ -104,6 +105,7 @@ void OnFatalError(const char* location, const char* message); V(ERR_TRANSFERRING_EXTERNALIZED_SHAREDARRAYBUFFER, \ "Cannot serialize externalized SharedArrayBuffer") \ V(ERR_TLS_PSK_SET_IDENTIY_HINT_FAILED, "Failed to set PSK identity hint") \ + V(ERR_WASI_NOT_STARTED, "wasi.start() has not been called") \ V(ERR_WORKER_INIT_FAILED, "Worker initialization failure") \ V(ERR_PROTO_ACCESS, \ "Accessing Object.prototype.__proto__ has been " \ diff --git a/src/node_file-inl.h b/src/node_file-inl.h index d30d77301005a3..2ad8c73f05e490 100644 --- a/src/node_file-inl.h +++ b/src/node_file-inl.h @@ -227,7 +227,7 @@ FSReqBase* GetReqWrap(const v8::FunctionCallbackInfo& args, return Unwrap(value.As()); } - BindingData* binding_data = Unwrap(args.Data()); + BindingData* binding_data = Environment::GetBindingData(args); Environment* env = binding_data->env(); if (value->StrictEquals(env->fs_use_promises_symbol())) { if (use_bigint) { diff --git a/src/node_file.cc b/src/node_file.cc index 203ec5c8ca57b1..96adbc9e756688 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -158,7 +158,7 @@ FileHandle* FileHandle::New(BindingData* binding_data, } void FileHandle::New(const FunctionCallbackInfo& args) { - BindingData* binding_data = Unwrap(args.Data()); + BindingData* binding_data = Environment::GetBindingData(args); Environment* env = binding_data->env(); CHECK(args.IsConstructCall()); CHECK(args[0]->IsInt32()); @@ -543,7 +543,7 @@ void FSReqCallback::SetReturnValue(const FunctionCallbackInfo& args) { void NewFSReqCallback(const FunctionCallbackInfo& args) { CHECK(args.IsConstructCall()); - BindingData* binding_data = Unwrap(args.Data()); + BindingData* binding_data = Environment::GetBindingData(args); new FSReqCallback(binding_data, args.This(), args[0]->IsTrue()); } @@ -556,8 +556,15 @@ FSReqAfterScope::FSReqAfterScope(FSReqBase* wrap, uv_fs_t* req) } FSReqAfterScope::~FSReqAfterScope() { + Clear(); +} + +void FSReqAfterScope::Clear() { + if (!wrap_) return; + uv_fs_req_cleanup(wrap_->req()); - delete wrap_; + wrap_->Detach(); + wrap_.reset(); } // TODO(joyeecheung): create a normal context object, and @@ -570,12 +577,16 @@ FSReqAfterScope::~FSReqAfterScope() { // which is also why the errors should have been constructed // in JS for more flexibility. void FSReqAfterScope::Reject(uv_fs_t* req) { - wrap_->Reject(UVException(wrap_->env()->isolate(), - req->result, - wrap_->syscall(), - nullptr, - req->path, - wrap_->data())); + BaseObjectPtr wrap { wrap_ }; + Local exception = + UVException(wrap_->env()->isolate(), + req->result, + wrap_->syscall(), + nullptr, + req->path, + wrap_->data()); + Clear(); + wrap->Reject(exception); } bool FSReqAfterScope::Proceed() { @@ -948,7 +959,7 @@ static void InternalModuleStat(const FunctionCallbackInfo& args) { } static void Stat(const FunctionCallbackInfo& args) { - BindingData* binding_data = Unwrap(args.Data()); + BindingData* binding_data = Environment::GetBindingData(args); Environment* env = binding_data->env(); const int argc = args.Length(); @@ -979,7 +990,7 @@ static void Stat(const FunctionCallbackInfo& args) { } static void LStat(const FunctionCallbackInfo& args) { - BindingData* binding_data = Unwrap(args.Data()); + BindingData* binding_data = Environment::GetBindingData(args); Environment* env = binding_data->env(); const int argc = args.Length(); @@ -1011,7 +1022,7 @@ static void LStat(const FunctionCallbackInfo& args) { } static void FStat(const FunctionCallbackInfo& args) { - BindingData* binding_data = Unwrap(args.Data()); + BindingData* binding_data = Environment::GetBindingData(args); Environment* env = binding_data->env(); const int argc = args.Length(); @@ -1674,7 +1685,7 @@ static void Open(const FunctionCallbackInfo& args) { } static void OpenFileHandle(const FunctionCallbackInfo& args) { - BindingData* binding_data = Unwrap(args.Data()); + BindingData* binding_data = Environment::GetBindingData(args); Environment* env = binding_data->env(); Isolate* isolate = env->isolate(); @@ -2303,15 +2314,18 @@ void BindingData::MemoryInfo(MemoryTracker* tracker) const { file_handle_read_wrap_freelist); } +// TODO(addaleax): Remove once we're on C++17. +constexpr FastStringKey BindingData::binding_data_name; + void Initialize(Local target, Local unused, Local context, void* priv) { Environment* env = Environment::GetCurrent(context); Isolate* isolate = env->isolate(); - Environment::BindingScope binding_scope(env); - if (!binding_scope) return; - BindingData* binding_data = binding_scope.data; + BindingData* const binding_data = + env->AddBindingData(context, target); + if (binding_data == nullptr) return; env->SetMethod(target, "access", Access); env->SetMethod(target, "close", Close); diff --git a/src/node_file.h b/src/node_file.h index 1fda81361fef79..39c9034f669ea7 100644 --- a/src/node_file.h +++ b/src/node_file.h @@ -16,9 +16,9 @@ class FileHandleReadWrap; class BindingData : public BaseObject { public: explicit BindingData(Environment* env, v8::Local wrap) - : BaseObject(env, wrap), - stats_field_array(env->isolate(), kFsStatsBufferLength), - stats_field_bigint_array(env->isolate(), kFsStatsBufferLength) {} + : BaseObject(env, wrap), + stats_field_array(env->isolate(), kFsStatsBufferLength), + stats_field_bigint_array(env->isolate(), kFsStatsBufferLength) {} AliasedFloat64Array stats_field_array; AliasedBigUint64Array stats_field_bigint_array; @@ -26,6 +26,8 @@ class BindingData : public BaseObject { std::vector> file_handle_read_wrap_freelist; + static constexpr FastStringKey binding_data_name { "fs" }; + void MemoryInfo(MemoryTracker* tracker) const override; SET_SELF_SIZE(BindingData) SET_MEMORY_INFO_NAME(BindingData) @@ -182,6 +184,7 @@ class FSReqAfterScope final { public: FSReqAfterScope(FSReqBase* wrap, uv_fs_t* req); ~FSReqAfterScope(); + void Clear(); bool Proceed(); @@ -193,7 +196,7 @@ class FSReqAfterScope final { FSReqAfterScope& operator=(const FSReqAfterScope&&) = delete; private: - FSReqBase* wrap_ = nullptr; + BaseObjectPtr wrap_; uv_fs_t* req_ = nullptr; v8::HandleScope handle_scope_; v8::Context::Scope context_scope_; diff --git a/src/node_http2.cc b/src/node_http2.cc index 6637166e954267..25f353bb1477e0 100644 --- a/src/node_http2.cc +++ b/src/node_http2.cc @@ -2351,7 +2351,7 @@ void HttpErrorString(const FunctionCallbackInfo& args) { // would be suitable, for instance, for creating the Base64 // output for an HTTP2-Settings header field. void PackSettings(const FunctionCallbackInfo& args) { - Http2State* state = Unwrap(args.Data()); + Http2State* state = Environment::GetBindingData(args); args.GetReturnValue().Set(Http2Settings::Pack(state)); } @@ -2359,7 +2359,7 @@ void PackSettings(const FunctionCallbackInfo& args) { // default SETTINGS. RefreshDefaultSettings updates that TypedArray with the // default values. void RefreshDefaultSettings(const FunctionCallbackInfo& args) { - Http2State* state = Unwrap(args.Data()); + Http2State* state = Environment::GetBindingData(args); Http2Settings::RefreshDefaults(state); } @@ -2423,7 +2423,7 @@ void Http2Session::RefreshState(const FunctionCallbackInfo& args) { // Constructor for new Http2Session instances. void Http2Session::New(const FunctionCallbackInfo& args) { - Http2State* state = Unwrap(args.Data()); + Http2State* state = Environment::GetBindingData(args); Environment* env = state->env(); CHECK(args.IsConstructCall()); SessionType type = @@ -2941,6 +2941,9 @@ void Http2State::MemoryInfo(MemoryTracker* tracker) const { tracker->TrackField("root_buffer", root_buffer); } +// TODO(addaleax): Remove once we're on C++17. +constexpr FastStringKey Http2State::binding_data_name; + // Set up the process.binding('http2') binding. void Initialize(Local target, Local unused, @@ -2950,9 +2953,8 @@ void Initialize(Local target, Isolate* isolate = env->isolate(); HandleScope handle_scope(isolate); - Environment::BindingScope binding_scope(env); - if (!binding_scope) return; - Http2State* state = binding_scope.data; + Http2State* const state = env->AddBindingData(context, target); + if (state == nullptr) return; #define SET_STATE_TYPEDARRAY(name, field) \ target->Set(context, \ diff --git a/src/node_http2_state.h b/src/node_http2_state.h index 80efb40cd27589..2e9d3e5d6bceb5 100644 --- a/src/node_http2_state.h +++ b/src/node_http2_state.h @@ -83,41 +83,36 @@ namespace http2 { class Http2State : public BaseObject { public: Http2State(Environment* env, v8::Local obj) - : BaseObject(env, obj), - root_buffer( - env->isolate(), - sizeof(http2_state_internal)), - session_state_buffer( - env->isolate(), - offsetof(http2_state_internal, session_state_buffer), - IDX_SESSION_STATE_COUNT, - root_buffer), - stream_state_buffer( - env->isolate(), - offsetof(http2_state_internal, stream_state_buffer), - IDX_STREAM_STATE_COUNT, - root_buffer), - stream_stats_buffer( - env->isolate(), - offsetof(http2_state_internal, stream_stats_buffer), - IDX_STREAM_STATS_COUNT, - root_buffer), - session_stats_buffer( - env->isolate(), - offsetof(http2_state_internal, session_stats_buffer), - IDX_SESSION_STATS_COUNT, - root_buffer), - options_buffer( - env->isolate(), - offsetof(http2_state_internal, options_buffer), - IDX_OPTIONS_FLAGS + 1, - root_buffer), - settings_buffer( - env->isolate(), - offsetof(http2_state_internal, settings_buffer), - IDX_SETTINGS_COUNT + 1, - root_buffer) { - } + : BaseObject(env, obj), + root_buffer(env->isolate(), sizeof(http2_state_internal)), + session_state_buffer( + env->isolate(), + offsetof(http2_state_internal, session_state_buffer), + IDX_SESSION_STATE_COUNT, + root_buffer), + stream_state_buffer( + env->isolate(), + offsetof(http2_state_internal, stream_state_buffer), + IDX_STREAM_STATE_COUNT, + root_buffer), + stream_stats_buffer( + env->isolate(), + offsetof(http2_state_internal, stream_stats_buffer), + IDX_STREAM_STATS_COUNT, + root_buffer), + session_stats_buffer( + env->isolate(), + offsetof(http2_state_internal, session_stats_buffer), + IDX_SESSION_STATS_COUNT, + root_buffer), + options_buffer(env->isolate(), + offsetof(http2_state_internal, options_buffer), + IDX_OPTIONS_FLAGS + 1, + root_buffer), + settings_buffer(env->isolate(), + offsetof(http2_state_internal, settings_buffer), + IDX_SETTINGS_COUNT + 1, + root_buffer) {} AliasedUint8Array root_buffer; AliasedFloat64Array session_state_buffer; @@ -131,6 +126,8 @@ class Http2State : public BaseObject { SET_SELF_SIZE(Http2State) SET_MEMORY_INFO_NAME(Http2State) + static constexpr FastStringKey binding_data_name { "http2" }; + private: struct http2_state_internal { // doubles first so that they are always sizeof(double)-aligned diff --git a/src/node_http_common-inl.h b/src/node_http_common-inl.h index 2c76dc3a1fd372..54f2faf39c49bc 100644 --- a/src/node_http_common-inl.h +++ b/src/node_http_common-inl.h @@ -76,6 +76,14 @@ size_t GetServerMaxHeaderPairs(size_t max_header_pairs) { return std::max(max_header_pairs, min_header_pairs); } +template +std::string NgHeaderBase::ToString() const { + std::string ret = name(); + ret += " = "; + ret += value(); + return ret; +} + template bool NgHeader::IsZeroLength( NgHeader::rcbuf_t* name, @@ -132,6 +140,12 @@ NgHeader::NgHeader(NgHeader&& other) noexcept other.env_ = nullptr; } +template +void NgHeader::MemoryInfo(MemoryTracker* tracker) const { + tracker->TrackField("name", name_); + tracker->TrackField("value", value_); +} + template v8::MaybeLocal NgHeader::GetName( NgHeader::allocator_t* allocator) const { diff --git a/src/node_http_common.h b/src/node_http_common.h index d2bdddd93f4649..c7e4d34af24196 100644 --- a/src/node_http_common.h +++ b/src/node_http_common.h @@ -453,6 +453,16 @@ class NgRcBufPointer : public MemoryRetainer { bool internalizable_ = false; }; +template +struct NgHeaderBase : public MemoryRetainer { + virtual v8::MaybeLocal GetName(allocator_t* allocator) const = 0; + virtual v8::MaybeLocal GetValue(allocator_t* allocator) const = 0; + virtual std::string name() const = 0; + virtual std::string value() const = 0; + virtual size_t length() const = 0; + virtual std::string ToString() const; +}; + // The ng libraries use nearly identical structs to represent // received http headers. The NgHeader class wraps those in a // consistent way and allows converting the name and value to @@ -461,7 +471,7 @@ class NgRcBufPointer : public MemoryRetainer { // memory tracking, and implementation of static utility functions. // See Http2HeaderTraits in node_http2.h for an example. template -class NgHeader : public MemoryRetainer { +class NgHeader final : public NgHeaderBase { public: typedef typename T::rcbufferpointer_t rcbufferpointer_t; typedef typename T::rcbufferpointer_t::rcbuf_t rcbuf_t; @@ -487,28 +497,20 @@ class NgHeader : public MemoryRetainer { // object to the v8 string. Once the v8 string is garbage collected, // the reference counter will be decremented. - inline v8::MaybeLocal GetName(allocator_t* allocator) const; - inline v8::MaybeLocal GetValue(allocator_t* allocator) const; + inline v8::MaybeLocal GetName( + allocator_t* allocator) const override; + inline v8::MaybeLocal GetValue( + allocator_t* allocator) const override; - inline std::string name() const; - inline std::string value() const; - inline size_t length() const; + inline std::string name() const override; + inline std::string value() const override; + inline size_t length() const override; - void MemoryInfo(MemoryTracker* tracker) const override { - tracker->TrackField("name", name_); - tracker->TrackField("value", value_); - } + void MemoryInfo(MemoryTracker* tracker) const override; SET_MEMORY_INFO_NAME(NgHeader) SET_SELF_SIZE(NgHeader) - std::string ToString() const { - std::string ret = name(); - ret += " = "; - ret += value(); - return ret; - } - private: Environment* env_; rcbufferpointer_t name_; diff --git a/src/node_http_parser.cc b/src/node_http_parser.cc index f98e9f5c7b6dab..c7a3df8d067af4 100644 --- a/src/node_http_parser.cc +++ b/src/node_http_parser.cc @@ -84,7 +84,10 @@ inline bool IsOWS(char c) { class BindingData : public BaseObject { public: - BindingData(Environment* env, Local obj) : BaseObject(env, obj) {} + BindingData(Environment* env, Local obj) + : BaseObject(env, obj) {} + + static constexpr FastStringKey binding_data_name { "http_parser" }; std::vector parser_buffer; bool parser_buffer_in_use = false; @@ -96,6 +99,9 @@ class BindingData : public BaseObject { SET_MEMORY_INFO_NAME(BindingData) }; +// TODO(addaleax): Remove once we're on C++17. +constexpr FastStringKey BindingData::binding_data_name; + // helper class for the Parser struct StringPtr { StringPtr() { @@ -444,7 +450,7 @@ class Parser : public AsyncWrap, public StreamListener { } static void New(const FunctionCallbackInfo& args) { - BindingData* binding_data = Unwrap(args.Data()); + BindingData* binding_data = Environment::GetBindingData(args); new Parser(binding_data, args.This()); } @@ -920,8 +926,9 @@ void InitializeHttpParser(Local target, Local context, void* priv) { Environment* env = Environment::GetCurrent(context); - Environment::BindingScope binding_scope(env); - if (!binding_scope) return; + BindingData* const binding_data = + env->AddBindingData(context, target); + if (binding_data == nullptr) return; Local t = env->NewFunctionTemplate(Parser::New); t->InstanceTemplate()->SetInternalFieldCount(Parser::kInternalFieldCount); diff --git a/src/node_internals.h b/src/node_internals.h index fa3ba022fe7e23..0ae17f71ecbcb2 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -112,7 +112,7 @@ class NodeArrayBufferAllocator : public ArrayBufferAllocator { void* Allocate(size_t size) override; // Defined in src/node.cc void* AllocateUninitialized(size_t size) override; void Free(void* data, size_t size) override; - virtual void* Reallocate(void* data, size_t old_size, size_t size); + void* Reallocate(void* data, size_t old_size, size_t size) override; virtual void RegisterPointer(void* data, size_t size) { total_mem_usage_.fetch_add(size, std::memory_order_relaxed); } @@ -243,9 +243,9 @@ class InternalCallbackScope { class DebugSealHandleScope { public: - explicit inline DebugSealHandleScope(v8::Isolate* isolate) + explicit inline DebugSealHandleScope(v8::Isolate* isolate = nullptr) #ifdef DEBUG - : actual_scope_(isolate) + : actual_scope_(isolate != nullptr ? isolate : v8::Isolate::GetCurrent()) #endif {} diff --git a/src/node_native_module_env.cc b/src/node_native_module_env.cc index b48ae962dd639f..be647b01c640b0 100644 --- a/src/node_native_module_env.cc +++ b/src/node_native_module_env.cc @@ -190,7 +190,7 @@ void NativeModuleEnv::Initialize(Local target, FIXED_ONE_BYTE_STRING(env->isolate(), "moduleCategories"), GetModuleCategories, nullptr, - env->as_callback_data(), + Local(), DEFAULT, None, SideEffectType::kHasNoSideEffect) diff --git a/src/node_options-inl.h b/src/node_options-inl.h index 682a1c6c47d020..4e1a12296bc77e 100644 --- a/src/node_options-inl.h +++ b/src/node_options-inl.h @@ -138,10 +138,9 @@ void OptionsParser::Implies(const char* from, const char* to) { auto it = options_.find(to); CHECK_NE(it, options_.end()); - CHECK_EQ(it->second.type, kBoolean); - implications_.emplace(from, Implication { - it->second.field, true - }); + CHECK(it->second.type == kBoolean || it->second.type == kV8Option); + implications_.emplace( + from, Implication{it->second.type, to, it->second.field, true}); } template @@ -150,9 +149,8 @@ void OptionsParser::ImpliesNot(const char* from, auto it = options_.find(to); CHECK_NE(it, options_.end()); CHECK_EQ(it->second.type, kBoolean); - implications_.emplace(from, Implication { - it->second.field, false - }); + implications_.emplace( + from, Implication{it->second.type, to, it->second.field, false}); } template @@ -196,9 +194,11 @@ template auto OptionsParser::Convert( typename OptionsParser::Implication original, ChildOptions* (Options::* get_child)()) { - return Implication { - Convert(original.target_field, get_child), - original.target_value + return Implication{ + original.type, + original.name, + Convert(original.target_field, get_child), + original.target_value, }; } @@ -366,19 +366,23 @@ void OptionsParser::Parse( break; } - if (it == options_.end()) { - v8_args->push_back(arg); - continue; - } - { auto implications = implications_.equal_range(name); for (auto it = implications.first; it != implications.second; ++it) { - *it->second.target_field->template Lookup(options) = - it->second.target_value; + if (it->second.type == kV8Option) { + v8_args->push_back(it->second.name); + } else { + *it->second.target_field->template Lookup(options) = + it->second.target_value; + } } } + if (it == options_.end()) { + v8_args->push_back(arg); + continue; + } + const OptionInfo& info = it->second; std::string value; if (info.type != kBoolean && info.type != kNoOp && info.type != kV8Option) { diff --git a/src/node_options.cc b/src/node_options.cc index 3b9142c19e98a8..013c3ef825efd6 100644 --- a/src/node_options.cc +++ b/src/node_options.cc @@ -435,6 +435,10 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { "throw an exception on deprecations", &EnvironmentOptions::throw_deprecation, kAllowedInEnvironment); + AddOption("--trace-atomics-wait", + "trace Atomics.wait() operations", + &EnvironmentOptions::trace_atomics_wait, + kAllowedInEnvironment); AddOption("--trace-deprecation", "show stack traces on deprecations", &EnvironmentOptions::trace_deprecation, @@ -593,6 +597,13 @@ PerIsolateOptionsParser::PerIsolateOptionsParser( kAllowedInEnvironment); Implies("--report-signal", "--report-on-signal"); + AddOption("--experimental-top-level-await", + "enable experimental support for ECMAScript Top-Level Await", + &PerIsolateOptions::experimental_top_level_await); + AddOption("--harmony-top-level-await", "", V8Option{}); + Implies("--experimental-top-level-await", "--harmony-top-level-await"); + Implies("--harmony-top-level-await", "--experimental-top-level-await"); + Insert(eop, &PerIsolateOptions::get_per_env_options); } diff --git a/src/node_options.h b/src/node_options.h index 539e41e67ac6ee..54710e487701dd 100644 --- a/src/node_options.h +++ b/src/node_options.h @@ -140,6 +140,7 @@ class EnvironmentOptions : public Options { std::string redirect_warnings; bool test_udp_no_try_send = false; bool throw_deprecation = false; + bool trace_atomics_wait = false; bool trace_deprecation = false; bool trace_exit = false; bool trace_sync_io = false; @@ -186,6 +187,7 @@ class PerIsolateOptions : public Options { bool no_node_snapshot = false; bool report_uncaught_exception = false; bool report_on_signal = false; + bool experimental_top_level_await = false; std::string report_signal = "SIGUSR2"; inline EnvironmentOptions* get_per_env_options(); void CheckOptions(std::vector* errors) override; @@ -418,6 +420,8 @@ class OptionsParser { // An implied option is composed of the information on where to store a // specific boolean value (if another specific option is encountered). struct Implication { + OptionType type; + std::string name; std::shared_ptr target_field; bool target_value; }; diff --git a/src/node_process.h b/src/node_process.h index ad86b449f95290..2e87385348d936 100644 --- a/src/node_process.h +++ b/src/node_process.h @@ -8,8 +8,7 @@ namespace node { v8::MaybeLocal CreateEnvVarProxy(v8::Local context, - v8::Isolate* isolate, - v8::Local data); + v8::Isolate* isolate); // Most of the time, it's best to use `console.error` to write // to the process.stderr stream. However, in some cases, such as diff --git a/src/node_process_object.cc b/src/node_process_object.cc index ee7d771c717c0a..ca17da9583efc8 100644 --- a/src/node_process_object.cc +++ b/src/node_process_object.cc @@ -147,7 +147,7 @@ void PatchProcessObject(const FunctionCallbackInfo& args) { FIXED_ONE_BYTE_STRING(isolate, "title"), ProcessTitleGetter, env->owns_process_state() ? ProcessTitleSetter : nullptr, - env->current_callback_data(), + Local(), DEFAULT, None, SideEffectType::kHasNoSideEffect) @@ -198,7 +198,7 @@ void PatchProcessObject(const FunctionCallbackInfo& args) { FIXED_ONE_BYTE_STRING(isolate, "debugPort"), DebugPortGetter, env->owns_process_state() ? DebugPortSetter : nullptr, - env->current_callback_data()) + Local()) .FromJust()); } diff --git a/src/node_stat_watcher.cc b/src/node_stat_watcher.cc index af23affc412935..70903525baa735 100644 --- a/src/node_stat_watcher.cc +++ b/src/node_stat_watcher.cc @@ -95,7 +95,8 @@ void StatWatcher::Callback(uv_fs_poll_t* handle, void StatWatcher::New(const FunctionCallbackInfo& args) { CHECK(args.IsConstructCall()); - fs::BindingData* binding_data = Unwrap(args.Data()); + fs::BindingData* binding_data = + Environment::GetBindingData(args); new StatWatcher(binding_data, args.This(), args[0]->IsTrue()); } diff --git a/src/node_v8.cc b/src/node_v8.cc index 7174d9ae7f830b..047ca594095d16 100644 --- a/src/node_v8.cc +++ b/src/node_v8.cc @@ -96,6 +96,8 @@ class BindingData : public BaseObject { heap_code_statistics_buffer(env->isolate(), kHeapCodeStatisticsPropertiesCount) {} + static constexpr FastStringKey binding_data_name { "v8" }; + AliasedFloat64Array heap_statistics_buffer; AliasedFloat64Array heap_space_statistics_buffer; AliasedFloat64Array heap_code_statistics_buffer; @@ -111,6 +113,8 @@ class BindingData : public BaseObject { SET_MEMORY_INFO_NAME(BindingData) }; +// TODO(addaleax): Remove once we're on C++17. +constexpr FastStringKey BindingData::binding_data_name; void CachedDataVersionTag(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); @@ -121,7 +125,7 @@ void CachedDataVersionTag(const FunctionCallbackInfo& args) { } void UpdateHeapStatisticsBuffer(const FunctionCallbackInfo& args) { - BindingData* data = Unwrap(args.Data()); + BindingData* data = Environment::GetBindingData(args); HeapStatistics s; args.GetIsolate()->GetHeapStatistics(&s); AliasedFloat64Array& buffer = data->heap_statistics_buffer; @@ -132,7 +136,7 @@ void UpdateHeapStatisticsBuffer(const FunctionCallbackInfo& args) { void UpdateHeapSpaceStatisticsBuffer(const FunctionCallbackInfo& args) { - BindingData* data = Unwrap(args.Data()); + BindingData* data = Environment::GetBindingData(args); HeapSpaceStatistics s; Isolate* const isolate = args.GetIsolate(); CHECK(args[0]->IsUint32()); @@ -147,7 +151,7 @@ void UpdateHeapSpaceStatisticsBuffer(const FunctionCallbackInfo& args) { } void UpdateHeapCodeStatisticsBuffer(const FunctionCallbackInfo& args) { - BindingData* data = Unwrap(args.Data()); + BindingData* data = Environment::GetBindingData(args); HeapCodeStatistics s; args.GetIsolate()->GetHeapCodeAndMetadataStatistics(&s); AliasedFloat64Array& buffer = data->heap_code_statistics_buffer; @@ -170,9 +174,9 @@ void Initialize(Local target, Local context, void* priv) { Environment* env = Environment::GetCurrent(context); - Environment::BindingScope binding_scope(env); - if (!binding_scope) return; - BindingData* binding_data = binding_scope.data; + BindingData* const binding_data = + env->AddBindingData(context, target); + if (binding_data == nullptr) return; env->SetMethodNoSideEffect(target, "cachedDataVersionTag", CachedDataVersionTag); diff --git a/src/node_version.h b/src/node_version.h index dc2c4f762bce36..f4fbe87b93d10a 100644 --- a/src/node_version.h +++ b/src/node_version.h @@ -23,13 +23,13 @@ #define SRC_NODE_VERSION_H_ #define NODE_MAJOR_VERSION 14 -#define NODE_MINOR_VERSION 2 -#define NODE_PATCH_VERSION 1 +#define NODE_MINOR_VERSION 3 +#define NODE_PATCH_VERSION 0 #define NODE_VERSION_IS_LTS 0 #define NODE_VERSION_LTS_CODENAME "" -#define NODE_VERSION_IS_RELEASE 0 +#define NODE_VERSION_IS_RELEASE 1 #ifndef NODE_STRINGIFY #define NODE_STRINGIFY(n) NODE_STRINGIFY_HELPER(n) diff --git a/src/node_wasi.cc b/src/node_wasi.cc index 0330656b29e926..909023d84e0235 100644 --- a/src/node_wasi.cc +++ b/src/node_wasi.cc @@ -5,6 +5,7 @@ #include "node_mem-inl.h" #include "util-inl.h" #include "node.h" +#include "node_errors.h" #include "uv.h" #include "uvwasi.h" #include "node_wasi.h" @@ -23,6 +24,15 @@ inline void Debug(WASI* wasi, Args&&... args) { Debug(wasi->env(), DebugCategory::WASI, std::forward(args)...); } +#define ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(ptr, obj) \ + do { \ + ASSIGN_OR_RETURN_UNWRAP(ptr, obj); \ + if ((*(ptr))->memory_.IsEmpty()) { \ + THROW_ERR_WASI_NOT_STARTED(Environment::GetCurrent(args)); \ + return; \ + } \ + } while (0) + #define RETURN_IF_BAD_ARG_COUNT(args, expected) \ do { \ if ((args).Length() != (expected)) { \ @@ -250,7 +260,7 @@ void WASI::ArgsGet(const FunctionCallbackInfo& args) { RETURN_IF_BAD_ARG_COUNT(args, 2); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, argv_offset); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, argv_buf_offset); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "args_get(%d, %d)\n", argv_offset, argv_buf_offset); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); CHECK_BOUNDS_OR_RETURN(args, @@ -282,7 +292,7 @@ void WASI::ArgsSizesGet(const FunctionCallbackInfo& args) { RETURN_IF_BAD_ARG_COUNT(args, 2); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, argc_offset); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, argv_buf_offset); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "args_sizes_get(%d, %d)\n", argc_offset, argv_buf_offset); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); CHECK_BOUNDS_OR_RETURN(args, mem_size, argc_offset, 4); @@ -310,7 +320,7 @@ void WASI::ClockResGet(const FunctionCallbackInfo& args) { RETURN_IF_BAD_ARG_COUNT(args, 2); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, clock_id); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, resolution_ptr); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "clock_res_get(%d, %d)\n", clock_id, resolution_ptr); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); CHECK_BOUNDS_OR_RETURN(args, mem_size, resolution_ptr, 8); @@ -336,7 +346,7 @@ void WASI::ClockTimeGet(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, clock_id); UNWRAP_BIGINT_OR_RETURN(args, args[1], Uint64, precision); CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, time_ptr); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "clock_time_get(%d, %d, %d)\n", clock_id, precision, time_ptr); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); CHECK_BOUNDS_OR_RETURN(args, mem_size, time_ptr, 8); @@ -361,7 +371,7 @@ void WASI::EnvironGet(const FunctionCallbackInfo& args) { RETURN_IF_BAD_ARG_COUNT(args, 2); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, environ_offset); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, environ_buf_offset); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "environ_get(%d, %d)\n", environ_offset, environ_buf_offset); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); CHECK_BOUNDS_OR_RETURN(args, @@ -395,7 +405,7 @@ void WASI::EnvironSizesGet(const FunctionCallbackInfo& args) { RETURN_IF_BAD_ARG_COUNT(args, 2); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, envc_offset); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, env_buf_offset); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "environ_sizes_get(%d, %d)\n", envc_offset, env_buf_offset); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); CHECK_BOUNDS_OR_RETURN(args, mem_size, envc_offset, 4); @@ -425,7 +435,7 @@ void WASI::FdAdvise(const FunctionCallbackInfo& args) { UNWRAP_BIGINT_OR_RETURN(args, args[1], Uint64, offset); UNWRAP_BIGINT_OR_RETURN(args, args[2], Uint64, len); CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, advice); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_advise(%d, %d, %d, %d)\n", fd, offset, len, advice); uvwasi_errno_t err = uvwasi_fd_advise(&wasi->uvw_, fd, offset, len, advice); args.GetReturnValue().Set(err); @@ -441,7 +451,7 @@ void WASI::FdAllocate(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd); UNWRAP_BIGINT_OR_RETURN(args, args[1], Uint64, offset); UNWRAP_BIGINT_OR_RETURN(args, args[2], Uint64, len); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_allocate(%d, %d, %d)\n", fd, offset, len); uvwasi_errno_t err = uvwasi_fd_allocate(&wasi->uvw_, fd, offset, len); args.GetReturnValue().Set(err); @@ -453,7 +463,7 @@ void WASI::FdClose(const FunctionCallbackInfo& args) { uint32_t fd; RETURN_IF_BAD_ARG_COUNT(args, 1); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_close(%d)\n", fd); uvwasi_errno_t err = uvwasi_fd_close(&wasi->uvw_, fd); args.GetReturnValue().Set(err); @@ -465,7 +475,7 @@ void WASI::FdDatasync(const FunctionCallbackInfo& args) { uint32_t fd; RETURN_IF_BAD_ARG_COUNT(args, 1); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_datasync(%d)\n", fd); uvwasi_errno_t err = uvwasi_fd_datasync(&wasi->uvw_, fd); args.GetReturnValue().Set(err); @@ -481,7 +491,7 @@ void WASI::FdFdstatGet(const FunctionCallbackInfo& args) { RETURN_IF_BAD_ARG_COUNT(args, 2); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, buf); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_fdstat_get(%d, %d)\n", fd, buf); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); CHECK_BOUNDS_OR_RETURN(args, mem_size, buf, 24); @@ -506,7 +516,7 @@ void WASI::FdFdstatSetFlags(const FunctionCallbackInfo& args) { RETURN_IF_BAD_ARG_COUNT(args, 2); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, flags); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_fdstat_set_flags(%d, %d)\n", fd, flags); uvwasi_errno_t err = uvwasi_fd_fdstat_set_flags(&wasi->uvw_, fd, flags); args.GetReturnValue().Set(err); @@ -522,7 +532,7 @@ void WASI::FdFdstatSetRights(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd); UNWRAP_BIGINT_OR_RETURN(args, args[1], Uint64, fs_rights_base); UNWRAP_BIGINT_OR_RETURN(args, args[2], Uint64, fs_rights_inheriting); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_fdstat_set_rights(%d, %d, %d)\n", fd, @@ -545,7 +555,7 @@ void WASI::FdFilestatGet(const FunctionCallbackInfo& args) { RETURN_IF_BAD_ARG_COUNT(args, 2); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, buf); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_filestat_get(%d, %d)\n", fd, buf); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); CHECK_BOUNDS_OR_RETURN(args, mem_size, buf, 64); @@ -574,7 +584,7 @@ void WASI::FdFilestatSetSize(const FunctionCallbackInfo& args) { RETURN_IF_BAD_ARG_COUNT(args, 2); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd); UNWRAP_BIGINT_OR_RETURN(args, args[1], Uint64, st_size); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_filestat_set_size(%d, %d)\n", fd, st_size); uvwasi_errno_t err = uvwasi_fd_filestat_set_size(&wasi->uvw_, fd, st_size); args.GetReturnValue().Set(err); @@ -592,7 +602,7 @@ void WASI::FdFilestatSetTimes(const FunctionCallbackInfo& args) { UNWRAP_BIGINT_OR_RETURN(args, args[1], Uint64, st_atim); UNWRAP_BIGINT_OR_RETURN(args, args[2], Uint64, st_mtim); CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, fst_flags); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_filestat_set_times(%d, %d, %d, %d)\n", fd, @@ -623,7 +633,7 @@ void WASI::FdPread(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, iovs_len); UNWRAP_BIGINT_OR_RETURN(args, args[3], Uint64, offset); CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, nread_ptr); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "uvwasi_fd_pread(%d, %d, %d, %d, %d)\n", fd, @@ -683,7 +693,7 @@ void WASI::FdPrestatGet(const FunctionCallbackInfo& args) { RETURN_IF_BAD_ARG_COUNT(args, 2); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, buf); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_prestat_get(%d, %d)\n", fd, buf); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); CHECK_BOUNDS_OR_RETURN(args, mem_size, buf, 8); @@ -710,7 +720,7 @@ void WASI::FdPrestatDirName(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, path_ptr); CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, path_len); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_prestat_dir_name(%d, %d, %d)\n", fd, path_ptr, path_len); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); CHECK_BOUNDS_OR_RETURN(args, mem_size, path_ptr, path_len); @@ -737,7 +747,7 @@ void WASI::FdPwrite(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, iovs_len); UNWRAP_BIGINT_OR_RETURN(args, args[3], Uint64, offset); CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, nwritten_ptr); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "uvwasi_fd_pwrite(%d, %d, %d, %d, %d)\n", fd, @@ -801,7 +811,7 @@ void WASI::FdRead(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, iovs_ptr); CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, iovs_len); CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, nread_ptr); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_read(%d, %d, %d, %d)\n", fd, iovs_ptr, iovs_len, nread_ptr); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); CHECK_BOUNDS_OR_RETURN(args, mem_size, iovs_ptr, iovs_len * 8); @@ -860,7 +870,7 @@ void WASI::FdReaddir(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, buf_len); UNWRAP_BIGINT_OR_RETURN(args, args[3], Uint64, cookie); CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, bufused_ptr); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "uvwasi_fd_readdir(%d, %d, %d, %d, %d)\n", fd, @@ -892,7 +902,7 @@ void WASI::FdRenumber(const FunctionCallbackInfo& args) { RETURN_IF_BAD_ARG_COUNT(args, 2); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, from); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, to); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_renumber(%d, %d)\n", from, to); uvwasi_errno_t err = uvwasi_fd_renumber(&wasi->uvw_, from, to); args.GetReturnValue().Set(err); @@ -912,7 +922,7 @@ void WASI::FdSeek(const FunctionCallbackInfo& args) { UNWRAP_BIGINT_OR_RETURN(args, args[1], Int64, offset); CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, whence); CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, newoffset_ptr); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_seek(%d, %d, %d, %d)\n", fd, offset, whence, newoffset_ptr); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); CHECK_BOUNDS_OR_RETURN(args, mem_size, newoffset_ptr, 8); @@ -934,7 +944,7 @@ void WASI::FdSync(const FunctionCallbackInfo& args) { uint32_t fd; RETURN_IF_BAD_ARG_COUNT(args, 1); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_sync(%d)\n", fd); uvwasi_errno_t err = uvwasi_fd_sync(&wasi->uvw_, fd); args.GetReturnValue().Set(err); @@ -950,7 +960,7 @@ void WASI::FdTell(const FunctionCallbackInfo& args) { RETURN_IF_BAD_ARG_COUNT(args, 2); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, offset_ptr); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_tell(%d, %d)\n", fd, offset_ptr); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); CHECK_BOUNDS_OR_RETURN(args, mem_size, offset_ptr, 8); @@ -977,7 +987,7 @@ void WASI::FdWrite(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, iovs_ptr); CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, iovs_len); CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, nwritten_ptr); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_write(%d, %d, %d, %d)\n", fd, @@ -1037,7 +1047,7 @@ void WASI::PathCreateDirectory(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, path_ptr); CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, path_len); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "path_create_directory(%d, %d, %d)\n", fd, path_ptr, path_len); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); CHECK_BOUNDS_OR_RETURN(args, mem_size, path_ptr, path_len); @@ -1064,7 +1074,7 @@ void WASI::PathFilestatGet(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, path_ptr); CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, path_len); CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, buf_ptr); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "path_filestat_get(%d, %d, %d)\n", fd, @@ -1114,7 +1124,7 @@ void WASI::PathFilestatSetTimes(const FunctionCallbackInfo& args) { UNWRAP_BIGINT_OR_RETURN(args, args[4], Uint64, st_atim); UNWRAP_BIGINT_OR_RETURN(args, args[5], Uint64, st_mtim); CHECK_TO_TYPE_OR_RETURN(args, args[6], Uint32, fst_flags); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "path_filestat_set_times(%d, %d, %d, %d, %d, %d, %d)\n", fd, @@ -1157,7 +1167,7 @@ void WASI::PathLink(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, new_fd); CHECK_TO_TYPE_OR_RETURN(args, args[5], Uint32, new_path_ptr); CHECK_TO_TYPE_OR_RETURN(args, args[6], Uint32, new_path_len); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "path_link(%d, %d, %d, %d, %d, %d, %d)\n", old_fd, @@ -1205,7 +1215,7 @@ void WASI::PathOpen(const FunctionCallbackInfo& args) { UNWRAP_BIGINT_OR_RETURN(args, args[6], Uint64, fs_rights_inheriting); CHECK_TO_TYPE_OR_RETURN(args, args[7], Uint32, fs_flags); CHECK_TO_TYPE_OR_RETURN(args, args[8], Uint32, fd_ptr); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "path_open(%d, %d, %d, %d, %d, %d, %d, %d, %d)\n", dirfd, @@ -1255,7 +1265,7 @@ void WASI::PathReadlink(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, buf_ptr); CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, buf_len); CHECK_TO_TYPE_OR_RETURN(args, args[5], Uint32, bufused_ptr); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "path_readlink(%d, %d, %d, %d, %d, %d)\n", fd, @@ -1294,7 +1304,7 @@ void WASI::PathRemoveDirectory(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, path_ptr); CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, path_len); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "path_remove_directory(%d, %d, %d)\n", fd, path_ptr, path_len); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); CHECK_BOUNDS_OR_RETURN(args, mem_size, path_ptr, path_len); @@ -1323,7 +1333,7 @@ void WASI::PathRename(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, new_fd); CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, new_path_ptr); CHECK_TO_TYPE_OR_RETURN(args, args[5], Uint32, new_path_len); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "path_rename(%d, %d, %d, %d, %d, %d)\n", old_fd, @@ -1361,7 +1371,7 @@ void WASI::PathSymlink(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, fd); CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, new_path_ptr); CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, new_path_len); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "path_symlink(%d, %d, %d, %d, %d)\n", old_path_ptr, @@ -1393,7 +1403,7 @@ void WASI::PathUnlinkFile(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, path_ptr); CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, path_len); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "path_unlink_file(%d, %d, %d)\n", fd, path_ptr, path_len); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); CHECK_BOUNDS_OR_RETURN(args, mem_size, path_ptr, path_len); @@ -1418,7 +1428,7 @@ void WASI::PollOneoff(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, out_ptr); CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, nsubscriptions); CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, nevents_ptr); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "poll_oneoff(%d, %d, %d, %d)\n", in_ptr, @@ -1446,21 +1456,21 @@ void WASI::PollOneoff(const FunctionCallbackInfo& args) { } for (uint32_t i = 0; i < nsubscriptions; ++i) { - uvwasi_subscription_t sub = in[i]; - wasi->readUInt64(memory, &sub.userdata, in_ptr); - wasi->readUInt8(memory, &sub.type, in_ptr + 8); - - if (sub.type == UVWASI_EVENTTYPE_CLOCK) { - wasi->readUInt32(memory, &sub.u.clock.clock_id, in_ptr + 16); - wasi->readUInt64(memory, &sub.u.clock.timeout, in_ptr + 24); - wasi->readUInt64(memory, &sub.u.clock.precision, in_ptr + 32); - wasi->readUInt16(memory, &sub.u.clock.flags, in_ptr + 40); - } else if (sub.type == UVWASI_EVENTTYPE_FD_READ || - sub.type == UVWASI_EVENTTYPE_FD_WRITE) { - wasi->readUInt32(memory, &sub.u.fd_readwrite.fd, in_ptr + 16); + uvwasi_subscription_t* sub = &in[i]; + wasi->readUInt64(memory, &sub->userdata, in_ptr); + wasi->readUInt8(memory, &sub->type, in_ptr + 8); + + if (sub->type == UVWASI_EVENTTYPE_CLOCK) { + wasi->readUInt32(memory, &sub->u.clock.clock_id, in_ptr + 16); + wasi->readUInt64(memory, &sub->u.clock.timeout, in_ptr + 24); + wasi->readUInt64(memory, &sub->u.clock.precision, in_ptr + 32); + wasi->readUInt16(memory, &sub->u.clock.flags, in_ptr + 40); + } else if (sub->type == UVWASI_EVENTTYPE_FD_READ || + sub->type == UVWASI_EVENTTYPE_FD_WRITE) { + wasi->readUInt32(memory, &sub->u.fd_readwrite.fd, in_ptr + 16); } - in_ptr += 56; + in_ptr += 48; } size_t nevents; @@ -1500,7 +1510,7 @@ void WASI::ProcExit(const FunctionCallbackInfo& args) { uint32_t code; RETURN_IF_BAD_ARG_COUNT(args, 1); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, code); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "proc_exit(%d)\n", code); args.GetReturnValue().Set(uvwasi_proc_exit(&wasi->uvw_, code)); } @@ -1511,7 +1521,7 @@ void WASI::ProcRaise(const FunctionCallbackInfo& args) { uint32_t sig; RETURN_IF_BAD_ARG_COUNT(args, 1); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, sig); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "proc_raise(%d)\n", sig); uvwasi_errno_t err = uvwasi_proc_raise(&wasi->uvw_, sig); args.GetReturnValue().Set(err); @@ -1527,7 +1537,7 @@ void WASI::RandomGet(const FunctionCallbackInfo& args) { RETURN_IF_BAD_ARG_COUNT(args, 2); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, buf_ptr); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, buf_len); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "random_get(%d, %d)\n", buf_ptr, buf_len); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); CHECK_BOUNDS_OR_RETURN(args, mem_size, buf_ptr, buf_len); @@ -1541,7 +1551,7 @@ void WASI::RandomGet(const FunctionCallbackInfo& args) { void WASI::SchedYield(const FunctionCallbackInfo& args) { WASI* wasi; RETURN_IF_BAD_ARG_COUNT(args, 0); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "sched_yield()\n"); uvwasi_errno_t err = uvwasi_sched_yield(&wasi->uvw_); args.GetReturnValue().Set(err); @@ -1565,7 +1575,7 @@ void WASI::SockRecv(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, ri_flags); CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, ro_datalen_ptr); CHECK_TO_TYPE_OR_RETURN(args, args[5], Uint32, ro_flags_ptr); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "sock_recv(%d, %d, %d, %d, %d, %d)\n", sock, @@ -1637,7 +1647,7 @@ void WASI::SockSend(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, si_data_len); CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, si_flags); CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, so_datalen_ptr); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "sock_send(%d, %d, %d, %d, %d)\n", sock, @@ -1695,7 +1705,7 @@ void WASI::SockShutdown(const FunctionCallbackInfo& args) { RETURN_IF_BAD_ARG_COUNT(args, 2); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, sock); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, how); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "sock_shutdown(%d, %d)\n", sock, how); uvwasi_errno_t err = uvwasi_sock_shutdown(&wasi->uvw_, sock, how); args.GetReturnValue().Set(err); diff --git a/src/node_worker.cc b/src/node_worker.cc index 1e1d9434cddb4c..8ba250577354d9 100644 --- a/src/node_worker.cc +++ b/src/node_worker.cc @@ -260,6 +260,11 @@ void Worker::Run() { DeleteFnPtr env_; auto cleanup_env = OnScopeLeave([&]() { + // TODO(addaleax): This call is harmless but should not be necessary. + // Figure out why V8 is raising a DCHECK() here without it + // (in test/parallel/test-async-hooks-worker-asyncfn-terminate-4.js). + isolate_->CancelTerminateExecution(); + if (!env_) return; env_->set_can_call_into_js(false); @@ -660,7 +665,7 @@ void Worker::StopThread(const FunctionCallbackInfo& args) { void Worker::Ref(const FunctionCallbackInfo& args) { Worker* w; ASSIGN_OR_RETURN_UNWRAP(&w, args.This()); - if (!w->has_ref_) { + if (!w->has_ref_ && !w->thread_joined_) { w->has_ref_ = true; w->env()->add_refs(1); } @@ -669,7 +674,7 @@ void Worker::Ref(const FunctionCallbackInfo& args) { void Worker::Unref(const FunctionCallbackInfo& args) { Worker* w; ASSIGN_OR_RETURN_UNWRAP(&w, args.This()); - if (w->has_ref_) { + if (w->has_ref_ && !w->thread_joined_) { w->has_ref_ = false; w->env()->add_refs(-1); } @@ -754,7 +759,7 @@ void Worker::TakeHeapSnapshot(const FunctionCallbackInfo& args) { env, std::move(snapshot)); Local args[] = { stream->object() }; taker->MakeCallback(env->ondone_string(), arraysize(args), args); - }); + }, /* refed */ false); }); args.GetReturnValue().Set(scheduled ? taker->object() : Local()); } diff --git a/src/node_zlib.cc b/src/node_zlib.cc index eacd710143a1b2..83698bd5192e4b 100644 --- a/src/node_zlib.cc +++ b/src/node_zlib.cc @@ -111,7 +111,12 @@ enum node_zlib_mode { struct CompressionError { CompressionError(const char* message, const char* code, int err) - : message(message), code(code), err(err) {} + : message(message), + code(code), + err(err) { + CHECK_NOT_NULL(message); + } + CompressionError() = default; const char* message = nullptr; @@ -997,7 +1002,7 @@ CompressionError ZlibContext::Init( if (err_ != Z_OK) { dictionary_.clear(); mode_ = NONE; - return ErrorForMessage(nullptr); + return ErrorForMessage("zlib error"); } return SetDictionary(); diff --git a/src/stream_base-inl.h b/src/stream_base-inl.h index 95152e34915853..149f542d841607 100644 --- a/src/stream_base-inl.h +++ b/src/stream_base-inl.h @@ -4,6 +4,7 @@ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #include "async_wrap-inl.h" +#include "base_object-inl.h" #include "node.h" #include "stream_base.h" #include "v8.h" @@ -31,9 +32,10 @@ StreamReq* StreamReq::FromObject(v8::Local req_wrap_obj) { } void StreamReq::Dispose() { - std::unique_ptr ptr(this); + BaseObjectPtr destroy_me{GetAsyncWrap()}; object()->SetAlignedPointerInInternalField( StreamReq::kStreamReqField, nullptr); + destroy_me->Detach(); } v8::Local StreamReq::object() { @@ -90,29 +92,29 @@ void StreamResource::RemoveStreamListener(StreamListener* listener) { } uv_buf_t StreamResource::EmitAlloc(size_t suggested_size) { - DebugSealHandleScope handle_scope(v8::Isolate::GetCurrent()); + DebugSealHandleScope seal_handle_scope; return listener_->OnStreamAlloc(suggested_size); } void StreamResource::EmitRead(ssize_t nread, const uv_buf_t& buf) { - DebugSealHandleScope handle_scope(v8::Isolate::GetCurrent()); + DebugSealHandleScope seal_handle_scope; if (nread > 0) bytes_read_ += static_cast(nread); listener_->OnStreamRead(nread, buf); } void StreamResource::EmitAfterWrite(WriteWrap* w, int status) { - DebugSealHandleScope handle_scope(v8::Isolate::GetCurrent()); + DebugSealHandleScope seal_handle_scope; listener_->OnStreamAfterWrite(w, status); } void StreamResource::EmitAfterShutdown(ShutdownWrap* w, int status) { - DebugSealHandleScope handle_scope(v8::Isolate::GetCurrent()); + DebugSealHandleScope seal_handle_scope; listener_->OnStreamAfterShutdown(w, status); } void StreamResource::EmitWantsWrite(size_t suggested_size) { - DebugSealHandleScope handle_scope(v8::Isolate::GetCurrent()); + DebugSealHandleScope seal_handle_scope; listener_->OnStreamWantsWrite(suggested_size); } diff --git a/src/stream_wrap.cc b/src/stream_wrap.cc index 90b2bb93416878..bd396110fccade 100644 --- a/src/stream_wrap.cc +++ b/src/stream_wrap.cc @@ -142,7 +142,7 @@ Local LibuvStreamWrap::GetConstructorTemplate( Local get_write_queue_size = FunctionTemplate::New(env->isolate(), GetWriteQueueSize, - env->current_callback_data(), + Local(), Signature::New(env->isolate(), tmpl)); tmpl->PrototypeTemplate()->SetAccessorProperty( env->write_queue_size_string(), diff --git a/src/tls_wrap.cc b/src/tls_wrap.cc index df6a989dfbe0b3..0c2c2bbc014cc3 100644 --- a/src/tls_wrap.cc +++ b/src/tls_wrap.cc @@ -1276,7 +1276,7 @@ void TLSWrap::Initialize(Local target, Local get_write_queue_size = FunctionTemplate::New(env->isolate(), GetWriteQueueSize, - env->current_callback_data(), + Local(), Signature::New(env->isolate(), t)); t->PrototypeTemplate()->SetAccessorProperty( env->write_queue_size_string(), diff --git a/src/udp_wrap.cc b/src/udp_wrap.cc index 1c42481f178a4b..9013bc9fe335c3 100644 --- a/src/udp_wrap.cc +++ b/src/udp_wrap.cc @@ -145,7 +145,7 @@ void UDPWrap::Initialize(Local target, Local get_fd_templ = FunctionTemplate::New(env->isolate(), UDPWrap::GetFD, - env->current_callback_data(), + Local(), signature); t->PrototypeTemplate()->SetAccessorProperty(env->fd_string(), diff --git a/src/util-inl.h b/src/util-inl.h index d44ee09fefbb3a..6b4bdfe034d64f 100644 --- a/src/util-inl.h +++ b/src/util-inl.h @@ -533,6 +533,37 @@ inline bool IsSafeJsInt(v8::Local v) { return false; } +constexpr size_t FastStringKey::HashImpl(const char* str) { + // Low-quality hash (djb2), but just fine for current use cases. + size_t h = 5381; + do { + h = h * 33 + *str; // NOLINT(readability/pointer_notation) + } while (*(str++) != '\0'); + return h; +} + +constexpr size_t FastStringKey::Hash::operator()( + const FastStringKey& key) const { + return key.cached_hash_; +} + +constexpr bool FastStringKey::operator==(const FastStringKey& other) const { + const char* p1 = name_; + const char* p2 = other.name_; + if (p1 == p2) return true; + do { + if (*(p1++) != *(p2++)) return false; + } while (*p1 != '\0'); + return true; +} + +constexpr FastStringKey::FastStringKey(const char* name) + : name_(name), cached_hash_(HashImpl(name)) {} + +constexpr const char* FastStringKey::c_str() const { + return name_; +} + } // namespace node #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS diff --git a/src/util.h b/src/util.h index 5eaa20b760168b..979091e6d6e002 100644 --- a/src/util.h +++ b/src/util.h @@ -764,6 +764,27 @@ class PersistentToLocal { } }; +// Can be used as a key for std::unordered_map when lookup performance is more +// important than size and the keys are statically used to avoid redundant hash +// computations. +class FastStringKey { + public: + constexpr explicit FastStringKey(const char* name); + + struct Hash { + constexpr size_t operator()(const FastStringKey& key) const; + }; + constexpr bool operator==(const FastStringKey& other) const; + + constexpr const char* c_str() const; + + private: + static constexpr size_t HashImpl(const char* str); + + const char* name_; + size_t cached_hash_; +}; + } // namespace node #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS diff --git a/test/.eslintrc.yaml b/test/.eslintrc.yaml index 86d4b595e7dc9a..f707caffdafde4 100644 --- a/test/.eslintrc.yaml +++ b/test/.eslintrc.yaml @@ -11,6 +11,42 @@ rules: prefer-const: error symbol-description: off + no-restricted-syntax: + # Config copied from .eslintrc.js + - error + - selector: "CallExpression:matches([callee.name='deepStrictEqual'], [callee.property.name='deepStrictEqual'])[arguments.2.type='Literal']" + message: "Do not use a literal for the third argument of assert.deepStrictEqual()" + - selector: "CallExpression:matches([callee.name='doesNotThrow'], [callee.property.name='doesNotThrow'])" + message: "Do not use `assert.doesNotThrow()`. Write the code without the wrapper and add a comment instead." + - selector: "CallExpression:matches([callee.name='doesNotReject'], [callee.property.name='doesNotReject'])" + message: "Do not use `assert.doesNotReject()`. Write the code without the wrapper and add a comment instead." + - selector: "CallExpression:matches([callee.name='rejects'], [callee.property.name='rejects'])[arguments.length<2]" + message: "`assert.rejects()` must be invoked with at least two arguments." + - selector: "CallExpression[callee.property.name='strictEqual'][arguments.2.type='Literal']" + message: "Do not use a literal for the third argument of assert.strictEqual()" + - selector: "CallExpression:matches([callee.name='throws'], [callee.property.name='throws'])[arguments.1.type='Literal']:not([arguments.1.regex])" + message: "Use an object as second argument of `assert.throws()`." + - selector: "CallExpression:matches([callee.name='throws'], [callee.property.name='throws'])[arguments.length<2]" + message: "`assert.throws()` must be invoked with at least two arguments." + - selector: "CallExpression[callee.name='setTimeout'][arguments.length<2]" + message: "`setTimeout()` must be invoked with at least two arguments." + - selector: "CallExpression[callee.name='setInterval'][arguments.length<2]" + message: "`setInterval()` must be invoked with at least two arguments." + - selector: "ThrowStatement > CallExpression[callee.name=/Error$/]" + message: "Use `new` keyword when throwing an `Error`." + - selector: "CallExpression:matches([callee.name='notDeepStrictEqual'], [callee.property.name='notDeepStrictEqual'])[arguments.0.type='Literal']:not([arguments.1.type='Literal']):not([arguments.1.type='ObjectExpression']):not([arguments.1.type='ArrayExpression']):not([arguments.1.type='UnaryExpression'])" + message: "The first argument should be the `actual`, not the `expected` value." + - selector: "CallExpression:matches([callee.name='notStrictEqual'], [callee.property.name='notStrictEqual'])[arguments.0.type='Literal']:not([arguments.1.type='Literal']):not([arguments.1.type='ObjectExpression']):not([arguments.1.type='ArrayExpression']):not([arguments.1.type='UnaryExpression'])" + message: "The first argument should be the `actual`, not the `expected` value." + - selector: "CallExpression:matches([callee.name='deepStrictEqual'], [callee.property.name='deepStrictEqual'])[arguments.0.type='Literal']:not([arguments.1.type='Literal']):not([arguments.1.type='ObjectExpression']):not([arguments.1.type='ArrayExpression']):not([arguments.1.type='UnaryExpression'])" + message: "The first argument should be the `actual`, not the `expected` value." + - selector: "CallExpression:matches([callee.name='strictEqual'], [callee.property.name='strictEqual'])[arguments.0.type='Literal']:not([arguments.1.type='Literal']):not([arguments.1.type='ObjectExpression']):not([arguments.1.type='ArrayExpression']):not([arguments.1.type='UnaryExpression'])" + message: "The first argument should be the `actual`, not the `expected` value." + - selector: "CallExpression[callee.name='isNaN']" + message: "Use Number.isNaN() instead of the global isNaN() function." + - selector: "VariableDeclarator > CallExpression:matches([callee.name='debuglog'], [callee.property.name='debuglog']):not([arguments.0.value='test'])" + message: "Use 'test' as debuglog value in tests." + # Custom rules in tools/eslint-rules node-core/prefer-assert-iferror: error node-core/prefer-assert-methods: error diff --git a/test/abort/common.gypi b/test/abort/common.gypi deleted file mode 100644 index 19396c61856af3..00000000000000 --- a/test/abort/common.gypi +++ /dev/null @@ -1,8 +0,0 @@ -{ - 'defines': [ 'V8_DEPRECATION_WARNINGS=1', 'NODE_WANT_INTERNALS=1' ], - 'conditions': [ - [ 'OS in "linux freebsd openbsd solaris android aix cloudabi"', { - 'cflags': ['-Wno-cast-function-type'], - }], - ], -} diff --git a/test/abort/test_abort-aliased-buffer-overflow/binding.cc b/test/abort/test_abort-aliased-buffer-overflow/binding.cc deleted file mode 100644 index c3bf66061bf0ee..00000000000000 --- a/test/abort/test_abort-aliased-buffer-overflow/binding.cc +++ /dev/null @@ -1,23 +0,0 @@ -#include -#include -#include - -#include -#include - -void AllocateAndResizeBuffer( - const v8::FunctionCallbackInfo& args) { - v8::Isolate* isolate = args.GetIsolate(); - int64_t length = args[0].As()->Int64Value(); - - node::AliasedBigUint64Array array{isolate, 0}; - - array.reserve(length); - assert(false); - } - -void init(v8::Local exports) { - NODE_SET_METHOD(exports, - "allocateAndResizeBuffer", - AllocateAndResizeBuffer); -} diff --git a/test/abort/test_abort-aliased-buffer-overflow/binding.gyp b/test/abort/test_abort-aliased-buffer-overflow/binding.gyp deleted file mode 100644 index 55fbe7050f18e4..00000000000000 --- a/test/abort/test_abort-aliased-buffer-overflow/binding.gyp +++ /dev/null @@ -1,9 +0,0 @@ -{ - 'targets': [ - { - 'target_name': 'binding', - 'sources': [ 'binding.cc' ], - 'includes': ['../common.gypi'], - } - ] -} diff --git a/test/abort/test_abort-aliased-buffer-overflow/test-abort-aliased-buffer-overflow.js b/test/abort/test_abort-aliased-buffer-overflow/test-abort-aliased-buffer-overflow.js deleted file mode 100644 index 33cd21295848b9..00000000000000 --- a/test/abort/test_abort-aliased-buffer-overflow/test-abort-aliased-buffer-overflow.js +++ /dev/null @@ -1,28 +0,0 @@ -'use strict'; -const common = require('../common'); -const assert = require('assert'); -const cp = require('child_process'); - -// This test ensures that during resizing of an Aliased*Array the computation -// of the new size does not overflow. - -if (process.argv[2] === 'child') { - // test - const binding = require(`./build/${common.buildType}/binding`); - - const bigValue = BigInt('0xE000 0000 E000 0000'); - binding.AllocateAndResizeBuffer(bigValue); - assert.fail('this should be unreachable'); -} else { - // observer - const child = cp.spawn(`${process.execPath}`, [`${__filename}`, 'child']); - child.on('exit', common.mustCall(function(code, signal) { - if (common.isWindows) { - assert.strictEqual(code, 134); - assert.strictEqual(signal, null); - } else { - assert.strictEqual(code, null); - assert.strictEqual(signal, 'SIGABRT'); - } - })); -} diff --git a/test/addons/async-hooks-promise/test.js b/test/addons/async-hooks-promise/test.js index a6c48e94a34f07..d38bf9bd978103 100644 --- a/test/addons/async-hooks-promise/test.js +++ b/test/addons/async-hooks-promise/test.js @@ -1,8 +1,11 @@ 'use strict'; +// Flags: --expose-internals const common = require('../../common'); const assert = require('assert'); const async_hooks = require('async_hooks'); +const { async_id_symbol, + trigger_async_id_symbol } = require('internal/async_hooks').symbols; const binding = require(`./build/${common.buildType}/binding`); if (process.env.NODE_TEST_WITH_ASYNC_HOOKS) { @@ -15,28 +18,60 @@ assert.strictEqual( binding.getPromiseField(Promise.resolve(1)), 0); -const hook0 = async_hooks.createHook({}).enable(); +const emptyHook = async_hooks.createHook({}).enable(); // Check that no PromiseWrap is created when there are no hook callbacks. assert.strictEqual( binding.getPromiseField(Promise.resolve(1)), 0); -hook0.disable(); +emptyHook.disable(); + +let lastResource; +let lastAsyncId; +let lastTriggerAsyncId; +const initOnlyHook = async_hooks.createHook({ + init(asyncId, type, triggerAsyncId, resource) { + lastAsyncId = asyncId; + lastTriggerAsyncId = triggerAsyncId; + lastResource = resource; + } +}).enable(); + +// Check that no PromiseWrap is created when only using an init hook. +{ + const promise = Promise.resolve(1); + assert.strictEqual(binding.getPromiseField(promise), 0); + assert.strictEqual(lastResource, promise); + assert.strictEqual(lastAsyncId, promise[async_id_symbol]); + assert.strictEqual(lastTriggerAsyncId, promise[trigger_async_id_symbol]); +} + +initOnlyHook.disable(); + +lastResource = null; +const hookWithDestroy = async_hooks.createHook({ + init(asyncId, type, triggerAsyncId, resource) { + lastAsyncId = asyncId; + lastTriggerAsyncId = triggerAsyncId; + lastResource = resource; + }, + + destroy() { -let pwrap = null; -const hook1 = async_hooks.createHook({ - init(id, type, tid, resource) { - pwrap = resource; } }).enable(); // Check that the internal field returns the same PromiseWrap passed to init(). -assert.strictEqual( - binding.getPromiseField(Promise.resolve(1)), - pwrap); +{ + const promise = Promise.resolve(1); + const promiseWrap = binding.getPromiseField(promise); + assert.strictEqual(lastResource, promiseWrap); + assert.strictEqual(lastAsyncId, promiseWrap[async_id_symbol]); + assert.strictEqual(lastTriggerAsyncId, promiseWrap[trigger_async_id_symbol]); +} -hook1.disable(); +hookWithDestroy.disable(); // Check that internal fields are no longer being set. This needs to be delayed // a bit because the `disable()` call only schedules disabling the hook in a @@ -45,4 +80,25 @@ setImmediate(() => { assert.strictEqual( binding.getPromiseField(Promise.resolve(1)), 0); + + const noDestroyHook = async_hooks.createHook({ + init(asyncId, type, triggerAsyncId, resource) { + lastAsyncId = asyncId; + lastTriggerAsyncId = triggerAsyncId; + lastResource = resource; + }, + + before() {}, + after() {}, + resolve() {} + }).enable(); + + // Check that no PromiseWrap is created when there is no destroy hook. + const promise = Promise.resolve(1); + assert.strictEqual(binding.getPromiseField(promise), 0); + assert.strictEqual(lastResource, promise); + assert.strictEqual(lastAsyncId, promise[async_id_symbol]); + assert.strictEqual(lastTriggerAsyncId, promise[trigger_async_id_symbol]); + + noDestroyHook.disable(); }); diff --git a/test/addons/null-buffer-neuter/binding.cc b/test/addons/null-buffer-neuter/binding.cc index 4c9dbf902589d9..7575e29fa85084 100644 --- a/test/addons/null-buffer-neuter/binding.cc +++ b/test/addons/null-buffer-neuter/binding.cc @@ -11,6 +11,10 @@ static void FreeCallback(char* data, void* hint) { alive--; } +void IsAlive(const v8::FunctionCallbackInfo& args) { + args.GetReturnValue().Set(alive); +} + void Run(const v8::FunctionCallbackInfo& args) { v8::Isolate* isolate = args.GetIsolate(); alive++; @@ -27,15 +31,11 @@ void Run(const v8::FunctionCallbackInfo& args) { char* data = node::Buffer::Data(buf); assert(data == nullptr); } - - isolate->RequestGarbageCollectionForTesting( - v8::Isolate::kFullGarbageCollection); - - assert(alive == 0); } void init(v8::Local exports) { NODE_SET_METHOD(exports, "run", Run); + NODE_SET_METHOD(exports, "isAlive", IsAlive); } NODE_MODULE(NODE_GYP_MODULE_NAME, init) diff --git a/test/addons/null-buffer-neuter/test.js b/test/addons/null-buffer-neuter/test.js index 3fc335914c9a44..d99690542a4d84 100644 --- a/test/addons/null-buffer-neuter/test.js +++ b/test/addons/null-buffer-neuter/test.js @@ -1,7 +1,11 @@ 'use strict'; // Flags: --expose-gc - const common = require('../../common'); +const assert = require('assert'); const binding = require(`./build/${common.buildType}/binding`); binding.run(); +global.gc(); +setImmediate(() => { + assert.strictEqual(binding.isAlive(), 0); +}); diff --git a/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-exceed-max-by-1-utf8.js b/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-exceed-max-by-1-utf8.js index 2ca7050d8ab4ea..78e73e0dc8557b 100644 --- a/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-exceed-max-by-1-utf8.js +++ b/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-exceed-max-by-1-utf8.js @@ -38,9 +38,8 @@ assert.throws(() => { name: 'Error' })(e); return true; - } else { - return true; } + return true; }); assert.throws(() => { diff --git a/test/async-hooks/init-hooks.js b/test/async-hooks/init-hooks.js index b10ec827198f6d..59ecc96b881a5a 100644 --- a/test/async-hooks/init-hooks.js +++ b/test/async-hooks/init-hooks.js @@ -165,14 +165,13 @@ class ActivityCollector { // Worker threads start main script execution inside of an AsyncWrap // callback, so we don't yield errors for these. return null; - } else { - const err = new Error(`Found a handle whose ${hook}` + - ' hook was invoked but not its init hook'); - // Don't throw if we see invocations due to an assertion in a test - // failing since we want to list the assertion failure instead - if (/process\._fatalException/.test(err.stack)) return null; - throw err; } + const err = new Error(`Found a handle whose ${hook}` + + ' hook was invoked but not its init hook'); + // Don't throw if we see invocations due to an assertion in a test + // failing since we want to list the assertion failure instead + if (/process\._fatalException/.test(err.stack)) return null; + throw err; } return h; } diff --git a/test/common/README.md b/test/common/README.md index 5479a39d8c215c..52b25fdcfe81a6 100644 --- a/test/common/README.md +++ b/test/common/README.md @@ -223,6 +223,10 @@ Platform check for Advanced Interactive eXecutive (AIX). Attempts to 'kill' `pid` +### `isDumbTerminal` + +* [<boolean>][] + ### `isFreeBSD` * [<boolean>][] @@ -385,6 +389,10 @@ will not be run. Logs '1..0 # Skipped: ' + `msg` and exits with exit code `0`. +### `skipIfDumbTerminal()` + +Skip the rest of the tests if the current terminal is a dumb terminal + ### `skipIfEslintMissing()` Skip the rest of the tests in the current file when `ESLint` is not available diff --git a/test/common/dns.js b/test/common/dns.js index 37f80dde02782c..d8a703cc53be86 100644 --- a/test/common/dns.js +++ b/test/common/dns.js @@ -36,16 +36,15 @@ function readDomainFromPacket(buffer, offset) { nread: 1 + length + nread, domain: domain ? `${chunk}.${domain}` : chunk }; - } else { - // Pointer to another part of the packet. - assert.strictEqual(length & 0xC0, 0xC0); - // eslint-disable-next-line space-infix-ops, space-unary-ops - const pointeeOffset = buffer.readUInt16BE(offset) &~ 0xC000; - return { - nread: 2, - domain: readDomainFromPacket(buffer, pointeeOffset) - }; } + // Pointer to another part of the packet. + assert.strictEqual(length & 0xC0, 0xC0); + // eslint-disable-next-line space-infix-ops, space-unary-ops + const pointeeOffset = buffer.readUInt16BE(offset) &~ 0xC000; + return { + nread: 2, + domain: readDomainFromPacket(buffer, pointeeOffset) + }; } function parseDNSPacket(buffer) { diff --git a/test/common/index.js b/test/common/index.js index e77e7b95059947..6343425858d8c7 100644 --- a/test/common/index.js +++ b/test/common/index.js @@ -112,6 +112,8 @@ const isOpenBSD = process.platform === 'openbsd'; const isLinux = process.platform === 'linux'; const isOSX = process.platform === 'darwin'; +const isDumbTerminal = process.env.TERM === 'dumb'; + const rootDir = isWindows ? 'c:\\' : '/'; const buildType = process.config.target_defaults ? @@ -307,10 +309,9 @@ function runCallChecks(exitCode) { if ('minimum' in context) { context.messageSegment = `at least ${context.minimum}`; return context.actual < context.minimum; - } else { - context.messageSegment = `exactly ${context.exact}`; - return context.actual !== context.exact; } + context.messageSegment = `exactly ${context.exact}`; + return context.actual !== context.exact; }); failed.forEach(function(context) { @@ -463,9 +464,8 @@ function nodeProcessAborted(exitCode, signal) { // the expected exit codes or signals. if (signal !== null) { return expectedSignals.includes(signal); - } else { - return expectedExitCodes.includes(exitCode); } + return expectedExitCodes.includes(exitCode); } function isAlive(pid) { @@ -653,6 +653,12 @@ function invalidArgTypeHelper(input) { return ` Received type ${typeof input} (${inspected})`; } +function skipIfDumbTerminal() { + if (isDumbTerminal) { + skip('skipping - dumb terminal'); + } +} + const common = { allowGlobals, buildType, @@ -672,6 +678,7 @@ const common = { invalidArgTypeHelper, isAIX, isAlive, + isDumbTerminal, isFreeBSD, isLinux, isMainThread, @@ -692,6 +699,7 @@ const common = { runWithInvalidFD, skip, skipIf32Bits, + skipIfDumbTerminal, skipIfEslintMissing, skipIfInspectorDisabled, skipIfWorker, diff --git a/test/common/index.mjs b/test/common/index.mjs index 96e6699e3c6f99..fe5ed9872948b7 100644 --- a/test/common/index.mjs +++ b/test/common/index.mjs @@ -12,6 +12,7 @@ const { isIBMi, isLinuxPPCBE, isSunOS, + isDumbTerminal, isFreeBSD, isOpenBSD, isLinux, @@ -31,6 +32,7 @@ const { mustCall, mustCallAtLeast, hasMultiLocalhost, + skipIfDumbTerminal, skipIfEslintMissing, canCreateSymLink, getCallSite, @@ -57,6 +59,7 @@ export { isIBMi, isLinuxPPCBE, isSunOS, + isDumbTerminal, isFreeBSD, isOpenBSD, isLinux, @@ -76,6 +79,7 @@ export { mustCall, mustCallAtLeast, hasMultiLocalhost, + skipIfDumbTerminal, skipIfEslintMissing, canCreateSymLink, getCallSite, diff --git a/test/common/inspector-helper.js b/test/common/inspector-helper.js index d430137746dd81..77d7928af135a6 100644 --- a/test/common/inspector-helper.js +++ b/test/common/inspector-helper.js @@ -217,9 +217,8 @@ class InspectorSession { return Promise .all(commands.map((command) => this._sendMessage(command))) .then(() => {}); - } else { - return this._sendMessage(commands); } + return this._sendMessage(commands); } waitForNotification(methodOrPredicate, description) { diff --git a/test/common/shared-lib-util.js b/test/common/shared-lib-util.js index e522a71b4748d8..9f891a6043ef3d 100644 --- a/test/common/shared-lib-util.js +++ b/test/common/shared-lib-util.js @@ -36,9 +36,8 @@ function getSharedLibPath() { return path.join(kExecPath, 'node.dll'); } else if (common.isOSX) { return path.join(kExecPath, `libnode.${kShlibSuffix}`); - } else { - return path.join(kExecPath, 'lib.target', `libnode.${kShlibSuffix}`); } + return path.join(kExecPath, 'lib.target', `libnode.${kShlibSuffix}`); } // Get the binary path of stack frames. diff --git a/test/common/wpt.js b/test/common/wpt.js index f6ac07bdfd296c..e79bd66b370735 100644 --- a/test/common/wpt.js +++ b/test/common/wpt.js @@ -42,6 +42,18 @@ class ResourceLoader { this.path = path; } + toRealFilePath(from, url) { + // We need to patch this to load the WebIDL parser + url = url.replace( + '/resources/WebIDLParser.js', + '/resources/webidl2/lib/webidl2.js' + ); + const base = path.dirname(from); + return url.startsWith('/') ? + fixtures.path('wpt', url) : + fixtures.path('wpt', base, url); + } + /** * Load a resource in test/fixtures/wpt specified with a URL * @param {string} from the path of the file loading this resource, @@ -51,15 +63,7 @@ class ResourceLoader { * pseudo-Response object. */ read(from, url, asFetch = true) { - // We need to patch this to load the WebIDL parser - url = url.replace( - '/resources/WebIDLParser.js', - '/resources/webidl2/lib/webidl2.js' - ); - const base = path.dirname(from); - const file = url.startsWith('/') ? - fixtures.path('wpt', url) : - fixtures.path('wpt', base, url); + const file = this.toRealFilePath(from, url); if (asFetch) { return fsPromises.readFile(file) .then((data) => { @@ -69,9 +73,8 @@ class ResourceLoader { text() { return data.toString(); } }; }); - } else { - return fs.readFileSync(file, 'utf8'); } + return fs.readFileSync(file, 'utf8'); } } @@ -135,7 +138,8 @@ class StatusRuleSet { } } -class WPTTest { +// A specification of WPT test +class WPTTestSpec { /** * @param {string} mod name of the WPT module, e.g. * 'html/webappapis/microtask-queuing' @@ -227,8 +231,8 @@ class StatusLoader { this.path = path; this.loaded = false; this.rules = new StatusRuleSet(); - /** @type {WPTTest[]} */ - this.tests = []; + /** @type {WPTTestSpec[]} */ + this.specs = []; } /** @@ -265,15 +269,19 @@ class StatusLoader { for (const file of list) { const relativePath = path.relative(subDir, file); const match = this.rules.match(relativePath); - this.tests.push(new WPTTest(this.path, relativePath, match)); + this.specs.push(new WPTTestSpec(this.path, relativePath, match)); } this.loaded = true; } } -const PASSED = 1; -const FAILED = 2; -const SKIPPED = 3; +const kPass = 'pass'; +const kFail = 'fail'; +const kSkip = 'skip'; +const kTimeout = 'timeout'; +const kIncomplete = 'incomplete'; +const kUncaught = 'uncaught'; +const NODE_UNCAUGHT = 100; class WPTRunner { constructor(path) { @@ -286,12 +294,13 @@ class WPTRunner { this.status = new StatusLoader(path); this.status.load(); - this.tests = new Map( - this.status.tests.map((item) => [item.filename, item]) + this.specMap = new Map( + this.status.specs.map((item) => [item.filename, item]) ); - this.results = new Map(); + this.results = {}; this.inProgress = new Set(); + this.unexpectedFailures = []; } /** @@ -328,39 +337,97 @@ class WPTRunner { // only `subset.any.js` will be run by the runner. if (process.argv[2]) { const filename = process.argv[2]; - if (!this.tests.has(filename)) { + if (!this.specMap.has(filename)) { throw new Error(`${filename} not found!`); } - queue.push(this.tests.get(filename)); + queue.push(this.specMap.get(filename)); } else { queue = this.buildQueue(); } - this.inProgress = new Set(queue.map((item) => item.filename)); - - for (const test of queue) { - const filename = test.filename; - const content = test.getContent(); - const meta = test.title = this.getMeta(content); - - const absolutePath = test.getAbsolutePath(); - const context = this.generateContext(test); - const relativePath = test.getRelativePath(); - const code = this.mergeScripts(relativePath, meta, content); - try { - vm.runInContext(code, context, { - filename: absolutePath - }); - } catch (err) { - this.fail(filename, { - name: '', - message: err.message, - stack: inspect(err) - }, 'UNCAUGHT'); - this.inProgress.delete(filename); + this.inProgress = new Set(queue.map((spec) => spec.filename)); + + for (const spec of queue) { + const testFileName = spec.filename; + const content = spec.getContent(); + const meta = spec.title = this.getMeta(content); + + const absolutePath = spec.getAbsolutePath(); + const context = this.generateContext(spec); + const relativePath = spec.getRelativePath(); + const scriptsToRun = []; + // Scripts specified with the `// META: script=` header + if (meta.script) { + for (const script of meta.script) { + scriptsToRun.push({ + filename: this.resource.toRealFilePath(relativePath, script), + code: this.resource.read(relativePath, script, false) + }); + } + } + // The actual test + scriptsToRun.push({ + code: content, + filename: absolutePath + }); + + for (const { code, filename } of scriptsToRun) { + try { + vm.runInContext(code, context, { filename }); + } catch (err) { + this.fail( + testFileName, + { + status: NODE_UNCAUGHT, + name: 'evaluation in WPTRunner.runJsTests()', + message: err.message, + stack: inspect(err) + }, + kUncaught + ); + this.inProgress.delete(filename); + break; + } } } - this.tryFinish(); + + process.on('exit', () => { + const total = this.specMap.size; + if (this.inProgress.size > 0) { + for (const filename of this.inProgress) { + this.fail(filename, { name: 'Unknown' }, kIncomplete); + } + } + inspect.defaultOptions.depth = Infinity; + console.log(this.results); + + const failures = []; + let expectedFailures = 0; + let skipped = 0; + for (const key of Object.keys(this.results)) { + const item = this.results[key]; + if (item.fail && item.fail.unexpected) { + failures.push(key); + } + if (item.fail && item.fail.expected) { + expectedFailures++; + } + if (item.skip) { + skipped++; + } + } + const ran = total - skipped; + const passed = ran - expectedFailures - failures.length; + console.log(`Ran ${ran}/${total} tests, ${skipped} skipped,`, + `${passed} passed, ${expectedFailures} expected failures,`, + `${failures.length} unexpected failures`); + if (failures.length > 0) { + const file = path.join('test', 'wpt', 'status', `${this.path}.json`); + throw new Error( + `Found ${failures.length} unexpected failures. ` + + `Consider updating ${file} for these files:\n${failures.join('\n')}`); + } + }); } mock(testfile) { @@ -410,115 +477,124 @@ class WPTRunner { sandbox.self = sandbox; // TODO(joyeecheung): we are not a window - work with the upstream to // add a new scope for us. - return context; } - resultCallback(filename, test) { - switch (test.status) { + getTestTitle(filename) { + const spec = this.specMap.get(filename); + const title = spec.meta && spec.meta.title; + return title ? `${filename} : ${title}` : filename; + } + + // Map WPT test status to strings + getTestStatus(status) { + switch (status) { case 1: - this.fail(filename, test, 'FAILURE'); - break; + return kFail; case 2: - this.fail(filename, test, 'TIMEOUT'); - break; + return kTimeout; case 3: - this.fail(filename, test, 'INCOMPLETE'); - break; + return kIncomplete; + case NODE_UNCAUGHT: + return kUncaught; default: - this.succeed(filename, test); + return kPass; } } + /** + * Report the status of each specific test case (there could be multiple + * in one test file). + * + * @param {string} filename + * @param {Test} test The Test object returned by WPT harness + */ + resultCallback(filename, test) { + const status = this.getTestStatus(test.status); + const title = this.getTestTitle(filename); + console.log(`---- ${title} ----`); + if (status !== kPass) { + this.fail(filename, test, status); + } else { + this.succeed(filename, test, status); + } + } + + /** + * Report the status of each WPT test (one per file) + * + * @param {string} filename + * @param {Test[]} test The Test objects returned by WPT harness + */ completionCallback(filename, tests, harnessStatus) { + // Treat it like a test case failure if (harnessStatus.status === 2) { - assert.fail(`test harness timed out in ${filename}`); + const title = this.getTestTitle(filename); + console.log(`---- ${title} ----`); + this.resultCallback(filename, { status: 2, name: 'Unknown' }); } this.inProgress.delete(filename); - this.tryFinish(); } - tryFinish() { - if (this.inProgress.size > 0) { - return; + addTestResult(filename, item) { + let result = this.results[filename]; + if (!result) { + result = this.results[filename] = {}; } - - this.reportResults(); - } - - reportResults() { - const unexpectedFailures = []; - for (const [filename, items] of this.results) { - const test = this.tests.get(filename); - let title = test.meta && test.meta.title; - title = title ? `${filename} : ${title}` : filename; - console.log(`---- ${title} ----`); - for (const item of items) { - switch (item.type) { - case FAILED: { - if (test.failReasons.length) { - console.log(`[EXPECTED_FAILURE] ${item.test.name}`); - console.log(test.failReasons.join('; ')); - } else { - console.log(`[UNEXPECTED_FAILURE] ${item.test.name}`); - unexpectedFailures.push([title, filename, item]); - } - break; - } - case PASSED: { - console.log(`[PASSED] ${item.test.name}`); - break; - } - case SKIPPED: { - console.log(`[SKIPPED] ${item.reason}`); - break; - } - } + if (item.status === kSkip) { + // { filename: { skip: 'reason' } } + result[kSkip] = item.reason; + } else { + // { filename: { fail: { expected: [ ... ], + // unexpected: [ ... ] } }} + if (!result[item.status]) { + result[item.status] = {}; } - } - - if (unexpectedFailures.length > 0) { - for (const [title, filename, item] of unexpectedFailures) { - console.log(`---- ${title} ----`); - console.log(`[${item.reason}] ${item.test.name}`); - console.log(item.test.message); - console.log(item.test.stack); - const command = `${process.execPath} ${process.execArgv}` + - ` ${require.main.filename} ${filename}`; - console.log(`Command: ${command}\n`); + const key = item.expected ? 'expected' : 'unexpected'; + if (!result[item.status][key]) { + result[item.status][key] = []; + } + if (result[item.status][key].indexOf(item.reason) === -1) { + result[item.status][key].push(item.reason); } - assert.fail(`${unexpectedFailures.length} unexpected failures found`); - } - } - - addResult(filename, item) { - const result = this.results.get(filename); - if (result) { - result.push(item); - } else { - this.results.set(filename, [item]); } } - succeed(filename, test) { - this.addResult(filename, { - type: PASSED, - test - }); + succeed(filename, test, status) { + console.log(`[${status.toUpperCase()}] ${test.name}`); } - fail(filename, test, reason) { - this.addResult(filename, { - type: FAILED, - test, - reason + fail(filename, test, status) { + const spec = this.specMap.get(filename); + const expected = !!(spec.failReasons.length); + if (expected) { + console.log(`[EXPECTED_FAILURE][${status.toUpperCase()}] ${test.name}`); + console.log(spec.failReasons.join('; ')); + } else { + console.log(`[UNEXPECTED_FAILURE][${status.toUpperCase()}] ${test.name}`); + } + if (status === kFail || status === kUncaught) { + console.log(test.message); + console.log(test.stack); + } + const command = `${process.execPath} ${process.execArgv}` + + ` ${require.main.filename} ${filename}`; + console.log(`Command: ${command}\n`); + this.addTestResult(filename, { + expected, + status: kFail, + reason: test.message || status }); } skip(filename, reasons) { - this.addResult(filename, { - type: SKIPPED, - reason: reasons.join('; ') + const title = this.getTestTitle(filename); + console.log(`---- ${title} ----`); + const joinedReasons = reasons.join('; '); + console.log(`[SKIPPED] ${joinedReasons}`); + this.addTestResult(filename, { + status: kSkip, + reason: joinedReasons }); } @@ -526,56 +602,41 @@ class WPTRunner { const matches = code.match(/\/\/ META: .+/g); if (!matches) { return {}; - } else { - const result = {}; - for (const match of matches) { - const parts = match.match(/\/\/ META: ([^=]+?)=(.+)/); - const key = parts[1]; - const value = parts[2]; - if (key === 'script') { - if (result[key]) { - result[key].push(value); - } else { - result[key] = [value]; - } + } + const result = {}; + for (const match of matches) { + const parts = match.match(/\/\/ META: ([^=]+?)=(.+)/); + const key = parts[1]; + const value = parts[2]; + if (key === 'script') { + if (result[key]) { + result[key].push(value); } else { - result[key] = value; + result[key] = [value]; } + } else { + result[key] = value; } - return result; - } - } - - mergeScripts(base, meta, content) { - if (!meta.script) { - return content; } - - // only one script - let result = ''; - for (const script of meta.script) { - result += this.resource.read(base, script, false); - } - - return result + content; + return result; } buildQueue() { const queue = []; - for (const test of this.tests.values()) { - const filename = test.filename; - if (test.skipReasons.length > 0) { - this.skip(filename, test.skipReasons); + for (const spec of this.specMap.values()) { + const filename = spec.filename; + if (spec.skipReasons.length > 0) { + this.skip(filename, spec.skipReasons); continue; } - const lackingIntl = intlRequirements.isLacking(test.requires); + const lackingIntl = intlRequirements.isLacking(spec.requires); if (lackingIntl) { this.skip(filename, [ `requires ${lackingIntl}` ]); continue; } - queue.push(test); + queue.push(spec); } return queue; } diff --git a/test/es-module/test-esm-cjs-named-error.mjs b/test/es-module/test-esm-cjs-named-error.mjs new file mode 100644 index 00000000000000..d34f762dfb4e26 --- /dev/null +++ b/test/es-module/test-esm-cjs-named-error.mjs @@ -0,0 +1,64 @@ +import '../common/index.mjs'; +import { rejects } from 'assert'; + +const fixtureBase = '../fixtures/es-modules/package-cjs-named-error'; + +const expectedRelative = 'The requested module \'./fail.cjs\' is expected to ' + + 'be of type CommonJS, which does not support named exports. CommonJS ' + + 'modules can be imported by importing the default export.\n' + + 'For example:\n' + + 'import pkg from \'./fail.cjs\';\n' + + 'const { comeOn } = pkg;'; + +const expectedPackageHack = 'The requested module \'./json-hack/fail.js\' is ' + + 'expected to be of type CommonJS, which does not support named exports. ' + + 'CommonJS modules can be imported by importing the default export.\n' + + 'For example:\n' + + 'import pkg from \'./json-hack/fail.js\';\n' + + 'const { comeOn } = pkg;'; + +const expectedBare = 'The requested module \'deep-fail\' is expected to ' + + 'be of type CommonJS, which does not support named exports. CommonJS ' + + 'modules can be imported by importing the default export.\n' + + 'For example:\n' + + 'import pkg from \'deep-fail\';\n' + + 'const { comeOn } = pkg;'; + +rejects(async () => { + await import(`${fixtureBase}/single-quote.mjs`); +}, { + name: 'SyntaxError', + message: expectedRelative +}, 'should support relative specifiers with single quotes'); + +rejects(async () => { + await import(`${fixtureBase}/double-quote.mjs`); +}, { + name: 'SyntaxError', + message: expectedRelative +}, 'should support relative specifiers with double quotes'); + +rejects(async () => { + await import(`${fixtureBase}/json-hack.mjs`); +}, { + name: 'SyntaxError', + message: expectedPackageHack +}, 'should respect recursive package.json for module type'); + +rejects(async () => { + await import(`${fixtureBase}/bare-import-single.mjs`); +}, { + name: 'SyntaxError', + message: expectedBare +}, 'should support bare specifiers with single quotes'); + +rejects(async () => { + await import(`${fixtureBase}/bare-import-double.mjs`); +}, { + name: 'SyntaxError', + message: expectedBare +}, 'should support bare specifiers with double quotes'); + +rejects(async () => { + await import(`${fixtureBase}/escaped-single-quote.mjs`); +}, /import pkg from '\.\/oh'no\.cjs'/, 'should support relative specifiers with escaped single quote'); diff --git a/test/es-module/test-esm-exports.mjs b/test/es-module/test-esm-exports.mjs index 74bf66be32c39a..f9dc6ec472f424 100644 --- a/test/es-module/test-esm-exports.mjs +++ b/test/es-module/test-esm-exports.mjs @@ -141,9 +141,13 @@ import fromInside from '../fixtures/node_modules/pkgexports/lib/hole.js'; ]); if (!isRequire) { + const onDirectoryImport = (err) => { + strictEqual(err.code, 'ERR_UNSUPPORTED_DIR_IMPORT'); + assertStartsWith(err.message, 'Directory import'); + }; notFoundExports.set('pkgexports/subpath/file', 'pkgexports/subpath/file'); - notFoundExports.set('pkgexports/subpath/dir1', 'pkgexports/subpath/dir1'); - notFoundExports.set('pkgexports/subpath/dir2', 'pkgexports/subpath/dir2'); + loadFixture('pkgexports/subpath/dir1').catch(mustCall(onDirectoryImport)); + loadFixture('pkgexports/subpath/dir2').catch(mustCall(onDirectoryImport)); } for (const [specifier, request] of notFoundExports) { diff --git a/test/es-module/test-esm-main-lookup.mjs b/test/es-module/test-esm-main-lookup.mjs index 2023a105e4dc42..4694d1c8e626e0 100644 --- a/test/es-module/test-esm-main-lookup.mjs +++ b/test/es-module/test-esm-main-lookup.mjs @@ -6,7 +6,7 @@ async function main() { try { mod = await import('../fixtures/es-modules/pjson-main'); } catch (e) { - assert.strictEqual(e.code, 'ERR_MODULE_NOT_FOUND'); + assert.strictEqual(e.code, 'ERR_UNSUPPORTED_DIR_IMPORT'); } assert.strictEqual(mod, undefined); diff --git a/test/es-module/test-esm-tla.mjs b/test/es-module/test-esm-tla.mjs new file mode 100644 index 00000000000000..816f88dd80a74e --- /dev/null +++ b/test/es-module/test-esm-tla.mjs @@ -0,0 +1,11 @@ +// Flags: --experimental-top-level-await + +import '../common/index.mjs'; +import fixtures from '../common/fixtures.js'; +import assert from 'assert'; +import { pathToFileURL } from 'url'; + +import(pathToFileURL(fixtures.path('/es-modules/tla/parent.mjs'))) + .then(({ default: order }) => { + assert.deepStrictEqual(order, ['order', 'b', 'c', 'd', 'a', 'parent']); + }); diff --git a/test/fixtures/cycles/warning-skip-proxy-traps-a.js b/test/fixtures/cycles/warning-skip-proxy-traps-a.js new file mode 100644 index 00000000000000..b64f8e633ebfff --- /dev/null +++ b/test/fixtures/cycles/warning-skip-proxy-traps-a.js @@ -0,0 +1,17 @@ +module.exports = new Proxy({}, { + get(_target, prop) { throw new Error(`get: ${String(prop)}`); }, + getPrototypeOf() { throw new Error('getPrototypeOf'); }, + setPrototypeOf() { throw new Error('setPrototypeOf'); }, + isExtensible() { throw new Error('isExtensible'); }, + preventExtensions() { throw new Error('preventExtensions'); }, + getOwnPropertyDescriptor() { throw new Error('getOwnPropertyDescriptor'); }, + defineProperty() { throw new Error('defineProperty'); }, + has() { throw new Error('has'); }, + set() { throw new Error('set'); }, + deleteProperty() { throw new Error('deleteProperty'); }, + ownKeys() { throw new Error('ownKeys'); }, + apply() { throw new Error('apply'); }, + construct() { throw new Error('construct'); } +}); + +require('./warning-skip-proxy-traps-b.js'); diff --git a/test/fixtures/cycles/warning-skip-proxy-traps-b.js b/test/fixtures/cycles/warning-skip-proxy-traps-b.js new file mode 100644 index 00000000000000..e686bd719c136f --- /dev/null +++ b/test/fixtures/cycles/warning-skip-proxy-traps-b.js @@ -0,0 +1,10 @@ +const assert = require('assert'); + +const object = require('./warning-skip-proxy-traps-a.js'); + +assert.throws(() => { + object.missingPropProxyTrap; +}, { + message: 'get: missingPropProxyTrap', + name: 'Error', +}); diff --git a/test/fixtures/es-modules/package-cjs-named-error/bare-import-double.mjs b/test/fixtures/es-modules/package-cjs-named-error/bare-import-double.mjs new file mode 100644 index 00000000000000..45b8e83a84b795 --- /dev/null +++ b/test/fixtures/es-modules/package-cjs-named-error/bare-import-double.mjs @@ -0,0 +1 @@ +import { comeOn } from "deep-fail"; diff --git a/test/fixtures/es-modules/package-cjs-named-error/bare-import-single.mjs b/test/fixtures/es-modules/package-cjs-named-error/bare-import-single.mjs new file mode 100644 index 00000000000000..24c6b528b723a7 --- /dev/null +++ b/test/fixtures/es-modules/package-cjs-named-error/bare-import-single.mjs @@ -0,0 +1 @@ +import { comeOn } from 'deep-fail'; diff --git a/test/fixtures/es-modules/package-cjs-named-error/double-quote.mjs b/test/fixtures/es-modules/package-cjs-named-error/double-quote.mjs new file mode 100644 index 00000000000000..3015ef5bfa88db --- /dev/null +++ b/test/fixtures/es-modules/package-cjs-named-error/double-quote.mjs @@ -0,0 +1 @@ +import { comeOn } from "./fail.cjs"; diff --git a/test/fixtures/es-modules/package-cjs-named-error/escaped-single-quote.mjs b/test/fixtures/es-modules/package-cjs-named-error/escaped-single-quote.mjs new file mode 100644 index 00000000000000..07165c8b54d137 --- /dev/null +++ b/test/fixtures/es-modules/package-cjs-named-error/escaped-single-quote.mjs @@ -0,0 +1 @@ +import { value } from "./oh'no.cjs"; diff --git a/test/fixtures/es-modules/package-cjs-named-error/fail.cjs b/test/fixtures/es-modules/package-cjs-named-error/fail.cjs new file mode 100644 index 00000000000000..40c512ab0e5ad2 --- /dev/null +++ b/test/fixtures/es-modules/package-cjs-named-error/fail.cjs @@ -0,0 +1,3 @@ +module.exports = { + comeOn: 'fhqwhgads' +}; diff --git a/test/fixtures/es-modules/package-cjs-named-error/json-hack.mjs b/test/fixtures/es-modules/package-cjs-named-error/json-hack.mjs new file mode 100644 index 00000000000000..8bcb98462aef78 --- /dev/null +++ b/test/fixtures/es-modules/package-cjs-named-error/json-hack.mjs @@ -0,0 +1 @@ +import { comeOn } from './json-hack/fail.js'; diff --git a/test/fixtures/es-modules/package-cjs-named-error/json-hack/fail.js b/test/fixtures/es-modules/package-cjs-named-error/json-hack/fail.js new file mode 100644 index 00000000000000..40c512ab0e5ad2 --- /dev/null +++ b/test/fixtures/es-modules/package-cjs-named-error/json-hack/fail.js @@ -0,0 +1,3 @@ +module.exports = { + comeOn: 'fhqwhgads' +}; diff --git a/test/fixtures/es-modules/package-cjs-named-error/json-hack/package.json b/test/fixtures/es-modules/package-cjs-named-error/json-hack/package.json new file mode 100644 index 00000000000000..5bbefffbabee39 --- /dev/null +++ b/test/fixtures/es-modules/package-cjs-named-error/json-hack/package.json @@ -0,0 +1,3 @@ +{ + "type": "commonjs" +} diff --git a/test/fixtures/es-modules/package-cjs-named-error/node_modules/deep-fail/index.js b/test/fixtures/es-modules/package-cjs-named-error/node_modules/deep-fail/index.js new file mode 100644 index 00000000000000..40c512ab0e5ad2 --- /dev/null +++ b/test/fixtures/es-modules/package-cjs-named-error/node_modules/deep-fail/index.js @@ -0,0 +1,3 @@ +module.exports = { + comeOn: 'fhqwhgads' +}; diff --git a/test/fixtures/es-modules/package-cjs-named-error/node_modules/deep-fail/package.json b/test/fixtures/es-modules/package-cjs-named-error/node_modules/deep-fail/package.json new file mode 100644 index 00000000000000..a52e9923b0c910 --- /dev/null +++ b/test/fixtures/es-modules/package-cjs-named-error/node_modules/deep-fail/package.json @@ -0,0 +1,4 @@ +{ + "name": "deep-fail", + "main": "index.mjs" +} diff --git a/test/fixtures/es-modules/package-cjs-named-error/oh'no.cjs b/test/fixtures/es-modules/package-cjs-named-error/oh'no.cjs new file mode 100644 index 00000000000000..a508e568a888fd --- /dev/null +++ b/test/fixtures/es-modules/package-cjs-named-error/oh'no.cjs @@ -0,0 +1,3 @@ +module.exports = { + value: 123 +}; diff --git a/test/fixtures/es-modules/package-cjs-named-error/package.json b/test/fixtures/es-modules/package-cjs-named-error/package.json new file mode 100644 index 00000000000000..e0ec22311d216a --- /dev/null +++ b/test/fixtures/es-modules/package-cjs-named-error/package.json @@ -0,0 +1,5 @@ +{ + "name": "package-cjs-named-error", + "main": "index.mjs", + "type": "module" +} diff --git a/test/fixtures/es-modules/package-cjs-named-error/single-quote.mjs b/test/fixtures/es-modules/package-cjs-named-error/single-quote.mjs new file mode 100644 index 00000000000000..c6e923162c2e8c --- /dev/null +++ b/test/fixtures/es-modules/package-cjs-named-error/single-quote.mjs @@ -0,0 +1 @@ +import { comeOn } from './fail.cjs'; diff --git a/test/fixtures/es-modules/tla/a.mjs b/test/fixtures/es-modules/tla/a.mjs new file mode 100644 index 00000000000000..c899a1c658c385 --- /dev/null +++ b/test/fixtures/es-modules/tla/a.mjs @@ -0,0 +1,7 @@ +import order from './order.mjs'; + +await new Promise((resolve) => { + setTimeout(resolve, 200); +}); + +order.push('a'); diff --git a/test/fixtures/es-modules/tla/b.mjs b/test/fixtures/es-modules/tla/b.mjs new file mode 100644 index 00000000000000..5149f5fda9361e --- /dev/null +++ b/test/fixtures/es-modules/tla/b.mjs @@ -0,0 +1,3 @@ +import order from './order.mjs'; + +order.push('b'); diff --git a/test/fixtures/es-modules/tla/c.mjs b/test/fixtures/es-modules/tla/c.mjs new file mode 100644 index 00000000000000..ab0479f12b8eac --- /dev/null +++ b/test/fixtures/es-modules/tla/c.mjs @@ -0,0 +1,3 @@ +import order from './order.mjs'; + +order.push('c'); diff --git a/test/fixtures/es-modules/tla/d.mjs b/test/fixtures/es-modules/tla/d.mjs new file mode 100644 index 00000000000000..4d6e7d496fc88a --- /dev/null +++ b/test/fixtures/es-modules/tla/d.mjs @@ -0,0 +1,6 @@ +import order from './order.mjs'; + +const end = Date.now() + 500; +while (end < Date.now()) {} + +order.push('d'); diff --git a/test/fixtures/es-modules/tla/order.mjs b/test/fixtures/es-modules/tla/order.mjs new file mode 100644 index 00000000000000..3258bf986eae36 --- /dev/null +++ b/test/fixtures/es-modules/tla/order.mjs @@ -0,0 +1 @@ +export default ['order']; diff --git a/test/fixtures/es-modules/tla/parent.mjs b/test/fixtures/es-modules/tla/parent.mjs new file mode 100644 index 00000000000000..ed17e102267696 --- /dev/null +++ b/test/fixtures/es-modules/tla/parent.mjs @@ -0,0 +1,9 @@ +import order from './order.mjs'; +import './a.mjs'; +import './b.mjs'; +import './c.mjs'; +import './d.mjs'; + +order.push('parent'); + +export default order; diff --git a/test/fixtures/node_modules/no_index/lib/index.js b/test/fixtures/node_modules/no_index/lib/index.js new file mode 100644 index 00000000000000..4ba52ba2c8df67 --- /dev/null +++ b/test/fixtures/node_modules/no_index/lib/index.js @@ -0,0 +1 @@ +module.exports = {} diff --git a/test/fixtures/node_modules/no_index/package.json b/test/fixtures/node_modules/no_index/package.json new file mode 100644 index 00000000000000..0c6100eadad184 --- /dev/null +++ b/test/fixtures/node_modules/no_index/package.json @@ -0,0 +1,3 @@ +{ + "main": "./lib/index.js" +} diff --git a/test/fixtures/wpt/README.md b/test/fixtures/wpt/README.md index dcf42abe7925f7..041e8fe1f2eec3 100644 --- a/test/fixtures/wpt/README.md +++ b/test/fixtures/wpt/README.md @@ -14,9 +14,10 @@ Last update: - encoding: https://github.com/web-platform-tests/wpt/tree/5059d2c777/encoding - url: https://github.com/web-platform-tests/wpt/tree/418f7fabeb/url - resources: https://github.com/web-platform-tests/wpt/tree/e1fddfbf80/resources -- interfaces: https://github.com/web-platform-tests/wpt/tree/712c9f275e/interfaces +- interfaces: https://github.com/web-platform-tests/wpt/tree/8ada332aea/interfaces - html/webappapis/microtask-queuing: https://github.com/web-platform-tests/wpt/tree/0c3bed38df/html/webappapis/microtask-queuing - html/webappapis/timers: https://github.com/web-platform-tests/wpt/tree/ddfe9c089b/html/webappapis/timers +- hr-time: https://github.com/web-platform-tests/wpt/tree/a5d1774ecf/hr-time [Web Platform Tests]: https://github.com/web-platform-tests/wpt [`git node wpt`]: https://github.com/nodejs/node-core-utils/blob/master/docs/git-node.md#git-node-wpt diff --git a/test/fixtures/wpt/hr-time/META.yml b/test/fixtures/wpt/hr-time/META.yml new file mode 100644 index 00000000000000..779d5b4af08428 --- /dev/null +++ b/test/fixtures/wpt/hr-time/META.yml @@ -0,0 +1,4 @@ +spec: https://w3c.github.io/hr-time/ +suggested_reviewers: + - plehegar + - igrigorik diff --git a/test/fixtures/wpt/hr-time/basic.any.js b/test/fixtures/wpt/hr-time/basic.any.js new file mode 100644 index 00000000000000..364dd81a344818 --- /dev/null +++ b/test/fixtures/wpt/hr-time/basic.any.js @@ -0,0 +1,28 @@ +test(function() { + assert_true((self.performance !== undefined), "self.performance exists"); + assert_equals(typeof self.performance, "object", "self.performance is an object"); + assert_equals((typeof self.performance.now), "function", "self.performance.now() is a function"); + assert_equals(typeof self.performance.now(), "number", "self.performance.now() returns a number"); +}, "self.performance.now() is a function that returns a number"); + +test(function() { + assert_true(self.performance.now() > 0); +}, "self.performance.now() returns a positive number"); + +test(function() { + var now1 = self.performance.now(); + var now2 = self.performance.now(); + assert_true((now2-now1) >= 0); + }, "self.performance.now() difference is not negative"); + +async_test(function() { + // Check whether the performance.now() method is close to Date() within 30ms (due to inaccuracies) + var initial_hrt = self.performance.now(); + var initial_date = Date.now(); + this.step_timeout(function() { + var final_hrt = self.performance.now(); + var final_date = Date.now(); + assert_approx_equals(final_hrt - initial_hrt, final_date - initial_date, 30, 'High resolution time value increased by approximately the same amount as time from date object'); + this.done(); + }, 2000); +}, 'High resolution time has approximately the right relative magnitude'); diff --git a/test/fixtures/wpt/hr-time/idlharness.any.js b/test/fixtures/wpt/hr-time/idlharness.any.js new file mode 100644 index 00000000000000..6676b001a8b816 --- /dev/null +++ b/test/fixtures/wpt/hr-time/idlharness.any.js @@ -0,0 +1,23 @@ +// META: global=window,worker +// META: script=/resources/WebIDLParser.js +// META: script=/resources/idlharness.js +// META: timeout=long + +'use strict'; + +// https://w3c.github.io/hr-time/ + +idl_test( + ['hr-time'], + ['html', 'dom'], + async idl_array => { + if (self.GLOBAL.isWorker()) { + idl_array.add_objects({ WorkerGlobalScope: ['self'] }); + } else { + idl_array.add_objects({ Window: ['self'] }); + } + idl_array.add_objects({ + Performance: ['performance'], + }); + } +); diff --git a/test/fixtures/wpt/hr-time/monotonic-clock.any.js b/test/fixtures/wpt/hr-time/monotonic-clock.any.js new file mode 100644 index 00000000000000..c53b04d844e4f5 --- /dev/null +++ b/test/fixtures/wpt/hr-time/monotonic-clock.any.js @@ -0,0 +1,13 @@ +// The time values returned when calling the now method MUST be monotonically increasing and not subject to system clock adjustments or system clock skew. +test(function() { + assert_true(self.performance.now() > 0, "self.performance.now() returns positive numbers"); +}, "self.performance.now() returns a positive number"); + +// The difference between any two chronologically recorded time values returned from the now method MUST never be negative. +test(function() { + var now1 = self.performance.now(); + var now2 = self.performance.now(); + assert_true((now2-now1) >= 0, "self.performance.now() difference is not negative"); + }, + "self.performance.now() difference is not negative" +); diff --git a/test/fixtures/wpt/hr-time/performance-tojson.html b/test/fixtures/wpt/hr-time/performance-tojson.html new file mode 100644 index 00000000000000..fd8049cb9a1eee --- /dev/null +++ b/test/fixtures/wpt/hr-time/performance-tojson.html @@ -0,0 +1,76 @@ + + + + + + + + + + \ No newline at end of file diff --git a/test/fixtures/wpt/hr-time/resources/now_frame.html b/test/fixtures/wpt/hr-time/resources/now_frame.html new file mode 100644 index 00000000000000..5bec688af9cd3c --- /dev/null +++ b/test/fixtures/wpt/hr-time/resources/now_frame.html @@ -0,0 +1,9 @@ + + + + + window.performance.now frame + + + + diff --git a/test/fixtures/wpt/hr-time/resources/unload-a.html b/test/fixtures/wpt/hr-time/resources/unload-a.html new file mode 100644 index 00000000000000..40c1d061830e6f --- /dev/null +++ b/test/fixtures/wpt/hr-time/resources/unload-a.html @@ -0,0 +1,13 @@ + + + + Helper page for ../unload-manual.html + + + + + + + diff --git a/test/fixtures/wpt/hr-time/resources/unload-b.html b/test/fixtures/wpt/hr-time/resources/unload-b.html new file mode 100644 index 00000000000000..7c2d90df275fbc --- /dev/null +++ b/test/fixtures/wpt/hr-time/resources/unload-b.html @@ -0,0 +1,13 @@ + + + + Helper page for ../unload-manual.html + + + + + + + diff --git a/test/fixtures/wpt/hr-time/resources/unload-c.html b/test/fixtures/wpt/hr-time/resources/unload-c.html new file mode 100644 index 00000000000000..731da9db758ba5 --- /dev/null +++ b/test/fixtures/wpt/hr-time/resources/unload-c.html @@ -0,0 +1,13 @@ + + + + Helper page for ../unload-manual.html + + + + + + + diff --git a/test/fixtures/wpt/hr-time/resources/unload.js b/test/fixtures/wpt/hr-time/resources/unload.js new file mode 100644 index 00000000000000..06b0bc7da78b4b --- /dev/null +++ b/test/fixtures/wpt/hr-time/resources/unload.js @@ -0,0 +1,50 @@ +const syncDelay = ms => { + const start = performance.now(); + let elapsedTime; + do { + elapsedTime = performance.now() - start; + } while (elapsedTime < ms); +}; + +const markTime = (docName, lifecycleEventName) => { + // Calculating these values before the below `mark` invocation ensures that delays in + // reaching across to the other window object doesn't interfere with the correctness + // of the test. + const dateNow = Date.now(); + const performanceNow = performance.now(); + + window.opener.mark({ + docName, + lifecycleEventName, + performanceNow: performanceNow, + dateNow: dateNow + }); +}; + +const setupUnloadPrompt = (docName, msg) => { + window.addEventListener("beforeunload", ev => { + markTime(docName, "beforeunload"); + return ev.returnValue = msg || "Click OK to continue test." + }); +}; + +const setupListeners = (docName, nextDocument) => { + window.addEventListener("load", () => { + markTime(docName, "load"); + document.getElementById("proceed").addEventListener("click", ev => { + ev.preventDefault(); + if (nextDocument) { + document.location = nextDocument; + } else { + window.close(); + } + }) + }); + + setupUnloadPrompt(docName); + + window.addEventListener("unload", () => { + markTime(docName, "unload"); + if (docName !== "c") { syncDelay(1000); } + }); +}; diff --git a/test/fixtures/wpt/hr-time/test_cross_frame_start.html b/test/fixtures/wpt/hr-time/test_cross_frame_start.html new file mode 100644 index 00000000000000..30e804bd735031 --- /dev/null +++ b/test/fixtures/wpt/hr-time/test_cross_frame_start.html @@ -0,0 +1,59 @@ + + + + + window.performance.now across frames + + + + + + + + + + +

Description

+

This test validates the values of the window.performance.now() are based on the current document's navigationStart.

+
+ + diff --git a/test/fixtures/wpt/hr-time/timeOrigin.html b/test/fixtures/wpt/hr-time/timeOrigin.html new file mode 100644 index 00000000000000..20aea75084515a --- /dev/null +++ b/test/fixtures/wpt/hr-time/timeOrigin.html @@ -0,0 +1,45 @@ + + + + + + + + + + \ No newline at end of file diff --git a/test/fixtures/wpt/hr-time/timing-attack.html b/test/fixtures/wpt/hr-time/timing-attack.html new file mode 100644 index 00000000000000..71ade4a8c48ce2 --- /dev/null +++ b/test/fixtures/wpt/hr-time/timing-attack.html @@ -0,0 +1,55 @@ + + + + +window.performance.now should not enable timing attacks + + + + + + + +

Description

+

The recommended minimum resolution of the Performance interface should be set to 5 microseconds.

+ +
+ + + diff --git a/test/fixtures/wpt/hr-time/unload-manual.html b/test/fixtures/wpt/hr-time/unload-manual.html new file mode 100644 index 00000000000000..18c4e0dc327919 --- /dev/null +++ b/test/fixtures/wpt/hr-time/unload-manual.html @@ -0,0 +1,73 @@ + + + + time origin value manual test + + + + + + + + + + +

Description

+

This test validates the behavior of performance.now() with respect to its time origin.

+
+

Manual Test Steps

+
    +
  1. Click here +
+
+ + diff --git a/test/fixtures/wpt/hr-time/window-worker-timeOrigin.window.js b/test/fixtures/wpt/hr-time/window-worker-timeOrigin.window.js new file mode 100644 index 00000000000000..1e5ef1cdffecf6 --- /dev/null +++ b/test/fixtures/wpt/hr-time/window-worker-timeOrigin.window.js @@ -0,0 +1,30 @@ +"use strict" +// https://w3c.github.io/hr-time/#time-origin + +async_test(function(test) { + // Cache global time before starting worker + const globalTimeOrigin = performance.timeOrigin; + const globalNowBeforeWorkerStart = performance.now(); + + // Start worker and retrieve time + const workerScript = "postMessage({timeOrigin: performance.timeOrigin, now: performance.now()})"; + const blob = new Blob([workerScript]); + let worker = new Worker(URL.createObjectURL(blob)); + + worker.addEventListener("message", test.step_func_done(function(event) { + const workerTimeOrigin = event.data.timeOrigin; + const workerNow = event.data.now; + + assert_not_equals(workerTimeOrigin, 0, "worker timeOrigin must not be 0"); + assert_not_equals(performance.timeOrigin, 0, "Document timeOrigin must not be 0"); + + assert_equals(globalTimeOrigin, performance.timeOrigin, "timeOrigin should not be changed in same document mode"); + assert_less_than(globalTimeOrigin, workerTimeOrigin, "Document timeOrigin must be earlier than worker timeOrigin"); + + // Document and worker's now() start from their respective timeOrigins. + const timeDiff = workerTimeOrigin - globalTimeOrigin; // convert worker's time to Document time. + assert_less_than(globalTimeOrigin + globalNowBeforeWorkerStart, globalTimeOrigin + timeDiff + workerNow, "Document old now is earlier than worker now."); + + // Comparing timing between Document and worker threads could be delicate as it relies on the thread implementation and could be subject to race conditions. + })); +}, 'timeOrigin and now() should be correctly ordered between window and worker'); diff --git a/test/fixtures/wpt/interfaces/console.idl b/test/fixtures/wpt/interfaces/console.idl index 53130711a1173f..3cd3c06b54b022 100644 --- a/test/fixtures/wpt/interfaces/console.idl +++ b/test/fixtures/wpt/interfaces/console.idl @@ -12,10 +12,10 @@ namespace console { // but see namespace object requirements below void error(any... data); void info(any... data); void log(any... data); - void table(any tabularData, optional sequence properties); + void table(optional any tabularData, optional sequence properties); void trace(any... data); void warn(any... data); - void dir(any item, optional object? options); + void dir(optional any item, optional object? options); void dirxml(any... data); // Counting diff --git a/test/fixtures/wpt/interfaces/dom.idl b/test/fixtures/wpt/interfaces/dom.idl new file mode 100644 index 00000000000000..102c23123819ba --- /dev/null +++ b/test/fixtures/wpt/interfaces/dom.idl @@ -0,0 +1,622 @@ +// GENERATED CONTENT - DO NOT EDIT +// Content was automatically extracted by Reffy into reffy-reports +// (https://github.com/tidoust/reffy-reports) +// Source: DOM Standard (https://dom.spec.whatwg.org/) + +[Exposed=(Window,Worker,AudioWorklet)] +interface Event { + constructor(DOMString type, optional EventInit eventInitDict = {}); + + readonly attribute DOMString type; + readonly attribute EventTarget? target; + readonly attribute EventTarget? srcElement; // historical + readonly attribute EventTarget? currentTarget; + sequence composedPath(); + + const unsigned short NONE = 0; + const unsigned short CAPTURING_PHASE = 1; + const unsigned short AT_TARGET = 2; + const unsigned short BUBBLING_PHASE = 3; + readonly attribute unsigned short eventPhase; + + void stopPropagation(); + attribute boolean cancelBubble; // historical alias of .stopPropagation + void stopImmediatePropagation(); + + readonly attribute boolean bubbles; + readonly attribute boolean cancelable; + attribute boolean returnValue; // historical + void preventDefault(); + readonly attribute boolean defaultPrevented; + readonly attribute boolean composed; + + [LegacyUnforgeable] readonly attribute boolean isTrusted; + readonly attribute DOMHighResTimeStamp timeStamp; + + void initEvent(DOMString type, optional boolean bubbles = false, optional boolean cancelable = false); // historical +}; + +dictionary EventInit { + boolean bubbles = false; + boolean cancelable = false; + boolean composed = false; +}; + +partial interface Window { + [Replaceable] readonly attribute any event; // historical +}; + +[Exposed=(Window,Worker)] +interface CustomEvent : Event { + constructor(DOMString type, optional CustomEventInit eventInitDict = {}); + + readonly attribute any detail; + + void initCustomEvent(DOMString type, optional boolean bubbles = false, optional boolean cancelable = false, optional any detail = null); // historical +}; + +dictionary CustomEventInit : EventInit { + any detail = null; +}; + +[Exposed=(Window,Worker,AudioWorklet)] +interface EventTarget { + constructor(); + + void addEventListener(DOMString type, EventListener? callback, optional (AddEventListenerOptions or boolean) options = {}); + void removeEventListener(DOMString type, EventListener? callback, optional (EventListenerOptions or boolean) options = {}); + boolean dispatchEvent(Event event); +}; + +callback interface EventListener { + void handleEvent(Event event); +}; + +dictionary EventListenerOptions { + boolean capture = false; +}; + +dictionary AddEventListenerOptions : EventListenerOptions { + boolean passive = false; + boolean once = false; +}; + +[Exposed=(Window,Worker)] +interface AbortController { + constructor(); + + [SameObject] readonly attribute AbortSignal signal; + + void abort(); +}; + +[Exposed=(Window,Worker)] +interface AbortSignal : EventTarget { + readonly attribute boolean aborted; + + attribute EventHandler onabort; +}; +interface mixin NonElementParentNode { + Element? getElementById(DOMString elementId); +}; +Document includes NonElementParentNode; +DocumentFragment includes NonElementParentNode; + +interface mixin DocumentOrShadowRoot { +}; +Document includes DocumentOrShadowRoot; +ShadowRoot includes DocumentOrShadowRoot; + +interface mixin ParentNode { + [SameObject] readonly attribute HTMLCollection children; + readonly attribute Element? firstElementChild; + readonly attribute Element? lastElementChild; + readonly attribute unsigned long childElementCount; + + [CEReactions, Unscopable] void prepend((Node or DOMString)... nodes); + [CEReactions, Unscopable] void append((Node or DOMString)... nodes); + [CEReactions, Unscopable] void replaceChildren((Node or DOMString)... nodes); + + Element? querySelector(DOMString selectors); + [NewObject] NodeList querySelectorAll(DOMString selectors); +}; +Document includes ParentNode; +DocumentFragment includes ParentNode; +Element includes ParentNode; + +interface mixin NonDocumentTypeChildNode { + readonly attribute Element? previousElementSibling; + readonly attribute Element? nextElementSibling; +}; +Element includes NonDocumentTypeChildNode; +CharacterData includes NonDocumentTypeChildNode; + +interface mixin ChildNode { + [CEReactions, Unscopable] void before((Node or DOMString)... nodes); + [CEReactions, Unscopable] void after((Node or DOMString)... nodes); + [CEReactions, Unscopable] void replaceWith((Node or DOMString)... nodes); + [CEReactions, Unscopable] void remove(); +}; +DocumentType includes ChildNode; +Element includes ChildNode; +CharacterData includes ChildNode; + +interface mixin Slottable { + readonly attribute HTMLSlotElement? assignedSlot; +}; +Element includes Slottable; +Text includes Slottable; + +[Exposed=Window] +interface NodeList { + getter Node? item(unsigned long index); + readonly attribute unsigned long length; + iterable; +}; + +[Exposed=Window, LegacyUnenumerableNamedProperties] +interface HTMLCollection { + readonly attribute unsigned long length; + getter Element? item(unsigned long index); + getter Element? namedItem(DOMString name); +}; + +[Exposed=Window] +interface MutationObserver { + constructor(MutationCallback callback); + + void observe(Node target, optional MutationObserverInit options = {}); + void disconnect(); + sequence takeRecords(); +}; + +callback MutationCallback = void (sequence mutations, MutationObserver observer); + +dictionary MutationObserverInit { + boolean childList = false; + boolean attributes; + boolean characterData; + boolean subtree = false; + boolean attributeOldValue; + boolean characterDataOldValue; + sequence attributeFilter; +}; + +[Exposed=Window] +interface MutationRecord { + readonly attribute DOMString type; + [SameObject] readonly attribute Node target; + [SameObject] readonly attribute NodeList addedNodes; + [SameObject] readonly attribute NodeList removedNodes; + readonly attribute Node? previousSibling; + readonly attribute Node? nextSibling; + readonly attribute DOMString? attributeName; + readonly attribute DOMString? attributeNamespace; + readonly attribute DOMString? oldValue; +}; + +[Exposed=Window] +interface Node : EventTarget { + const unsigned short ELEMENT_NODE = 1; + const unsigned short ATTRIBUTE_NODE = 2; + const unsigned short TEXT_NODE = 3; + const unsigned short CDATA_SECTION_NODE = 4; + const unsigned short ENTITY_REFERENCE_NODE = 5; // historical + const unsigned short ENTITY_NODE = 6; // historical + const unsigned short PROCESSING_INSTRUCTION_NODE = 7; + const unsigned short COMMENT_NODE = 8; + const unsigned short DOCUMENT_NODE = 9; + const unsigned short DOCUMENT_TYPE_NODE = 10; + const unsigned short DOCUMENT_FRAGMENT_NODE = 11; + const unsigned short NOTATION_NODE = 12; // historical + readonly attribute unsigned short nodeType; + readonly attribute DOMString nodeName; + + readonly attribute USVString baseURI; + + readonly attribute boolean isConnected; + readonly attribute Document? ownerDocument; + Node getRootNode(optional GetRootNodeOptions options = {}); + readonly attribute Node? parentNode; + readonly attribute Element? parentElement; + boolean hasChildNodes(); + [SameObject] readonly attribute NodeList childNodes; + readonly attribute Node? firstChild; + readonly attribute Node? lastChild; + readonly attribute Node? previousSibling; + readonly attribute Node? nextSibling; + + [CEReactions] attribute DOMString? nodeValue; + [CEReactions] attribute DOMString? textContent; + [CEReactions] void normalize(); + + [CEReactions, NewObject] Node cloneNode(optional boolean deep = false); + boolean isEqualNode(Node? otherNode); + boolean isSameNode(Node? otherNode); // historical alias of === + + const unsigned short DOCUMENT_POSITION_DISCONNECTED = 0x01; + const unsigned short DOCUMENT_POSITION_PRECEDING = 0x02; + const unsigned short DOCUMENT_POSITION_FOLLOWING = 0x04; + const unsigned short DOCUMENT_POSITION_CONTAINS = 0x08; + const unsigned short DOCUMENT_POSITION_CONTAINED_BY = 0x10; + const unsigned short DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20; + unsigned short compareDocumentPosition(Node other); + boolean contains(Node? other); + + DOMString? lookupPrefix(DOMString? namespace); + DOMString? lookupNamespaceURI(DOMString? prefix); + boolean isDefaultNamespace(DOMString? namespace); + + [CEReactions] Node insertBefore(Node node, Node? child); + [CEReactions] Node appendChild(Node node); + [CEReactions] Node replaceChild(Node node, Node child); + [CEReactions] Node removeChild(Node child); +}; + +dictionary GetRootNodeOptions { + boolean composed = false; +}; + +[Exposed=Window] +interface Document : Node { + constructor(); + + [SameObject] readonly attribute DOMImplementation implementation; + readonly attribute USVString URL; + readonly attribute USVString documentURI; + readonly attribute DOMString compatMode; + readonly attribute DOMString characterSet; + readonly attribute DOMString charset; // historical alias of .characterSet + readonly attribute DOMString inputEncoding; // historical alias of .characterSet + readonly attribute DOMString contentType; + + readonly attribute DocumentType? doctype; + readonly attribute Element? documentElement; + HTMLCollection getElementsByTagName(DOMString qualifiedName); + HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName); + HTMLCollection getElementsByClassName(DOMString classNames); + + [CEReactions, NewObject] Element createElement(DOMString localName, optional (DOMString or ElementCreationOptions) options = {}); + [CEReactions, NewObject] Element createElementNS(DOMString? namespace, DOMString qualifiedName, optional (DOMString or ElementCreationOptions) options = {}); + [NewObject] DocumentFragment createDocumentFragment(); + [NewObject] Text createTextNode(DOMString data); + [NewObject] CDATASection createCDATASection(DOMString data); + [NewObject] Comment createComment(DOMString data); + [NewObject] ProcessingInstruction createProcessingInstruction(DOMString target, DOMString data); + + [CEReactions, NewObject] Node importNode(Node node, optional boolean deep = false); + [CEReactions] Node adoptNode(Node node); + + [NewObject] Attr createAttribute(DOMString localName); + [NewObject] Attr createAttributeNS(DOMString? namespace, DOMString qualifiedName); + + [NewObject] Event createEvent(DOMString interface); // historical + + [NewObject] Range createRange(); + + // NodeFilter.SHOW_ALL = 0xFFFFFFFF + [NewObject] NodeIterator createNodeIterator(Node root, optional unsigned long whatToShow = 0xFFFFFFFF, optional NodeFilter? filter = null); + [NewObject] TreeWalker createTreeWalker(Node root, optional unsigned long whatToShow = 0xFFFFFFFF, optional NodeFilter? filter = null); +}; + +[Exposed=Window] +interface XMLDocument : Document {}; + +dictionary ElementCreationOptions { + DOMString is; +}; + +[Exposed=Window] +interface DOMImplementation { + [NewObject] DocumentType createDocumentType(DOMString qualifiedName, DOMString publicId, DOMString systemId); + [NewObject] XMLDocument createDocument(DOMString? namespace, [LegacyNullToEmptyString] DOMString qualifiedName, optional DocumentType? doctype = null); + [NewObject] Document createHTMLDocument(optional DOMString title); + + boolean hasFeature(); // useless; always returns true +}; + +[Exposed=Window] +interface DocumentType : Node { + readonly attribute DOMString name; + readonly attribute DOMString publicId; + readonly attribute DOMString systemId; +}; + +[Exposed=Window] +interface DocumentFragment : Node { + constructor(); +}; + +[Exposed=Window] +interface ShadowRoot : DocumentFragment { + readonly attribute ShadowRootMode mode; + readonly attribute Element host; + attribute EventHandler onslotchange; +}; + +enum ShadowRootMode { "open", "closed" }; + +[Exposed=Window] +interface Element : Node { + readonly attribute DOMString? namespaceURI; + readonly attribute DOMString? prefix; + readonly attribute DOMString localName; + readonly attribute DOMString tagName; + + [CEReactions] attribute DOMString id; + [CEReactions] attribute DOMString className; + [SameObject, PutForwards=value] readonly attribute DOMTokenList classList; + [CEReactions, Unscopable] attribute DOMString slot; + + boolean hasAttributes(); + [SameObject] readonly attribute NamedNodeMap attributes; + sequence getAttributeNames(); + DOMString? getAttribute(DOMString qualifiedName); + DOMString? getAttributeNS(DOMString? namespace, DOMString localName); + [CEReactions] void setAttribute(DOMString qualifiedName, DOMString value); + [CEReactions] void setAttributeNS(DOMString? namespace, DOMString qualifiedName, DOMString value); + [CEReactions] void removeAttribute(DOMString qualifiedName); + [CEReactions] void removeAttributeNS(DOMString? namespace, DOMString localName); + [CEReactions] boolean toggleAttribute(DOMString qualifiedName, optional boolean force); + boolean hasAttribute(DOMString qualifiedName); + boolean hasAttributeNS(DOMString? namespace, DOMString localName); + + Attr? getAttributeNode(DOMString qualifiedName); + Attr? getAttributeNodeNS(DOMString? namespace, DOMString localName); + [CEReactions] Attr? setAttributeNode(Attr attr); + [CEReactions] Attr? setAttributeNodeNS(Attr attr); + [CEReactions] Attr removeAttributeNode(Attr attr); + + ShadowRoot attachShadow(ShadowRootInit init); + readonly attribute ShadowRoot? shadowRoot; + + Element? closest(DOMString selectors); + boolean matches(DOMString selectors); + boolean webkitMatchesSelector(DOMString selectors); // historical alias of .matches + + HTMLCollection getElementsByTagName(DOMString qualifiedName); + HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName); + HTMLCollection getElementsByClassName(DOMString classNames); + + [CEReactions] Element? insertAdjacentElement(DOMString where, Element element); // historical + void insertAdjacentText(DOMString where, DOMString data); // historical +}; + +dictionary ShadowRootInit { + required ShadowRootMode mode; + boolean delegatesFocus = false; +}; + +[Exposed=Window, + LegacyUnenumerableNamedProperties] +interface NamedNodeMap { + readonly attribute unsigned long length; + getter Attr? item(unsigned long index); + getter Attr? getNamedItem(DOMString qualifiedName); + Attr? getNamedItemNS(DOMString? namespace, DOMString localName); + [CEReactions] Attr? setNamedItem(Attr attr); + [CEReactions] Attr? setNamedItemNS(Attr attr); + [CEReactions] Attr removeNamedItem(DOMString qualifiedName); + [CEReactions] Attr removeNamedItemNS(DOMString? namespace, DOMString localName); +}; + +[Exposed=Window] +interface Attr : Node { + readonly attribute DOMString? namespaceURI; + readonly attribute DOMString? prefix; + readonly attribute DOMString localName; + readonly attribute DOMString name; + [CEReactions] attribute DOMString value; + + readonly attribute Element? ownerElement; + + readonly attribute boolean specified; // useless; always returns true +}; +[Exposed=Window] +interface CharacterData : Node { + attribute [LegacyNullToEmptyString] DOMString data; + readonly attribute unsigned long length; + DOMString substringData(unsigned long offset, unsigned long count); + void appendData(DOMString data); + void insertData(unsigned long offset, DOMString data); + void deleteData(unsigned long offset, unsigned long count); + void replaceData(unsigned long offset, unsigned long count, DOMString data); +}; + +[Exposed=Window] +interface Text : CharacterData { + constructor(optional DOMString data = ""); + + [NewObject] Text splitText(unsigned long offset); + readonly attribute DOMString wholeText; +}; + +[Exposed=Window] +interface CDATASection : Text { +}; +[Exposed=Window] +interface ProcessingInstruction : CharacterData { + readonly attribute DOMString target; +}; +[Exposed=Window] +interface Comment : CharacterData { + constructor(optional DOMString data = ""); +}; + +[Exposed=Window] +interface AbstractRange { + readonly attribute Node startContainer; + readonly attribute unsigned long startOffset; + readonly attribute Node endContainer; + readonly attribute unsigned long endOffset; + readonly attribute boolean collapsed; +}; + +dictionary StaticRangeInit { + required Node startContainer; + required unsigned long startOffset; + required Node endContainer; + required unsigned long endOffset; +}; + +[Exposed=Window] +interface StaticRange : AbstractRange { + constructor(StaticRangeInit init); +}; + +[Exposed=Window] +interface Range : AbstractRange { + constructor(); + + readonly attribute Node commonAncestorContainer; + + void setStart(Node node, unsigned long offset); + void setEnd(Node node, unsigned long offset); + void setStartBefore(Node node); + void setStartAfter(Node node); + void setEndBefore(Node node); + void setEndAfter(Node node); + void collapse(optional boolean toStart = false); + void selectNode(Node node); + void selectNodeContents(Node node); + + const unsigned short START_TO_START = 0; + const unsigned short START_TO_END = 1; + const unsigned short END_TO_END = 2; + const unsigned short END_TO_START = 3; + short compareBoundaryPoints(unsigned short how, Range sourceRange); + + [CEReactions] void deleteContents(); + [CEReactions, NewObject] DocumentFragment extractContents(); + [CEReactions, NewObject] DocumentFragment cloneContents(); + [CEReactions] void insertNode(Node node); + [CEReactions] void surroundContents(Node newParent); + + [NewObject] Range cloneRange(); + void detach(); + + boolean isPointInRange(Node node, unsigned long offset); + short comparePoint(Node node, unsigned long offset); + + boolean intersectsNode(Node node); + + stringifier; +}; + +[Exposed=Window] +interface NodeIterator { + [SameObject] readonly attribute Node root; + readonly attribute Node referenceNode; + readonly attribute boolean pointerBeforeReferenceNode; + readonly attribute unsigned long whatToShow; + readonly attribute NodeFilter? filter; + + Node? nextNode(); + Node? previousNode(); + + void detach(); +}; + +[Exposed=Window] +interface TreeWalker { + [SameObject] readonly attribute Node root; + readonly attribute unsigned long whatToShow; + readonly attribute NodeFilter? filter; + attribute Node currentNode; + + Node? parentNode(); + Node? firstChild(); + Node? lastChild(); + Node? previousSibling(); + Node? nextSibling(); + Node? previousNode(); + Node? nextNode(); +}; +[Exposed=Window] +callback interface NodeFilter { + // Constants for acceptNode() + const unsigned short FILTER_ACCEPT = 1; + const unsigned short FILTER_REJECT = 2; + const unsigned short FILTER_SKIP = 3; + + // Constants for whatToShow + const unsigned long SHOW_ALL = 0xFFFFFFFF; + const unsigned long SHOW_ELEMENT = 0x1; + const unsigned long SHOW_ATTRIBUTE = 0x2; + const unsigned long SHOW_TEXT = 0x4; + const unsigned long SHOW_CDATA_SECTION = 0x8; + const unsigned long SHOW_ENTITY_REFERENCE = 0x10; // historical + const unsigned long SHOW_ENTITY = 0x20; // historical + const unsigned long SHOW_PROCESSING_INSTRUCTION = 0x40; + const unsigned long SHOW_COMMENT = 0x80; + const unsigned long SHOW_DOCUMENT = 0x100; + const unsigned long SHOW_DOCUMENT_TYPE = 0x200; + const unsigned long SHOW_DOCUMENT_FRAGMENT = 0x400; + const unsigned long SHOW_NOTATION = 0x800; // historical + + unsigned short acceptNode(Node node); +}; + +[Exposed=Window] +interface DOMTokenList { + readonly attribute unsigned long length; + getter DOMString? item(unsigned long index); + boolean contains(DOMString token); + [CEReactions] void add(DOMString... tokens); + [CEReactions] void remove(DOMString... tokens); + [CEReactions] boolean toggle(DOMString token, optional boolean force); + [CEReactions] boolean replace(DOMString token, DOMString newToken); + boolean supports(DOMString token); + [CEReactions] stringifier attribute DOMString value; + iterable; +}; + +[Exposed=Window] +interface XPathResult { + const unsigned short ANY_TYPE = 0; + const unsigned short NUMBER_TYPE = 1; + const unsigned short STRING_TYPE = 2; + const unsigned short BOOLEAN_TYPE = 3; + const unsigned short UNORDERED_NODE_ITERATOR_TYPE = 4; + const unsigned short ORDERED_NODE_ITERATOR_TYPE = 5; + const unsigned short UNORDERED_NODE_SNAPSHOT_TYPE = 6; + const unsigned short ORDERED_NODE_SNAPSHOT_TYPE = 7; + const unsigned short ANY_UNORDERED_NODE_TYPE = 8; + const unsigned short FIRST_ORDERED_NODE_TYPE = 9; + + readonly attribute unsigned short resultType; + readonly attribute unrestricted double numberValue; + readonly attribute DOMString stringValue; + readonly attribute boolean booleanValue; + readonly attribute Node? singleNodeValue; + readonly attribute boolean invalidIteratorState; + readonly attribute unsigned long snapshotLength; + + Node? iterateNext(); + Node? snapshotItem(unsigned long index); +}; + +[Exposed=Window] +interface XPathExpression { + // XPathResult.ANY_TYPE = 0 + XPathResult evaluate(Node contextNode, optional unsigned short type = 0, optional XPathResult? result = null); +}; + +callback interface XPathNSResolver { + DOMString? lookupNamespaceURI(DOMString? prefix); +}; + +interface mixin XPathEvaluatorBase { + [NewObject] XPathExpression createExpression(DOMString expression, optional XPathNSResolver? resolver = null); + XPathNSResolver createNSResolver(Node nodeResolver); + // XPathResult.ANY_TYPE = 0 + XPathResult evaluate(DOMString expression, Node contextNode, optional XPathNSResolver? resolver = null, optional unsigned short type = 0, optional XPathResult? result = null); +}; +Document includes XPathEvaluatorBase; + +[Exposed=Window] +interface XPathEvaluator { + constructor(); +}; + +XPathEvaluator includes XPathEvaluatorBase; diff --git a/test/fixtures/wpt/interfaces/encoding.idl b/test/fixtures/wpt/interfaces/encoding.idl index b805363c534fea..d00624fa1ed7ed 100644 --- a/test/fixtures/wpt/interfaces/encoding.idl +++ b/test/fixtures/wpt/interfaces/encoding.idl @@ -18,10 +18,11 @@ dictionary TextDecodeOptions { boolean stream = false; }; -[Constructor(optional DOMString label = "utf-8", optional TextDecoderOptions options), - Exposed=(Window,Worker)] +[Exposed=(Window,Worker)] interface TextDecoder { - USVString decode(optional BufferSource input, optional TextDecodeOptions options); + constructor(optional DOMString label = "utf-8", optional TextDecoderOptions options = {}); + + USVString decode(optional [AllowShared] BufferSource input, optional TextDecodeOptions options = {}); }; TextDecoder includes TextDecoderCommon; @@ -29,10 +30,17 @@ interface mixin TextEncoderCommon { readonly attribute DOMString encoding; }; -[Constructor, - Exposed=(Window,Worker)] +dictionary TextEncoderEncodeIntoResult { + unsigned long long read; + unsigned long long written; +}; + +[Exposed=(Window,Worker)] interface TextEncoder { + constructor(); + [NewObject] Uint8Array encode(optional USVString input = ""); + TextEncoderEncodeIntoResult encodeInto(USVString source, [AllowShared] Uint8Array destination); }; TextEncoder includes TextEncoderCommon; @@ -41,16 +49,16 @@ interface mixin GenericTransformStream { readonly attribute WritableStream writable; }; -[Constructor(optional DOMString label = "utf-8", optional TextDecoderOptions options), - Exposed=(Window,Worker)] +[Exposed=(Window,Worker)] interface TextDecoderStream { + constructor(optional DOMString label = "utf-8", optional TextDecoderOptions options = {}); }; TextDecoderStream includes TextDecoderCommon; TextDecoderStream includes GenericTransformStream; -[Constructor, - Exposed=(Window,Worker)] +[Exposed=(Window,Worker)] interface TextEncoderStream { + constructor(); }; TextEncoderStream includes TextEncoderCommon; TextEncoderStream includes GenericTransformStream; diff --git a/test/fixtures/wpt/interfaces/hr-time.idl b/test/fixtures/wpt/interfaces/hr-time.idl new file mode 100644 index 00000000000000..8179c66f44de27 --- /dev/null +++ b/test/fixtures/wpt/interfaces/hr-time.idl @@ -0,0 +1,17 @@ +// GENERATED CONTENT - DO NOT EDIT +// Content was automatically extracted by Reffy into reffy-reports +// (https://github.com/tidoust/reffy-reports) +// Source: High Resolution Time (https://w3c.github.io/hr-time/) + +typedef double DOMHighResTimeStamp; + +[Exposed=(Window,Worker)] +interface Performance : EventTarget { + DOMHighResTimeStamp now(); + readonly attribute DOMHighResTimeStamp timeOrigin; + [Default] object toJSON(); +}; + +partial interface mixin WindowOrWorkerGlobalScope { + [Replaceable] readonly attribute Performance performance; +}; diff --git a/test/fixtures/wpt/interfaces/html.idl b/test/fixtures/wpt/interfaces/html.idl new file mode 100644 index 00000000000000..7b2a96ce6760a0 --- /dev/null +++ b/test/fixtures/wpt/interfaces/html.idl @@ -0,0 +1,2615 @@ +// GENERATED CONTENT - DO NOT EDIT +// Content was automatically extracted by Reffy into reffy-reports +// (https://github.com/tidoust/reffy-reports) +// Source: HTML Standard (https://html.spec.whatwg.org/multipage/) + +[Exposed=Window, + LegacyUnenumerableNamedProperties] +interface HTMLAllCollection { + readonly attribute unsigned long length; + getter Element (unsigned long index); + getter (HTMLCollection or Element)? namedItem(DOMString name); + (HTMLCollection or Element)? item(optional DOMString nameOrIndex); + + // Note: HTMLAllCollection objects have a custom [[Call]] internal method and an [[IsHTMLDDA]] internal slot. +}; + +[Exposed=Window] +interface HTMLFormControlsCollection : HTMLCollection { + // inherits length and item() + getter (RadioNodeList or Element)? namedItem(DOMString name); // shadows inherited namedItem() +}; + +[Exposed=Window] +interface RadioNodeList : NodeList { + attribute DOMString value; +}; + +[Exposed=Window] +interface HTMLOptionsCollection : HTMLCollection { + // inherits item(), namedItem() + [CEReactions] attribute unsigned long length; // shadows inherited length + [CEReactions] setter void (unsigned long index, HTMLOptionElement? option); + [CEReactions] void add((HTMLOptionElement or HTMLOptGroupElement) element, optional (HTMLElement or long)? before = null); + [CEReactions] void remove(long index); + attribute long selectedIndex; +}; + +[Exposed=(Window,Worker)] +interface DOMStringList { + readonly attribute unsigned long length; + getter DOMString? item(unsigned long index); + boolean contains(DOMString string); +}; + +enum DocumentReadyState { "loading", "interactive", "complete" }; +typedef (HTMLScriptElement or SVGScriptElement) HTMLOrSVGScriptElement; + +[LegacyOverrideBuiltIns] +partial interface Document { + // resource metadata management + [PutForwards=href, LegacyUnforgeable] readonly attribute Location? location; + attribute USVString domain; + readonly attribute USVString referrer; + attribute USVString cookie; + readonly attribute DOMString lastModified; + readonly attribute DocumentReadyState readyState; + + // DOM tree accessors + getter object (DOMString name); + [CEReactions] attribute DOMString title; + [CEReactions] attribute DOMString dir; + [CEReactions] attribute HTMLElement? body; + readonly attribute HTMLHeadElement? head; + [SameObject] readonly attribute HTMLCollection images; + [SameObject] readonly attribute HTMLCollection embeds; + [SameObject] readonly attribute HTMLCollection plugins; + [SameObject] readonly attribute HTMLCollection links; + [SameObject] readonly attribute HTMLCollection forms; + [SameObject] readonly attribute HTMLCollection scripts; + NodeList getElementsByName(DOMString elementName); + readonly attribute HTMLOrSVGScriptElement? currentScript; // classic scripts in a document tree only + + // dynamic markup insertion + [CEReactions] Document open(optional DOMString unused1, optional DOMString unused2); // both arguments are ignored + WindowProxy? open(USVString url, DOMString name, DOMString features); + [CEReactions] void close(); + [CEReactions] void write(DOMString... text); + [CEReactions] void writeln(DOMString... text); + + // user interaction + readonly attribute WindowProxy? defaultView; + boolean hasFocus(); + [CEReactions] attribute DOMString designMode; + [CEReactions] boolean execCommand(DOMString commandId, optional boolean showUI = false, optional DOMString value = ""); + boolean queryCommandEnabled(DOMString commandId); + boolean queryCommandIndeterm(DOMString commandId); + boolean queryCommandState(DOMString commandId); + boolean queryCommandSupported(DOMString commandId); + DOMString queryCommandValue(DOMString commandId); + + // special event handler IDL attributes that only apply to Document objects + [LegacyLenientThis] attribute EventHandler onreadystatechange; + + // also has obsolete members +}; +Document includes GlobalEventHandlers; +Document includes DocumentAndElementEventHandlers; + +partial interface mixin DocumentOrShadowRoot { + readonly attribute Element? activeElement; +}; + +[Exposed=Window] +interface HTMLElement : Element { + [HTMLConstructor] constructor(); + + // metadata attributes + [CEReactions] attribute DOMString title; + [CEReactions] attribute DOMString lang; + [CEReactions] attribute boolean translate; + [CEReactions] attribute DOMString dir; + + // user interaction + [CEReactions] attribute boolean hidden; + void click(); + [CEReactions] attribute DOMString accessKey; + readonly attribute DOMString accessKeyLabel; + [CEReactions] attribute boolean draggable; + [CEReactions] attribute boolean spellcheck; + [CEReactions] attribute DOMString autocapitalize; + + [CEReactions] attribute [LegacyNullToEmptyString] DOMString innerText; + + ElementInternals attachInternals(); +}; + +HTMLElement includes GlobalEventHandlers; +HTMLElement includes DocumentAndElementEventHandlers; +HTMLElement includes ElementContentEditable; +HTMLElement includes HTMLOrSVGElement; + +[Exposed=Window] +interface HTMLUnknownElement : HTMLElement { + // Note: intentionally no [HTMLConstructor] +}; + +interface mixin HTMLOrSVGElement { + [SameObject] readonly attribute DOMStringMap dataset; + attribute DOMString nonce; // intentionally no [CEReactions] + + [CEReactions] attribute boolean autofocus; + [CEReactions] attribute long tabIndex; + void focus(optional FocusOptions options = {}); + void blur(); +}; + +[Exposed=Window, + LegacyOverrideBuiltIns] +interface DOMStringMap { + getter DOMString (DOMString name); + [CEReactions] setter void (DOMString name, DOMString value); + [CEReactions] deleter void (DOMString name); +}; + +[Exposed=Window] +interface HTMLHtmlElement : HTMLElement { + [HTMLConstructor] constructor(); +}; + +[Exposed=Window] +interface HTMLHeadElement : HTMLElement { + [HTMLConstructor] constructor(); +}; + +[Exposed=Window] +interface HTMLTitleElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute DOMString text; +}; + +[Exposed=Window] +interface HTMLBaseElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute USVString href; + [CEReactions] attribute DOMString target; +}; + +[Exposed=Window] +interface HTMLLinkElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute USVString href; + [CEReactions] attribute DOMString? crossOrigin; + [CEReactions] attribute DOMString rel; + [CEReactions] attribute DOMString as; // (default "") + [SameObject, PutForwards=value] readonly attribute DOMTokenList relList; + [CEReactions] attribute DOMString media; + [CEReactions] attribute DOMString integrity; + [CEReactions] attribute DOMString hreflang; + [CEReactions] attribute DOMString type; + [SameObject, PutForwards=value] readonly attribute DOMTokenList sizes; + [CEReactions] attribute USVString imageSrcset; + [CEReactions] attribute DOMString imageSizes; + [CEReactions] attribute DOMString referrerPolicy; +}; +HTMLLinkElement includes LinkStyle; + +[Exposed=Window] +interface HTMLMetaElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute DOMString name; + [CEReactions] attribute DOMString httpEquiv; + [CEReactions] attribute DOMString content; +}; + +[Exposed=Window] +interface HTMLStyleElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute DOMString media; +}; +HTMLStyleElement includes LinkStyle; + +[Exposed=Window] +interface HTMLBodyElement : HTMLElement { + [HTMLConstructor] constructor(); +}; + +HTMLBodyElement includes WindowEventHandlers; + +[Exposed=Window] +interface HTMLHeadingElement : HTMLElement { + [HTMLConstructor] constructor(); +}; + +[Exposed=Window] +interface HTMLParagraphElement : HTMLElement { + [HTMLConstructor] constructor(); +}; + +[Exposed=Window] +interface HTMLHRElement : HTMLElement { + [HTMLConstructor] constructor(); +}; + +[Exposed=Window] +interface HTMLPreElement : HTMLElement { + [HTMLConstructor] constructor(); +}; + +[Exposed=Window] +interface HTMLQuoteElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute USVString cite; +}; + +[Exposed=Window] +interface HTMLOListElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute boolean reversed; + [CEReactions] attribute long start; + [CEReactions] attribute DOMString type; +}; + +[Exposed=Window] +interface HTMLUListElement : HTMLElement { + [HTMLConstructor] constructor(); +}; + +[Exposed=Window] +interface HTMLMenuElement : HTMLElement { + [HTMLConstructor] constructor(); +}; + +[Exposed=Window] +interface HTMLLIElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute long value; +}; + +[Exposed=Window] +interface HTMLDListElement : HTMLElement { + [HTMLConstructor] constructor(); +}; + +[Exposed=Window] +interface HTMLDivElement : HTMLElement { + [HTMLConstructor] constructor(); +}; + +[Exposed=Window] +interface HTMLAnchorElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute DOMString target; + [CEReactions] attribute DOMString download; + [CEReactions] attribute USVString ping; + [CEReactions] attribute DOMString rel; + [SameObject, PutForwards=value] readonly attribute DOMTokenList relList; + [CEReactions] attribute DOMString hreflang; + [CEReactions] attribute DOMString type; + + [CEReactions] attribute DOMString text; + + [CEReactions] attribute DOMString referrerPolicy; +}; +HTMLAnchorElement includes HTMLHyperlinkElementUtils; + +[Exposed=Window] +interface HTMLDataElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute DOMString value; +}; + +[Exposed=Window] +interface HTMLTimeElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute DOMString dateTime; +}; + +[Exposed=Window] +interface HTMLSpanElement : HTMLElement { + [HTMLConstructor] constructor(); +}; + +[Exposed=Window] +interface HTMLBRElement : HTMLElement { + [HTMLConstructor] constructor(); +}; + +interface mixin HTMLHyperlinkElementUtils { + [CEReactions] stringifier attribute USVString href; + readonly attribute USVString origin; + [CEReactions] attribute USVString protocol; + [CEReactions] attribute USVString username; + [CEReactions] attribute USVString password; + [CEReactions] attribute USVString host; + [CEReactions] attribute USVString hostname; + [CEReactions] attribute USVString port; + [CEReactions] attribute USVString pathname; + [CEReactions] attribute USVString search; + [CEReactions] attribute USVString hash; +}; + +[Exposed=Window] +interface HTMLModElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute USVString cite; + [CEReactions] attribute DOMString dateTime; +}; + +[Exposed=Window] +interface HTMLPictureElement : HTMLElement { + [HTMLConstructor] constructor(); +}; + +[Exposed=Window] +interface HTMLSourceElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute USVString src; + [CEReactions] attribute DOMString type; + [CEReactions] attribute USVString srcset; + [CEReactions] attribute DOMString sizes; + [CEReactions] attribute DOMString media; +}; + +[Exposed=Window, + LegacyFactoryFunction=Image(optional unsigned long width, optional unsigned long height)] +interface HTMLImageElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute DOMString alt; + [CEReactions] attribute USVString src; + [CEReactions] attribute USVString srcset; + [CEReactions] attribute DOMString sizes; + [CEReactions] attribute DOMString? crossOrigin; + [CEReactions] attribute DOMString useMap; + [CEReactions] attribute boolean isMap; + [CEReactions] attribute unsigned long width; + [CEReactions] attribute unsigned long height; + readonly attribute unsigned long naturalWidth; + readonly attribute unsigned long naturalHeight; + readonly attribute boolean complete; + readonly attribute USVString currentSrc; + [CEReactions] attribute DOMString referrerPolicy; + [CEReactions] attribute DOMString decoding; + [CEReactions] attribute DOMString loading; + + Promise decode(); +}; + +[Exposed=Window] +interface HTMLIFrameElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute USVString src; + [CEReactions] attribute DOMString srcdoc; + [CEReactions] attribute DOMString name; + [SameObject, PutForwards=value] readonly attribute DOMTokenList sandbox; + [CEReactions] attribute DOMString allow; + [CEReactions] attribute boolean allowFullscreen; + [CEReactions] attribute boolean allowPaymentRequest; + [CEReactions] attribute DOMString width; + [CEReactions] attribute DOMString height; + [CEReactions] attribute DOMString referrerPolicy; + readonly attribute Document? contentDocument; + readonly attribute WindowProxy? contentWindow; + Document? getSVGDocument(); +}; + +[Exposed=Window] +interface HTMLEmbedElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute USVString src; + [CEReactions] attribute DOMString type; + [CEReactions] attribute DOMString width; + [CEReactions] attribute DOMString height; + Document? getSVGDocument(); +}; + +[Exposed=Window] +interface HTMLObjectElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute USVString data; + [CEReactions] attribute DOMString type; + [CEReactions] attribute DOMString name; + [CEReactions] attribute DOMString useMap; + readonly attribute HTMLFormElement? form; + [CEReactions] attribute DOMString width; + [CEReactions] attribute DOMString height; + readonly attribute Document? contentDocument; + readonly attribute WindowProxy? contentWindow; + Document? getSVGDocument(); + + readonly attribute boolean willValidate; + readonly attribute ValidityState validity; + readonly attribute DOMString validationMessage; + boolean checkValidity(); + boolean reportValidity(); + void setCustomValidity(DOMString error); +}; + +[Exposed=Window] +interface HTMLParamElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute DOMString name; + [CEReactions] attribute DOMString value; +}; + +[Exposed=Window] +interface HTMLVideoElement : HTMLMediaElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute unsigned long width; + [CEReactions] attribute unsigned long height; + readonly attribute unsigned long videoWidth; + readonly attribute unsigned long videoHeight; + [CEReactions] attribute USVString poster; + [CEReactions] attribute boolean playsInline; +}; + +[Exposed=Window, + LegacyFactoryFunction=Audio(optional DOMString src)] +interface HTMLAudioElement : HTMLMediaElement { + [HTMLConstructor] constructor(); +}; + +[Exposed=Window] +interface HTMLTrackElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute DOMString kind; + [CEReactions] attribute USVString src; + [CEReactions] attribute DOMString srclang; + [CEReactions] attribute DOMString label; + [CEReactions] attribute boolean default; + + const unsigned short NONE = 0; + const unsigned short LOADING = 1; + const unsigned short LOADED = 2; + const unsigned short ERROR = 3; + readonly attribute unsigned short readyState; + + readonly attribute TextTrack track; +}; + +enum CanPlayTypeResult { "" /* empty string */, "maybe", "probably" }; +typedef (MediaStream or MediaSource or Blob) MediaProvider; + +[Exposed=Window] +interface HTMLMediaElement : HTMLElement { + + // error state + readonly attribute MediaError? error; + + // network state + [CEReactions] attribute USVString src; + attribute MediaProvider? srcObject; + readonly attribute USVString currentSrc; + [CEReactions] attribute DOMString? crossOrigin; + const unsigned short NETWORK_EMPTY = 0; + const unsigned short NETWORK_IDLE = 1; + const unsigned short NETWORK_LOADING = 2; + const unsigned short NETWORK_NO_SOURCE = 3; + readonly attribute unsigned short networkState; + [CEReactions] attribute DOMString preload; + readonly attribute TimeRanges buffered; + void load(); + CanPlayTypeResult canPlayType(DOMString type); + + // ready state + const unsigned short HAVE_NOTHING = 0; + const unsigned short HAVE_METADATA = 1; + const unsigned short HAVE_CURRENT_DATA = 2; + const unsigned short HAVE_FUTURE_DATA = 3; + const unsigned short HAVE_ENOUGH_DATA = 4; + readonly attribute unsigned short readyState; + readonly attribute boolean seeking; + + // playback state + attribute double currentTime; + void fastSeek(double time); + readonly attribute unrestricted double duration; + object getStartDate(); + readonly attribute boolean paused; + attribute double defaultPlaybackRate; + attribute double playbackRate; + readonly attribute TimeRanges played; + readonly attribute TimeRanges seekable; + readonly attribute boolean ended; + [CEReactions] attribute boolean autoplay; + [CEReactions] attribute boolean loop; + Promise play(); + void pause(); + + // controls + [CEReactions] attribute boolean controls; + attribute double volume; + attribute boolean muted; + [CEReactions] attribute boolean defaultMuted; + + // tracks + [SameObject] readonly attribute AudioTrackList audioTracks; + [SameObject] readonly attribute VideoTrackList videoTracks; + [SameObject] readonly attribute TextTrackList textTracks; + TextTrack addTextTrack(TextTrackKind kind, optional DOMString label = "", optional DOMString language = ""); +}; + +[Exposed=Window] +interface MediaError { + const unsigned short MEDIA_ERR_ABORTED = 1; + const unsigned short MEDIA_ERR_NETWORK = 2; + const unsigned short MEDIA_ERR_DECODE = 3; + const unsigned short MEDIA_ERR_SRC_NOT_SUPPORTED = 4; + + readonly attribute unsigned short code; + readonly attribute DOMString message; +}; + +[Exposed=Window] +interface AudioTrackList : EventTarget { + readonly attribute unsigned long length; + getter AudioTrack (unsigned long index); + AudioTrack? getTrackById(DOMString id); + + attribute EventHandler onchange; + attribute EventHandler onaddtrack; + attribute EventHandler onremovetrack; +}; + +[Exposed=Window] +interface AudioTrack { + readonly attribute DOMString id; + readonly attribute DOMString kind; + readonly attribute DOMString label; + readonly attribute DOMString language; + attribute boolean enabled; +}; + +[Exposed=Window] +interface VideoTrackList : EventTarget { + readonly attribute unsigned long length; + getter VideoTrack (unsigned long index); + VideoTrack? getTrackById(DOMString id); + readonly attribute long selectedIndex; + + attribute EventHandler onchange; + attribute EventHandler onaddtrack; + attribute EventHandler onremovetrack; +}; + +[Exposed=Window] +interface VideoTrack { + readonly attribute DOMString id; + readonly attribute DOMString kind; + readonly attribute DOMString label; + readonly attribute DOMString language; + attribute boolean selected; +}; + +[Exposed=Window] +interface TextTrackList : EventTarget { + readonly attribute unsigned long length; + getter TextTrack (unsigned long index); + TextTrack? getTrackById(DOMString id); + + attribute EventHandler onchange; + attribute EventHandler onaddtrack; + attribute EventHandler onremovetrack; +}; + +enum TextTrackMode { "disabled", "hidden", "showing" }; +enum TextTrackKind { "subtitles", "captions", "descriptions", "chapters", "metadata" }; + +[Exposed=Window] +interface TextTrack : EventTarget { + readonly attribute TextTrackKind kind; + readonly attribute DOMString label; + readonly attribute DOMString language; + + readonly attribute DOMString id; + readonly attribute DOMString inBandMetadataTrackDispatchType; + + attribute TextTrackMode mode; + + readonly attribute TextTrackCueList? cues; + readonly attribute TextTrackCueList? activeCues; + + void addCue(TextTrackCue cue); + void removeCue(TextTrackCue cue); + + attribute EventHandler oncuechange; +}; + +[Exposed=Window] +interface TextTrackCueList { + readonly attribute unsigned long length; + getter TextTrackCue (unsigned long index); + TextTrackCue? getCueById(DOMString id); +}; + +[Exposed=Window] +interface TextTrackCue : EventTarget { + readonly attribute TextTrack? track; + + attribute DOMString id; + attribute double startTime; + attribute double endTime; + attribute boolean pauseOnExit; + + attribute EventHandler onenter; + attribute EventHandler onexit; +}; + +[Exposed=Window] +interface TimeRanges { + readonly attribute unsigned long length; + double start(unsigned long index); + double end(unsigned long index); +}; + +[Exposed=Window, + Constructor(DOMString type, optional TrackEventInit eventInitDict = {})] +interface TrackEvent : Event { + readonly attribute (VideoTrack or AudioTrack or TextTrack)? track; +}; + +dictionary TrackEventInit : EventInit { + (VideoTrack or AudioTrack or TextTrack)? track = null; +}; + +[Exposed=Window] +interface HTMLMapElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute DOMString name; + [SameObject] readonly attribute HTMLCollection areas; +}; + +[Exposed=Window] +interface HTMLAreaElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute DOMString alt; + [CEReactions] attribute DOMString coords; + [CEReactions] attribute DOMString shape; + [CEReactions] attribute DOMString target; + [CEReactions] attribute DOMString download; + [CEReactions] attribute USVString ping; + [CEReactions] attribute DOMString rel; + [SameObject, PutForwards=value] readonly attribute DOMTokenList relList; + [CEReactions] attribute DOMString referrerPolicy; +}; +HTMLAreaElement includes HTMLHyperlinkElementUtils; + +[Exposed=Window] +interface HTMLTableElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute HTMLTableCaptionElement? caption; + HTMLTableCaptionElement createCaption(); + [CEReactions] void deleteCaption(); + + [CEReactions] attribute HTMLTableSectionElement? tHead; + HTMLTableSectionElement createTHead(); + [CEReactions] void deleteTHead(); + + [CEReactions] attribute HTMLTableSectionElement? tFoot; + HTMLTableSectionElement createTFoot(); + [CEReactions] void deleteTFoot(); + + [SameObject] readonly attribute HTMLCollection tBodies; + HTMLTableSectionElement createTBody(); + + [SameObject] readonly attribute HTMLCollection rows; + HTMLTableRowElement insertRow(optional long index = -1); + [CEReactions] void deleteRow(long index); +}; + +[Exposed=Window] +interface HTMLTableCaptionElement : HTMLElement { + [HTMLConstructor] constructor(); +}; + +[Exposed=Window] +interface HTMLTableColElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute unsigned long span; +}; + +[Exposed=Window] +interface HTMLTableSectionElement : HTMLElement { + [HTMLConstructor] constructor(); + + [SameObject] readonly attribute HTMLCollection rows; + HTMLTableRowElement insertRow(optional long index = -1); + [CEReactions] void deleteRow(long index); +}; + +[Exposed=Window] +interface HTMLTableRowElement : HTMLElement { + [HTMLConstructor] constructor(); + + readonly attribute long rowIndex; + readonly attribute long sectionRowIndex; + [SameObject] readonly attribute HTMLCollection cells; + HTMLTableCellElement insertCell(optional long index = -1); + [CEReactions] void deleteCell(long index); +}; + +[Exposed=Window] +interface HTMLTableCellElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute unsigned long colSpan; + [CEReactions] attribute unsigned long rowSpan; + [CEReactions] attribute DOMString headers; + readonly attribute long cellIndex; + + [CEReactions] attribute DOMString scope; // only conforming for th elements + [CEReactions] attribute DOMString abbr; // only conforming for th elements +}; + +[Exposed=Window, + LegacyOverrideBuiltIns, + LegacyUnenumerableNamedProperties] +interface HTMLFormElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute DOMString acceptCharset; + [CEReactions] attribute USVString action; + [CEReactions] attribute DOMString autocomplete; + [CEReactions] attribute DOMString enctype; + [CEReactions] attribute DOMString encoding; + [CEReactions] attribute DOMString method; + [CEReactions] attribute DOMString name; + [CEReactions] attribute boolean noValidate; + [CEReactions] attribute DOMString target; + [CEReactions] attribute DOMString rel; + [SameObject, PutForwards=value] readonly attribute DOMTokenList relList; + + [SameObject] readonly attribute HTMLFormControlsCollection elements; + readonly attribute unsigned long length; + getter Element (unsigned long index); + getter (RadioNodeList or Element) (DOMString name); + + void submit(); + void requestSubmit(optional HTMLElement? submitter = null); + [CEReactions] void reset(); + boolean checkValidity(); + boolean reportValidity(); +}; + +[Exposed=Window] +interface HTMLLabelElement : HTMLElement { + [HTMLConstructor] constructor(); + + readonly attribute HTMLFormElement? form; + [CEReactions] attribute DOMString htmlFor; + readonly attribute HTMLElement? control; +}; + +[Exposed=Window] +interface HTMLInputElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute DOMString accept; + [CEReactions] attribute DOMString alt; + [CEReactions] attribute DOMString autocomplete; + [CEReactions] attribute boolean defaultChecked; + attribute boolean checked; + [CEReactions] attribute DOMString dirName; + [CEReactions] attribute boolean disabled; + readonly attribute HTMLFormElement? form; + attribute FileList? files; + [CEReactions] attribute USVString formAction; + [CEReactions] attribute DOMString formEnctype; + [CEReactions] attribute DOMString formMethod; + [CEReactions] attribute boolean formNoValidate; + [CEReactions] attribute DOMString formTarget; + [CEReactions] attribute unsigned long height; + attribute boolean indeterminate; + readonly attribute HTMLElement? list; + [CEReactions] attribute DOMString max; + [CEReactions] attribute long maxLength; + [CEReactions] attribute DOMString min; + [CEReactions] attribute long minLength; + [CEReactions] attribute boolean multiple; + [CEReactions] attribute DOMString name; + [CEReactions] attribute DOMString pattern; + [CEReactions] attribute DOMString placeholder; + [CEReactions] attribute boolean readOnly; + [CEReactions] attribute boolean required; + [CEReactions] attribute unsigned long size; + [CEReactions] attribute USVString src; + [CEReactions] attribute DOMString step; + [CEReactions] attribute DOMString type; + [CEReactions] attribute DOMString defaultValue; + [CEReactions] attribute [LegacyNullToEmptyString] DOMString value; + attribute object? valueAsDate; + attribute unrestricted double valueAsNumber; + [CEReactions] attribute unsigned long width; + + void stepUp(optional long n = 1); + void stepDown(optional long n = 1); + + readonly attribute boolean willValidate; + readonly attribute ValidityState validity; + readonly attribute DOMString validationMessage; + boolean checkValidity(); + boolean reportValidity(); + void setCustomValidity(DOMString error); + + readonly attribute NodeList? labels; + + void select(); + attribute unsigned long? selectionStart; + attribute unsigned long? selectionEnd; + attribute DOMString? selectionDirection; + void setRangeText(DOMString replacement); + void setRangeText(DOMString replacement, unsigned long start, unsigned long end, optional SelectionMode selectionMode = "preserve"); + void setSelectionRange(unsigned long start, unsigned long end, optional DOMString direction); +}; + +[Exposed=Window] +interface HTMLButtonElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute boolean disabled; + readonly attribute HTMLFormElement? form; + [CEReactions] attribute USVString formAction; + [CEReactions] attribute DOMString formEnctype; + [CEReactions] attribute DOMString formMethod; + [CEReactions] attribute boolean formNoValidate; + [CEReactions] attribute DOMString formTarget; + [CEReactions] attribute DOMString name; + [CEReactions] attribute DOMString type; + [CEReactions] attribute DOMString value; + + readonly attribute boolean willValidate; + readonly attribute ValidityState validity; + readonly attribute DOMString validationMessage; + boolean checkValidity(); + boolean reportValidity(); + void setCustomValidity(DOMString error); + + readonly attribute NodeList labels; +}; + +[Exposed=Window] +interface HTMLSelectElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute DOMString autocomplete; + [CEReactions] attribute boolean disabled; + readonly attribute HTMLFormElement? form; + [CEReactions] attribute boolean multiple; + [CEReactions] attribute DOMString name; + [CEReactions] attribute boolean required; + [CEReactions] attribute unsigned long size; + + readonly attribute DOMString type; + + [SameObject] readonly attribute HTMLOptionsCollection options; + [CEReactions] attribute unsigned long length; + getter Element? item(unsigned long index); + HTMLOptionElement? namedItem(DOMString name); + [CEReactions] void add((HTMLOptionElement or HTMLOptGroupElement) element, optional (HTMLElement or long)? before = null); + [CEReactions] void remove(); // ChildNode overload + [CEReactions] void remove(long index); + [CEReactions] setter void (unsigned long index, HTMLOptionElement? option); + + [SameObject] readonly attribute HTMLCollection selectedOptions; + attribute long selectedIndex; + attribute DOMString value; + + readonly attribute boolean willValidate; + readonly attribute ValidityState validity; + readonly attribute DOMString validationMessage; + boolean checkValidity(); + boolean reportValidity(); + void setCustomValidity(DOMString error); + + readonly attribute NodeList labels; +}; + +[Exposed=Window] +interface HTMLDataListElement : HTMLElement { + [HTMLConstructor] constructor(); + + [SameObject] readonly attribute HTMLCollection options; +}; + +[Exposed=Window] +interface HTMLOptGroupElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute boolean disabled; + [CEReactions] attribute DOMString label; +}; + +[Exposed=Window, + LegacyFactoryFunction=Option(optional DOMString text = "", optional DOMString value, optional boolean defaultSelected = false, optional boolean selected = false)] +interface HTMLOptionElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute boolean disabled; + readonly attribute HTMLFormElement? form; + [CEReactions] attribute DOMString label; + [CEReactions] attribute boolean defaultSelected; + attribute boolean selected; + [CEReactions] attribute DOMString value; + + [CEReactions] attribute DOMString text; + readonly attribute long index; +}; + +[Exposed=Window] +interface HTMLTextAreaElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute DOMString autocomplete; + [CEReactions] attribute unsigned long cols; + [CEReactions] attribute DOMString dirName; + [CEReactions] attribute boolean disabled; + readonly attribute HTMLFormElement? form; + [CEReactions] attribute long maxLength; + [CEReactions] attribute long minLength; + [CEReactions] attribute DOMString name; + [CEReactions] attribute DOMString placeholder; + [CEReactions] attribute boolean readOnly; + [CEReactions] attribute boolean required; + [CEReactions] attribute unsigned long rows; + [CEReactions] attribute DOMString wrap; + + readonly attribute DOMString type; + [CEReactions] attribute DOMString defaultValue; + attribute [LegacyNullToEmptyString] DOMString value; + readonly attribute unsigned long textLength; + + readonly attribute boolean willValidate; + readonly attribute ValidityState validity; + readonly attribute DOMString validationMessage; + boolean checkValidity(); + boolean reportValidity(); + void setCustomValidity(DOMString error); + + readonly attribute NodeList labels; + + void select(); + attribute unsigned long selectionStart; + attribute unsigned long selectionEnd; + attribute DOMString selectionDirection; + void setRangeText(DOMString replacement); + void setRangeText(DOMString replacement, unsigned long start, unsigned long end, optional SelectionMode selectionMode = "preserve"); + void setSelectionRange(unsigned long start, unsigned long end, optional DOMString direction); +}; + +[Exposed=Window] +interface HTMLOutputElement : HTMLElement { + [HTMLConstructor] constructor(); + + [SameObject, PutForwards=value] readonly attribute DOMTokenList htmlFor; + readonly attribute HTMLFormElement? form; + [CEReactions] attribute DOMString name; + + readonly attribute DOMString type; + [CEReactions] attribute DOMString defaultValue; + [CEReactions] attribute DOMString value; + + readonly attribute boolean willValidate; + readonly attribute ValidityState validity; + readonly attribute DOMString validationMessage; + boolean checkValidity(); + boolean reportValidity(); + void setCustomValidity(DOMString error); + + readonly attribute NodeList labels; +}; + +[Exposed=Window] +interface HTMLProgressElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute double value; + [CEReactions] attribute double max; + readonly attribute double position; + readonly attribute NodeList labels; +}; + +[Exposed=Window] +interface HTMLMeterElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute double value; + [CEReactions] attribute double min; + [CEReactions] attribute double max; + [CEReactions] attribute double low; + [CEReactions] attribute double high; + [CEReactions] attribute double optimum; + readonly attribute NodeList labels; +}; + +[Exposed=Window] +interface HTMLFieldSetElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute boolean disabled; + readonly attribute HTMLFormElement? form; + [CEReactions] attribute DOMString name; + + readonly attribute DOMString type; + + [SameObject] readonly attribute HTMLCollection elements; + + readonly attribute boolean willValidate; + [SameObject] readonly attribute ValidityState validity; + readonly attribute DOMString validationMessage; + boolean checkValidity(); + boolean reportValidity(); + void setCustomValidity(DOMString error); +}; + +[Exposed=Window] +interface HTMLLegendElement : HTMLElement { + [HTMLConstructor] constructor(); + + readonly attribute HTMLFormElement? form; +}; + +enum SelectionMode { + "select", + "start", + "end", + "preserve" // default +}; + +[Exposed=Window] +interface ValidityState { + readonly attribute boolean valueMissing; + readonly attribute boolean typeMismatch; + readonly attribute boolean patternMismatch; + readonly attribute boolean tooLong; + readonly attribute boolean tooShort; + readonly attribute boolean rangeUnderflow; + readonly attribute boolean rangeOverflow; + readonly attribute boolean stepMismatch; + readonly attribute boolean badInput; + readonly attribute boolean customError; + readonly attribute boolean valid; +}; + +[Exposed=Window] +interface SubmitEvent : Event { + constructor(DOMString type, optional SubmitEventInit eventInitDict = {}); + + readonly attribute HTMLElement? submitter; +}; + +dictionary SubmitEventInit : EventInit { + HTMLElement? submitter = null; +}; + +[Exposed=Window] +interface FormDataEvent : Event { + constructor(DOMString type, FormDataEventInit eventInitDict); + + readonly attribute FormData formData; +}; + +dictionary FormDataEventInit : EventInit { + required FormData formData; +}; + +[Exposed=Window] +interface HTMLDetailsElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute boolean open; +}; + +[Exposed=Window] +interface HTMLDialogElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute boolean open; + attribute DOMString returnValue; + [CEReactions] void show(); + [CEReactions] void showModal(); + [CEReactions] void close(optional DOMString returnValue); +}; + +[Exposed=Window] +interface HTMLScriptElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute USVString src; + [CEReactions] attribute DOMString type; + [CEReactions] attribute boolean noModule; + [CEReactions] attribute boolean async; + [CEReactions] attribute boolean defer; + [CEReactions] attribute DOMString? crossOrigin; + [CEReactions] attribute DOMString text; + [CEReactions] attribute DOMString integrity; + [CEReactions] attribute DOMString referrerPolicy; + +}; + +[Exposed=Window] +interface HTMLTemplateElement : HTMLElement { + [HTMLConstructor] constructor(); + + readonly attribute DocumentFragment content; +}; + +[Exposed=Window] +interface HTMLSlotElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute DOMString name; + sequence assignedNodes(optional AssignedNodesOptions options = {}); + sequence assignedElements(optional AssignedNodesOptions options = {}); +}; + +dictionary AssignedNodesOptions { + boolean flatten = false; +}; + +typedef (CanvasRenderingContext2D or ImageBitmapRenderingContext or WebGLRenderingContext or WebGL2RenderingContext) RenderingContext; + +[Exposed=Window] +interface HTMLCanvasElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute unsigned long width; + [CEReactions] attribute unsigned long height; + + RenderingContext? getContext(DOMString contextId, optional any options = null); + + USVString toDataURL(optional DOMString type = "image/png", optional any quality); + void toBlob(BlobCallback _callback, optional DOMString type = "image/png", optional any quality); + OffscreenCanvas transferControlToOffscreen(); +}; + +callback BlobCallback = void (Blob? blob); + +typedef (HTMLImageElement or + SVGImageElement) HTMLOrSVGImageElement; + +typedef (HTMLOrSVGImageElement or + HTMLVideoElement or + HTMLCanvasElement or + ImageBitmap or + OffscreenCanvas) CanvasImageSource; + +enum CanvasFillRule { "nonzero", "evenodd" }; + +dictionary CanvasRenderingContext2DSettings { + boolean alpha = true; + boolean desynchronized = false; +}; + +enum ImageSmoothingQuality { "low", "medium", "high" }; + +[Exposed=Window] +interface CanvasRenderingContext2D { + // back-reference to the canvas + readonly attribute HTMLCanvasElement canvas; + + CanvasRenderingContext2DSettings getContextAttributes(); +}; +CanvasRenderingContext2D includes CanvasState; +CanvasRenderingContext2D includes CanvasTransform; +CanvasRenderingContext2D includes CanvasCompositing; +CanvasRenderingContext2D includes CanvasImageSmoothing; +CanvasRenderingContext2D includes CanvasFillStrokeStyles; +CanvasRenderingContext2D includes CanvasShadowStyles; +CanvasRenderingContext2D includes CanvasFilters; +CanvasRenderingContext2D includes CanvasRect; +CanvasRenderingContext2D includes CanvasDrawPath; +CanvasRenderingContext2D includes CanvasUserInterface; +CanvasRenderingContext2D includes CanvasText; +CanvasRenderingContext2D includes CanvasDrawImage; +CanvasRenderingContext2D includes CanvasImageData; +CanvasRenderingContext2D includes CanvasPathDrawingStyles; +CanvasRenderingContext2D includes CanvasTextDrawingStyles; +CanvasRenderingContext2D includes CanvasPath; + +interface mixin CanvasState { + // state + void save(); // push state on state stack + void restore(); // pop state stack and restore state +}; + +interface mixin CanvasTransform { + // transformations (default transform is the identity matrix) + void scale(unrestricted double x, unrestricted double y); + void rotate(unrestricted double angle); + void translate(unrestricted double x, unrestricted double y); + void transform(unrestricted double a, unrestricted double b, unrestricted double c, unrestricted double d, unrestricted double e, unrestricted double f); + + [NewObject] DOMMatrix getTransform(); + void setTransform(unrestricted double a, unrestricted double b, unrestricted double c, unrestricted double d, unrestricted double e, unrestricted double f); + void setTransform(optional DOMMatrix2DInit transform = {}); + void resetTransform(); + +}; + +interface mixin CanvasCompositing { + // compositing + attribute unrestricted double globalAlpha; // (default 1.0) + attribute DOMString globalCompositeOperation; // (default source-over) +}; + +interface mixin CanvasImageSmoothing { + // image smoothing + attribute boolean imageSmoothingEnabled; // (default true) + attribute ImageSmoothingQuality imageSmoothingQuality; // (default low) + +}; + +interface mixin CanvasFillStrokeStyles { + // colors and styles (see also the CanvasPathDrawingStyles and CanvasTextDrawingStyles interfaces) + attribute (DOMString or CanvasGradient or CanvasPattern) strokeStyle; // (default black) + attribute (DOMString or CanvasGradient or CanvasPattern) fillStyle; // (default black) + CanvasGradient createLinearGradient(double x0, double y0, double x1, double y1); + CanvasGradient createRadialGradient(double x0, double y0, double r0, double x1, double y1, double r1); + CanvasPattern? createPattern(CanvasImageSource image, [LegacyNullToEmptyString] DOMString repetition); + +}; + +interface mixin CanvasShadowStyles { + // shadows + attribute unrestricted double shadowOffsetX; // (default 0) + attribute unrestricted double shadowOffsetY; // (default 0) + attribute unrestricted double shadowBlur; // (default 0) + attribute DOMString shadowColor; // (default transparent black) +}; + +interface mixin CanvasFilters { + // filters + attribute DOMString filter; // (default "none") +}; + +interface mixin CanvasRect { + // rects + void clearRect(unrestricted double x, unrestricted double y, unrestricted double w, unrestricted double h); + void fillRect(unrestricted double x, unrestricted double y, unrestricted double w, unrestricted double h); + void strokeRect(unrestricted double x, unrestricted double y, unrestricted double w, unrestricted double h); +}; + +interface mixin CanvasDrawPath { + // path API (see also CanvasPath) + void beginPath(); + void fill(optional CanvasFillRule fillRule = "nonzero"); + void fill(Path2D path, optional CanvasFillRule fillRule = "nonzero"); + void stroke(); + void stroke(Path2D path); + void clip(optional CanvasFillRule fillRule = "nonzero"); + void clip(Path2D path, optional CanvasFillRule fillRule = "nonzero"); + boolean isPointInPath(unrestricted double x, unrestricted double y, optional CanvasFillRule fillRule = "nonzero"); + boolean isPointInPath(Path2D path, unrestricted double x, unrestricted double y, optional CanvasFillRule fillRule = "nonzero"); + boolean isPointInStroke(unrestricted double x, unrestricted double y); + boolean isPointInStroke(Path2D path, unrestricted double x, unrestricted double y); +}; + +interface mixin CanvasUserInterface { + void drawFocusIfNeeded(Element element); + void drawFocusIfNeeded(Path2D path, Element element); + void scrollPathIntoView(); + void scrollPathIntoView(Path2D path); +}; + +interface mixin CanvasText { + // text (see also the CanvasPathDrawingStyles and CanvasTextDrawingStyles interfaces) + void fillText(DOMString text, unrestricted double x, unrestricted double y, optional unrestricted double maxWidth); + void strokeText(DOMString text, unrestricted double x, unrestricted double y, optional unrestricted double maxWidth); + TextMetrics measureText(DOMString text); +}; + +interface mixin CanvasDrawImage { + // drawing images + void drawImage(CanvasImageSource image, unrestricted double dx, unrestricted double dy); + void drawImage(CanvasImageSource image, unrestricted double dx, unrestricted double dy, unrestricted double dw, unrestricted double dh); + void drawImage(CanvasImageSource image, unrestricted double sx, unrestricted double sy, unrestricted double sw, unrestricted double sh, unrestricted double dx, unrestricted double dy, unrestricted double dw, unrestricted double dh); +}; + +interface mixin CanvasImageData { + // pixel manipulation + ImageData createImageData(long sw, long sh); + ImageData createImageData(ImageData imagedata); + ImageData getImageData(long sx, long sy, long sw, long sh); + void putImageData(ImageData imagedata, long dx, long dy); + void putImageData(ImageData imagedata, long dx, long dy, long dirtyX, long dirtyY, long dirtyWidth, long dirtyHeight); +}; + +enum CanvasLineCap { "butt", "round", "square" }; +enum CanvasLineJoin { "round", "bevel", "miter" }; +enum CanvasTextAlign { "start", "end", "left", "right", "center" }; +enum CanvasTextBaseline { "top", "hanging", "middle", "alphabetic", "ideographic", "bottom" }; +enum CanvasDirection { "ltr", "rtl", "inherit" }; + +interface mixin CanvasPathDrawingStyles { + // line caps/joins + attribute unrestricted double lineWidth; // (default 1) + attribute CanvasLineCap lineCap; // (default "butt") + attribute CanvasLineJoin lineJoin; // (default "miter") + attribute unrestricted double miterLimit; // (default 10) + + // dashed lines + void setLineDash(sequence segments); // default empty + sequence getLineDash(); + attribute unrestricted double lineDashOffset; +}; + +interface mixin CanvasTextDrawingStyles { + // text + attribute DOMString font; // (default 10px sans-serif) + attribute CanvasTextAlign textAlign; // (default: "start") + attribute CanvasTextBaseline textBaseline; // (default: "alphabetic") + attribute CanvasDirection direction; // (default: "inherit") +}; + +interface mixin CanvasPath { + // shared path API methods + void closePath(); + void moveTo(unrestricted double x, unrestricted double y); + void lineTo(unrestricted double x, unrestricted double y); + void quadraticCurveTo(unrestricted double cpx, unrestricted double cpy, unrestricted double x, unrestricted double y); + void bezierCurveTo(unrestricted double cp1x, unrestricted double cp1y, unrestricted double cp2x, unrestricted double cp2y, unrestricted double x, unrestricted double y); + void arcTo(unrestricted double x1, unrestricted double y1, unrestricted double x2, unrestricted double y2, unrestricted double radius); + void rect(unrestricted double x, unrestricted double y, unrestricted double w, unrestricted double h); + void arc(unrestricted double x, unrestricted double y, unrestricted double radius, unrestricted double startAngle, unrestricted double endAngle, optional boolean anticlockwise = false); + void ellipse(unrestricted double x, unrestricted double y, unrestricted double radiusX, unrestricted double radiusY, unrestricted double rotation, unrestricted double startAngle, unrestricted double endAngle, optional boolean anticlockwise = false); +}; + +[Exposed=(Window,Worker)] +interface CanvasGradient { + // opaque object + void addColorStop(double offset, DOMString color); +}; + +[Exposed=(Window,Worker)] +interface CanvasPattern { + // opaque object + void setTransform(optional DOMMatrix2DInit transform = {}); +}; + +[Exposed=(Window,Worker)] +interface TextMetrics { + // x-direction + readonly attribute double width; // advance width + readonly attribute double actualBoundingBoxLeft; + readonly attribute double actualBoundingBoxRight; + + // y-direction + readonly attribute double fontBoundingBoxAscent; + readonly attribute double fontBoundingBoxDescent; + readonly attribute double actualBoundingBoxAscent; + readonly attribute double actualBoundingBoxDescent; + readonly attribute double emHeightAscent; + readonly attribute double emHeightDescent; + readonly attribute double hangingBaseline; + readonly attribute double alphabeticBaseline; + readonly attribute double ideographicBaseline; +}; + +[Exposed=(Window,Worker), + Serializable] +interface ImageData { + constructor(unsigned long sw, unsigned long sh); + constructor(Uint8ClampedArray data, unsigned long sw, optional unsigned long sh); + + readonly attribute unsigned long width; + readonly attribute unsigned long height; + readonly attribute Uint8ClampedArray data; +}; + +[Exposed=(Window,Worker)] +interface Path2D { + constructor(optional (Path2D or DOMString) path); + + void addPath(Path2D path, optional DOMMatrix2DInit transform = {}); +}; +Path2D includes CanvasPath; + +[Exposed=(Window,Worker)] +interface ImageBitmapRenderingContext { + readonly attribute (HTMLCanvasElement or OffscreenCanvas) canvas; + void transferFromImageBitmap(ImageBitmap? bitmap); +}; + +dictionary ImageBitmapRenderingContextSettings { + boolean alpha = true; +}; + +typedef (OffscreenCanvasRenderingContext2D or ImageBitmapRenderingContext or WebGLRenderingContext or WebGL2RenderingContext) OffscreenRenderingContext; + +dictionary ImageEncodeOptions { + DOMString type = "image/png"; + unrestricted double quality; +}; + +enum OffscreenRenderingContextId { "2d", "bitmaprenderer", "webgl", "webgl2" }; + +[Exposed=(Window,Worker), Transferable] +interface OffscreenCanvas : EventTarget { + constructor([EnforceRange] unsigned long long width, [EnforceRange] unsigned long long height); + + attribute [EnforceRange] unsigned long long width; + attribute [EnforceRange] unsigned long long height; + + OffscreenRenderingContext? getContext(OffscreenRenderingContextId contextId, optional any options = null); + ImageBitmap transferToImageBitmap(); + Promise convertToBlob(optional ImageEncodeOptions options = {}); +}; + +[Exposed=(Window,Worker)] +interface OffscreenCanvasRenderingContext2D { + void commit(); + readonly attribute OffscreenCanvas canvas; +}; + +OffscreenCanvasRenderingContext2D includes CanvasState; +OffscreenCanvasRenderingContext2D includes CanvasTransform; +OffscreenCanvasRenderingContext2D includes CanvasCompositing; +OffscreenCanvasRenderingContext2D includes CanvasImageSmoothing; +OffscreenCanvasRenderingContext2D includes CanvasFillStrokeStyles; +OffscreenCanvasRenderingContext2D includes CanvasShadowStyles; +OffscreenCanvasRenderingContext2D includes CanvasFilters; +OffscreenCanvasRenderingContext2D includes CanvasRect; +OffscreenCanvasRenderingContext2D includes CanvasDrawPath; +OffscreenCanvasRenderingContext2D includes CanvasText; +OffscreenCanvasRenderingContext2D includes CanvasDrawImage; +OffscreenCanvasRenderingContext2D includes CanvasImageData; +OffscreenCanvasRenderingContext2D includes CanvasPathDrawingStyles; +OffscreenCanvasRenderingContext2D includes CanvasTextDrawingStyles; +OffscreenCanvasRenderingContext2D includes CanvasPath; + +[Exposed=Window] +interface CustomElementRegistry { + [CEReactions] void define(DOMString name, CustomElementConstructor constructor, optional ElementDefinitionOptions options = {}); + any get(DOMString name); + Promise whenDefined(DOMString name); + [CEReactions] void upgrade(Node root); +}; + +callback CustomElementConstructor = HTMLElement (); + +dictionary ElementDefinitionOptions { + DOMString extends; +}; + +[Exposed=Window] +interface ElementInternals { + // Form-associated custom elements + + void setFormValue((File or USVString or FormData)? value, + optional (File or USVString or FormData)? state); + + readonly attribute HTMLFormElement? form; + + void setValidity(optional ValidityStateFlags flags = {}, + optional DOMString message, + optional HTMLElement anchor); + readonly attribute boolean willValidate; + readonly attribute ValidityState validity; + readonly attribute DOMString validationMessage; + boolean checkValidity(); + boolean reportValidity(); + + readonly attribute NodeList labels; +}; + +dictionary ValidityStateFlags { + boolean valueMissing = false; + boolean typeMismatch = false; + boolean patternMismatch = false; + boolean tooLong = false; + boolean tooShort = false; + boolean rangeUnderflow = false; + boolean rangeOverflow = false; + boolean stepMismatch = false; + boolean badInput = false; + boolean customError = false; +}; + +dictionary FocusOptions { + boolean preventScroll = false; +}; + +interface mixin ElementContentEditable { + [CEReactions] attribute DOMString contentEditable; + [CEReactions] attribute DOMString enterKeyHint; + readonly attribute boolean isContentEditable; + [CEReactions] attribute DOMString inputMode; +}; + +[Exposed=Window, + Constructor] +interface DataTransfer { + attribute DOMString dropEffect; + attribute DOMString effectAllowed; + + [SameObject] readonly attribute DataTransferItemList items; + + void setDragImage(Element image, long x, long y); + + /* old interface */ + readonly attribute FrozenArray types; + DOMString getData(DOMString format); + void setData(DOMString format, DOMString data); + void clearData(optional DOMString format); + [SameObject] readonly attribute FileList files; +}; + +[Exposed=Window] +interface DataTransferItemList { + readonly attribute unsigned long length; + getter DataTransferItem (unsigned long index); + DataTransferItem? add(DOMString data, DOMString type); + DataTransferItem? add(File data); + void remove(unsigned long index); + void clear(); +}; + +[Exposed=Window] +interface DataTransferItem { + readonly attribute DOMString kind; + readonly attribute DOMString type; + void getAsString(FunctionStringCallback? _callback); + File? getAsFile(); +}; + +callback FunctionStringCallback = void (DOMString data); + +[Exposed=Window, + Constructor(DOMString type, optional DragEventInit eventInitDict = {})] +interface DragEvent : MouseEvent { + readonly attribute DataTransfer? dataTransfer; +}; + +dictionary DragEventInit : MouseEventInit { + DataTransfer? dataTransfer = null; +}; + +[Global=Window, + Exposed=Window, + LegacyUnenumerableNamedProperties] +interface Window : EventTarget { + // the current browsing context + [LegacyUnforgeable] readonly attribute WindowProxy window; + [Replaceable] readonly attribute WindowProxy self; + [LegacyUnforgeable] readonly attribute Document document; + attribute DOMString name; + [PutForwards=href, LegacyUnforgeable] readonly attribute Location location; + readonly attribute History history; + readonly attribute CustomElementRegistry customElements; + [Replaceable] readonly attribute BarProp locationbar; + [Replaceable] readonly attribute BarProp menubar; + [Replaceable] readonly attribute BarProp personalbar; + [Replaceable] readonly attribute BarProp scrollbars; + [Replaceable] readonly attribute BarProp statusbar; + [Replaceable] readonly attribute BarProp toolbar; + attribute DOMString status; + void close(); + readonly attribute boolean closed; + void stop(); + void focus(); + void blur(); + + // other browsing contexts + [Replaceable] readonly attribute WindowProxy frames; + [Replaceable] readonly attribute unsigned long length; + [LegacyUnforgeable] readonly attribute WindowProxy? top; + attribute any opener; + [Replaceable] readonly attribute WindowProxy? parent; + readonly attribute Element? frameElement; + WindowProxy? open(optional USVString url = "", optional DOMString target = "_blank", optional [LegacyNullToEmptyString] DOMString features = ""); + getter object (DOMString name); + // Since this is the global object, the IDL named getter adds a NamedPropertiesObject exotic + // object on the prototype chain. Indeed, this does not make the global object an exotic object. + // Indexed access is taken care of by the WindowProxy exotic object. + + // the user agent + readonly attribute Navigator navigator; + [SecureContext] readonly attribute ApplicationCache applicationCache; + + // user prompts + void alert(); + void alert(DOMString message); + boolean confirm(optional DOMString message = ""); + DOMString? prompt(optional DOMString message = "", optional DOMString default = ""); + void print(); + + void postMessage(any message, USVString targetOrigin, optional sequence transfer = []); + void postMessage(any message, optional WindowPostMessageOptions options = {}); +}; +Window includes GlobalEventHandlers; +Window includes WindowEventHandlers; + +dictionary WindowPostMessageOptions : PostMessageOptions { + USVString targetOrigin = "/"; +}; + +[Exposed=Window] +interface BarProp { + readonly attribute boolean visible; +}; + +enum ScrollRestoration { "auto", "manual" }; + +[Exposed=Window] +interface History { + readonly attribute unsigned long length; + attribute ScrollRestoration scrollRestoration; + readonly attribute any state; + void go(optional long delta = 0); + void back(); + void forward(); + void pushState(any data, DOMString title, optional USVString? url = null); + void replaceState(any data, DOMString title, optional USVString? url = null); +}; + +[Exposed=Window] +interface Location { // but see also additional creation steps and overridden internal methods + [LegacyUnforgeable] stringifier attribute USVString href; + [LegacyUnforgeable] readonly attribute USVString origin; + [LegacyUnforgeable] attribute USVString protocol; + [LegacyUnforgeable] attribute USVString host; + [LegacyUnforgeable] attribute USVString hostname; + [LegacyUnforgeable] attribute USVString port; + [LegacyUnforgeable] attribute USVString pathname; + [LegacyUnforgeable] attribute USVString search; + [LegacyUnforgeable] attribute USVString hash; + + [LegacyUnforgeable] void assign(USVString url); + [LegacyUnforgeable] void replace(USVString url); + [LegacyUnforgeable] void reload(); + + [LegacyUnforgeable, SameObject] readonly attribute DOMStringList ancestorOrigins; +}; + +[Exposed=Window, + Constructor(DOMString type, optional PopStateEventInit eventInitDict = {})] +interface PopStateEvent : Event { + readonly attribute any state; +}; + +dictionary PopStateEventInit : EventInit { + any state = null; +}; + +[Exposed=Window, + Constructor(DOMString type, optional HashChangeEventInit eventInitDict = {})] +interface HashChangeEvent : Event { + readonly attribute USVString oldURL; + readonly attribute USVString newURL; +}; + +dictionary HashChangeEventInit : EventInit { + USVString oldURL = ""; + USVString newURL = ""; +}; + +[Exposed=Window, + Constructor(DOMString type, optional PageTransitionEventInit eventInitDict = {})] +interface PageTransitionEvent : Event { + readonly attribute boolean persisted; +}; + +dictionary PageTransitionEventInit : EventInit { + boolean persisted = false; +}; + +[Exposed=Window] +interface BeforeUnloadEvent : Event { + attribute DOMString returnValue; +}; + +[SecureContext, + Exposed=Window] +interface ApplicationCache : EventTarget { + + // update status + const unsigned short UNCACHED = 0; + const unsigned short IDLE = 1; + const unsigned short CHECKING = 2; + const unsigned short DOWNLOADING = 3; + const unsigned short UPDATEREADY = 4; + const unsigned short OBSOLETE = 5; + readonly attribute unsigned short status; + + // updates + void update(); + void abort(); + void swapCache(); + + // events + attribute EventHandler onchecking; + attribute EventHandler onerror; + attribute EventHandler onnoupdate; + attribute EventHandler ondownloading; + attribute EventHandler onprogress; + attribute EventHandler onupdateready; + attribute EventHandler oncached; + attribute EventHandler onobsolete; +}; + +interface mixin NavigatorOnLine { + readonly attribute boolean onLine; +}; + +[Exposed=(Window,Worker)] +interface ErrorEvent : Event { + constructor(DOMString type, optional ErrorEventInit eventInitDict = {}); + + readonly attribute DOMString message; + readonly attribute USVString filename; + readonly attribute unsigned long lineno; + readonly attribute unsigned long colno; + readonly attribute any error; +}; + +dictionary ErrorEventInit : EventInit { + DOMString message = ""; + USVString filename = ""; + unsigned long lineno = 0; + unsigned long colno = 0; + any error = null; +}; + +[Exposed=(Window,Worker)] +interface PromiseRejectionEvent : Event { + constructor(DOMString type, PromiseRejectionEventInit eventInitDict); + + readonly attribute Promise promise; + readonly attribute any reason; +}; + +dictionary PromiseRejectionEventInit : EventInit { + required Promise promise; + any reason; +}; + +[LegacyTreatNonObjectAsNull] +callback EventHandlerNonNull = any (Event event); +typedef EventHandlerNonNull? EventHandler; + +[LegacyTreatNonObjectAsNull] +callback OnErrorEventHandlerNonNull = any ((Event or DOMString) event, optional DOMString source, optional unsigned long lineno, optional unsigned long colno, optional any error); +typedef OnErrorEventHandlerNonNull? OnErrorEventHandler; + +[LegacyTreatNonObjectAsNull] +callback OnBeforeUnloadEventHandlerNonNull = DOMString? (Event event); +typedef OnBeforeUnloadEventHandlerNonNull? OnBeforeUnloadEventHandler; + +interface mixin GlobalEventHandlers { + attribute EventHandler onabort; + attribute EventHandler onauxclick; + attribute EventHandler onblur; + attribute EventHandler oncancel; + attribute EventHandler oncanplay; + attribute EventHandler oncanplaythrough; + attribute EventHandler onchange; + attribute EventHandler onclick; + attribute EventHandler onclose; + attribute EventHandler oncontextmenu; + attribute EventHandler oncuechange; + attribute EventHandler ondblclick; + attribute EventHandler ondrag; + attribute EventHandler ondragend; + attribute EventHandler ondragenter; + attribute EventHandler ondragexit; + attribute EventHandler ondragleave; + attribute EventHandler ondragover; + attribute EventHandler ondragstart; + attribute EventHandler ondrop; + attribute EventHandler ondurationchange; + attribute EventHandler onemptied; + attribute EventHandler onended; + attribute OnErrorEventHandler onerror; + attribute EventHandler onfocus; + attribute EventHandler onformdata; + attribute EventHandler oninput; + attribute EventHandler oninvalid; + attribute EventHandler onkeydown; + attribute EventHandler onkeypress; + attribute EventHandler onkeyup; + attribute EventHandler onload; + attribute EventHandler onloadeddata; + attribute EventHandler onloadedmetadata; + attribute EventHandler onloadstart; + attribute EventHandler onmousedown; + [LegacyLenientThis] attribute EventHandler onmouseenter; + [LegacyLenientThis] attribute EventHandler onmouseleave; + attribute EventHandler onmousemove; + attribute EventHandler onmouseout; + attribute EventHandler onmouseover; + attribute EventHandler onmouseup; + attribute EventHandler onpause; + attribute EventHandler onplay; + attribute EventHandler onplaying; + attribute EventHandler onprogress; + attribute EventHandler onratechange; + attribute EventHandler onreset; + attribute EventHandler onresize; + attribute EventHandler onscroll; + attribute EventHandler onsecuritypolicyviolation; + attribute EventHandler onseeked; + attribute EventHandler onseeking; + attribute EventHandler onselect; + attribute EventHandler onslotchange; + attribute EventHandler onstalled; + attribute EventHandler onsubmit; + attribute EventHandler onsuspend; + attribute EventHandler ontimeupdate; + attribute EventHandler ontoggle; + attribute EventHandler onvolumechange; + attribute EventHandler onwaiting; + attribute EventHandler onwebkitanimationend; + attribute EventHandler onwebkitanimationiteration; + attribute EventHandler onwebkitanimationstart; + attribute EventHandler onwebkittransitionend; + attribute EventHandler onwheel; +}; + +interface mixin WindowEventHandlers { + attribute EventHandler onafterprint; + attribute EventHandler onbeforeprint; + attribute OnBeforeUnloadEventHandler onbeforeunload; + attribute EventHandler onhashchange; + attribute EventHandler onlanguagechange; + attribute EventHandler onmessage; + attribute EventHandler onmessageerror; + attribute EventHandler onoffline; + attribute EventHandler ononline; + attribute EventHandler onpagehide; + attribute EventHandler onpageshow; + attribute EventHandler onpopstate; + attribute EventHandler onrejectionhandled; + attribute EventHandler onstorage; + attribute EventHandler onunhandledrejection; + attribute EventHandler onunload; +}; + +interface mixin DocumentAndElementEventHandlers { + attribute EventHandler oncopy; + attribute EventHandler oncut; + attribute EventHandler onpaste; +}; + +typedef (DOMString or Function) TimerHandler; + +interface mixin WindowOrWorkerGlobalScope { + [Replaceable] readonly attribute USVString origin; + + // base64 utility methods + DOMString btoa(DOMString data); + ByteString atob(DOMString data); + + // timers + long setTimeout(TimerHandler handler, optional long timeout = 0, any... arguments); + void clearTimeout(optional long handle = 0); + long setInterval(TimerHandler handler, optional long timeout = 0, any... arguments); + void clearInterval(optional long handle = 0); + + // microtask queuing + void queueMicrotask(VoidFunction callback); + + // ImageBitmap + Promise createImageBitmap(ImageBitmapSource image, optional ImageBitmapOptions options = {}); + Promise createImageBitmap(ImageBitmapSource image, long sx, long sy, long sw, long sh, optional ImageBitmapOptions options = {}); +}; +Window includes WindowOrWorkerGlobalScope; +WorkerGlobalScope includes WindowOrWorkerGlobalScope; + +[Exposed=Window] +interface DOMParser { + constructor(); + + [NewObject] Document parseFromString(DOMString string, DOMParserSupportedType type); +}; + +enum DOMParserSupportedType { + "text/html", + "text/xml", + "application/xml", + "application/xhtml+xml", + "image/svg+xml" +}; + +[Exposed=Window] +interface Navigator { + // objects implementing this interface also implement the interfaces given below +}; +Navigator includes NavigatorID; +Navigator includes NavigatorLanguage; +Navigator includes NavigatorOnLine; +Navigator includes NavigatorContentUtils; +Navigator includes NavigatorCookies; +Navigator includes NavigatorPlugins; +Navigator includes NavigatorConcurrentHardware; + +interface mixin NavigatorID { + readonly attribute DOMString appCodeName; // constant "Mozilla" + readonly attribute DOMString appName; // constant "Netscape" + readonly attribute DOMString appVersion; + readonly attribute DOMString platform; + readonly attribute DOMString product; // constant "Gecko" + [Exposed=Window] readonly attribute DOMString productSub; + readonly attribute DOMString userAgent; + [Exposed=Window] readonly attribute DOMString vendor; + [Exposed=Window] readonly attribute DOMString vendorSub; // constant "" +}; + +partial interface mixin NavigatorID { + [Exposed=Window] boolean taintEnabled(); // constant false + [Exposed=Window] readonly attribute DOMString oscpu; +}; + +interface mixin NavigatorLanguage { + readonly attribute DOMString language; + readonly attribute FrozenArray languages; +}; + +interface mixin NavigatorContentUtils { + [SecureContext] void registerProtocolHandler(DOMString scheme, USVString url); + [SecureContext] void unregisterProtocolHandler(DOMString scheme, USVString url); +}; + +interface mixin NavigatorCookies { + readonly attribute boolean cookieEnabled; +}; + +interface mixin NavigatorPlugins { + [SameObject] readonly attribute PluginArray plugins; + [SameObject] readonly attribute MimeTypeArray mimeTypes; + boolean javaEnabled(); +}; + +[Exposed=Window, + LegacyUnenumerableNamedProperties] +interface PluginArray { + void refresh(optional boolean reload = false); + readonly attribute unsigned long length; + getter Plugin? item(unsigned long index); + getter Plugin? namedItem(DOMString name); +}; + +[Exposed=Window, + LegacyUnenumerableNamedProperties] +interface MimeTypeArray { + readonly attribute unsigned long length; + getter MimeType? item(unsigned long index); + getter MimeType? namedItem(DOMString name); +}; + +[Exposed=Window, + LegacyUnenumerableNamedProperties] +interface Plugin { + readonly attribute DOMString name; + readonly attribute DOMString description; + readonly attribute DOMString filename; + readonly attribute unsigned long length; + getter MimeType? item(unsigned long index); + getter MimeType? namedItem(DOMString name); +}; + +[Exposed=Window] +interface MimeType { + readonly attribute DOMString type; + readonly attribute DOMString description; + readonly attribute DOMString suffixes; // comma-separated + readonly attribute Plugin enabledPlugin; +}; + +[Exposed=(Window,Worker), Serializable, Transferable] +interface ImageBitmap { + readonly attribute unsigned long width; + readonly attribute unsigned long height; + void close(); +}; + +typedef (CanvasImageSource or + Blob or + ImageData) ImageBitmapSource; + +enum ImageOrientation { "none", "flipY" }; +enum PremultiplyAlpha { "none", "premultiply", "default" }; +enum ColorSpaceConversion { "none", "default" }; +enum ResizeQuality { "pixelated", "low", "medium", "high" }; + +dictionary ImageBitmapOptions { + ImageOrientation imageOrientation = "none"; + PremultiplyAlpha premultiplyAlpha = "default"; + ColorSpaceConversion colorSpaceConversion = "default"; + [EnforceRange] unsigned long resizeWidth; + [EnforceRange] unsigned long resizeHeight; + ResizeQuality resizeQuality = "low"; +}; + +callback FrameRequestCallback = void (DOMHighResTimeStamp time); + +interface mixin AnimationFrameProvider { + unsigned long requestAnimationFrame(FrameRequestCallback callback); + void cancelAnimationFrame(unsigned long handle); +}; +Window includes AnimationFrameProvider; +DedicatedWorkerGlobalScope includes AnimationFrameProvider; + +[Exposed=(Window,Worker,AudioWorklet)] +interface MessageEvent : Event { + constructor(DOMString type, optional MessageEventInit eventInitDict = {}); + + readonly attribute any data; + readonly attribute USVString origin; + readonly attribute DOMString lastEventId; + readonly attribute MessageEventSource? source; + readonly attribute FrozenArray ports; + + void initMessageEvent(DOMString type, optional boolean bubbles = false, optional boolean cancelable = false, optional any data = null, optional USVString origin = "", optional DOMString lastEventId = "", optional MessageEventSource? source = null, optional sequence ports = []); +}; + +dictionary MessageEventInit : EventInit { + any data = null; + USVString origin = ""; + DOMString lastEventId = ""; + MessageEventSource? source = null; + sequence ports = []; +}; + +typedef (WindowProxy or MessagePort or ServiceWorker) MessageEventSource; + +[Exposed=(Window,Worker)] +interface EventSource : EventTarget { + constructor(USVString url, optional EventSourceInit eventSourceInitDict = {}); + + readonly attribute USVString url; + readonly attribute boolean withCredentials; + + // ready state + const unsigned short CONNECTING = 0; + const unsigned short OPEN = 1; + const unsigned short CLOSED = 2; + readonly attribute unsigned short readyState; + + // networking + attribute EventHandler onopen; + attribute EventHandler onmessage; + attribute EventHandler onerror; + void close(); +}; + +dictionary EventSourceInit { + boolean withCredentials = false; +}; + +enum BinaryType { "blob", "arraybuffer" }; +[Exposed=(Window,Worker)] +interface WebSocket : EventTarget { + constructor(USVString url, optional (DOMString or sequence) protocols = []); + + readonly attribute USVString url; + + // ready state + const unsigned short CONNECTING = 0; + const unsigned short OPEN = 1; + const unsigned short CLOSING = 2; + const unsigned short CLOSED = 3; + readonly attribute unsigned short readyState; + readonly attribute unsigned long long bufferedAmount; + + // networking + attribute EventHandler onopen; + attribute EventHandler onerror; + attribute EventHandler onclose; + readonly attribute DOMString extensions; + readonly attribute DOMString protocol; + void close(optional [Clamp] unsigned short code, optional USVString reason); + + // messaging + attribute EventHandler onmessage; + attribute BinaryType binaryType; + void send(USVString data); + void send(Blob data); + void send(ArrayBuffer data); + void send(ArrayBufferView data); +}; + +[Exposed=(Window,Worker)] +interface CloseEvent : Event { + constructor(DOMString type, optional CloseEventInit eventInitDict = {}); + + readonly attribute boolean wasClean; + readonly attribute unsigned short code; + readonly attribute USVString reason; +}; + +dictionary CloseEventInit : EventInit { + boolean wasClean = false; + unsigned short code = 0; + USVString reason = ""; +}; + +[Constructor, Exposed=(Window,Worker)] +interface MessageChannel { + readonly attribute MessagePort port1; + readonly attribute MessagePort port2; +}; + +[Exposed=(Window,Worker,AudioWorklet), Transferable] +interface MessagePort : EventTarget { + void postMessage(any message, sequence transfer); + void postMessage(any message, optional PostMessageOptions options = {}); + void start(); + void close(); + + // event handlers + attribute EventHandler onmessage; + attribute EventHandler onmessageerror; +}; + +dictionary PostMessageOptions { + sequence transfer = []; +}; + +[Exposed=(Window,Worker)] +interface BroadcastChannel : EventTarget { + constructor(DOMString name); + + readonly attribute DOMString name; + void postMessage(any message); + void close(); + attribute EventHandler onmessage; + attribute EventHandler onmessageerror; +}; + +[Exposed=Worker] +interface WorkerGlobalScope : EventTarget { + readonly attribute WorkerGlobalScope self; + readonly attribute WorkerLocation location; + readonly attribute WorkerNavigator navigator; + void importScripts(USVString... urls); + + attribute OnErrorEventHandler onerror; + attribute EventHandler onlanguagechange; + attribute EventHandler onoffline; + attribute EventHandler ononline; + attribute EventHandler onrejectionhandled; + attribute EventHandler onunhandledrejection; +}; + +[Global=(Worker,DedicatedWorker),Exposed=DedicatedWorker] +interface DedicatedWorkerGlobalScope : WorkerGlobalScope { + [Replaceable] readonly attribute DOMString name; + + void postMessage(any message, sequence transfer); + void postMessage(any message, optional PostMessageOptions options = {}); + + void close(); + + attribute EventHandler onmessage; + attribute EventHandler onmessageerror; +}; + +[Global=(Worker,SharedWorker),Exposed=SharedWorker] +interface SharedWorkerGlobalScope : WorkerGlobalScope { + [Replaceable] readonly attribute DOMString name; + + void close(); + + attribute EventHandler onconnect; +}; + +interface mixin AbstractWorker { + attribute EventHandler onerror; +}; + +[Exposed=(Window,Worker)] +interface Worker : EventTarget { + constructor(USVString scriptURL, optional WorkerOptions options = {}); + + void terminate(); + + void postMessage(any message, sequence transfer); + void postMessage(any message, optional PostMessageOptions options = {}); + attribute EventHandler onmessage; + attribute EventHandler onmessageerror; +}; + +dictionary WorkerOptions { + WorkerType type = "classic"; + RequestCredentials credentials = "same-origin"; // credentials is only used if type is "module" + DOMString name = ""; +}; + +enum WorkerType { "classic", "module" }; + +Worker includes AbstractWorker; + +[Exposed=(Window,Worker)] +interface SharedWorker : EventTarget { + constructor(USVString scriptURL, optional (DOMString or WorkerOptions) options = {}); + + readonly attribute MessagePort port; +}; +SharedWorker includes AbstractWorker; + +interface mixin NavigatorConcurrentHardware { + readonly attribute unsigned long long hardwareConcurrency; +}; + +[Exposed=Worker] +interface WorkerNavigator {}; +WorkerNavigator includes NavigatorID; +WorkerNavigator includes NavigatorLanguage; +WorkerNavigator includes NavigatorOnLine; +WorkerNavigator includes NavigatorConcurrentHardware; + +[Exposed=Worker] +interface WorkerLocation { + stringifier readonly attribute USVString href; + readonly attribute USVString origin; + readonly attribute USVString protocol; + readonly attribute USVString host; + readonly attribute USVString hostname; + readonly attribute USVString port; + readonly attribute USVString pathname; + readonly attribute USVString search; + readonly attribute USVString hash; +}; + +[Exposed=Window] +interface Storage { + readonly attribute unsigned long length; + DOMString? key(unsigned long index); + getter DOMString? getItem(DOMString key); + setter void setItem(DOMString key, DOMString value); + deleter void removeItem(DOMString key); + void clear(); +}; + +interface mixin WindowSessionStorage { + readonly attribute Storage sessionStorage; +}; +Window includes WindowSessionStorage; + +interface mixin WindowLocalStorage { + readonly attribute Storage localStorage; +}; +Window includes WindowLocalStorage; + +[Exposed=Window, + Constructor(DOMString type, optional StorageEventInit eventInitDict = {})] +interface StorageEvent : Event { + readonly attribute DOMString? key; + readonly attribute DOMString? oldValue; + readonly attribute DOMString? newValue; + readonly attribute USVString url; + readonly attribute Storage? storageArea; + + void initStorageEvent(DOMString type, optional boolean bubbles = false, optional boolean cancelable = false, optional DOMString? key = null, optional DOMString? oldValue = null, optional DOMString? newValue = null, optional USVString url = "", optional Storage? storageArea = null); +}; + +dictionary StorageEventInit : EventInit { + DOMString? key = null; + DOMString? oldValue = null; + DOMString? newValue = null; + USVString url = ""; + Storage? storageArea = null; +}; + +[Exposed=Window] +interface HTMLMarqueeElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute DOMString behavior; + [CEReactions] attribute DOMString bgColor; + [CEReactions] attribute DOMString direction; + [CEReactions] attribute DOMString height; + [CEReactions] attribute unsigned long hspace; + [CEReactions] attribute long loop; + [CEReactions] attribute unsigned long scrollAmount; + [CEReactions] attribute unsigned long scrollDelay; + [CEReactions] attribute boolean trueSpeed; + [CEReactions] attribute unsigned long vspace; + [CEReactions] attribute DOMString width; + + attribute EventHandler onbounce; + attribute EventHandler onfinish; + attribute EventHandler onstart; + + void start(); + void stop(); +}; + +[Exposed=Window] +interface HTMLFrameSetElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute DOMString cols; + [CEReactions] attribute DOMString rows; +}; +HTMLFrameSetElement includes WindowEventHandlers; + +[Exposed=Window] +interface HTMLFrameElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute DOMString name; + [CEReactions] attribute DOMString scrolling; + [CEReactions] attribute USVString src; + [CEReactions] attribute DOMString frameBorder; + [CEReactions] attribute USVString longDesc; + [CEReactions] attribute boolean noResize; + readonly attribute Document? contentDocument; + readonly attribute WindowProxy? contentWindow; + + [CEReactions] attribute [LegacyNullToEmptyString] DOMString marginHeight; + [CEReactions] attribute [LegacyNullToEmptyString] DOMString marginWidth; +}; + +partial interface HTMLAnchorElement { + [CEReactions] attribute DOMString coords; + [CEReactions] attribute DOMString charset; + [CEReactions] attribute DOMString name; + [CEReactions] attribute DOMString rev; + [CEReactions] attribute DOMString shape; +}; + +partial interface HTMLAreaElement { + [CEReactions] attribute boolean noHref; +}; + +partial interface HTMLBodyElement { + [CEReactions] attribute [LegacyNullToEmptyString] DOMString text; + [CEReactions] attribute [LegacyNullToEmptyString] DOMString link; + [CEReactions] attribute [LegacyNullToEmptyString] DOMString vLink; + [CEReactions] attribute [LegacyNullToEmptyString] DOMString aLink; + [CEReactions] attribute [LegacyNullToEmptyString] DOMString bgColor; + [CEReactions] attribute DOMString background; +}; + +partial interface HTMLBRElement { + [CEReactions] attribute DOMString clear; +}; + +partial interface HTMLTableCaptionElement { + [CEReactions] attribute DOMString align; +}; + +partial interface HTMLTableColElement { + [CEReactions] attribute DOMString align; + [CEReactions] attribute DOMString ch; + [CEReactions] attribute DOMString chOff; + [CEReactions] attribute DOMString vAlign; + [CEReactions] attribute DOMString width; +}; + +[Exposed=Window] +interface HTMLDirectoryElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute boolean compact; +}; + +partial interface HTMLDivElement { + [CEReactions] attribute DOMString align; +}; + +partial interface HTMLDListElement { + [CEReactions] attribute boolean compact; +}; + +partial interface HTMLEmbedElement { + [CEReactions] attribute DOMString align; + [CEReactions] attribute DOMString name; +}; + +[Exposed=Window] +interface HTMLFontElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute [LegacyNullToEmptyString] DOMString color; + [CEReactions] attribute DOMString face; + [CEReactions] attribute DOMString size; +}; + +partial interface HTMLHeadingElement { + [CEReactions] attribute DOMString align; +}; + +partial interface HTMLHRElement { + [CEReactions] attribute DOMString align; + [CEReactions] attribute DOMString color; + [CEReactions] attribute boolean noShade; + [CEReactions] attribute DOMString size; + [CEReactions] attribute DOMString width; +}; + +partial interface HTMLHtmlElement { + [CEReactions] attribute DOMString version; +}; + +partial interface HTMLIFrameElement { + [CEReactions] attribute DOMString align; + [CEReactions] attribute DOMString scrolling; + [CEReactions] attribute DOMString frameBorder; + [CEReactions] attribute USVString longDesc; + + [CEReactions] attribute [LegacyNullToEmptyString] DOMString marginHeight; + [CEReactions] attribute [LegacyNullToEmptyString] DOMString marginWidth; +}; + +partial interface HTMLImageElement { + [CEReactions] attribute DOMString name; + [CEReactions] attribute USVString lowsrc; + [CEReactions] attribute DOMString align; + [CEReactions] attribute unsigned long hspace; + [CEReactions] attribute unsigned long vspace; + [CEReactions] attribute USVString longDesc; + + [CEReactions] attribute [LegacyNullToEmptyString] DOMString border; +}; + +partial interface HTMLInputElement { + [CEReactions] attribute DOMString align; + [CEReactions] attribute DOMString useMap; +}; + +partial interface HTMLLegendElement { + [CEReactions] attribute DOMString align; +}; + +partial interface HTMLLIElement { + [CEReactions] attribute DOMString type; +}; + +partial interface HTMLLinkElement { + [CEReactions] attribute DOMString charset; + [CEReactions] attribute DOMString rev; + [CEReactions] attribute DOMString target; +}; + +partial interface HTMLMenuElement { + [CEReactions] attribute boolean compact; +}; + +partial interface HTMLMetaElement { + [CEReactions] attribute DOMString scheme; +}; + +partial interface HTMLObjectElement { + [CEReactions] attribute DOMString align; + [CEReactions] attribute DOMString archive; + [CEReactions] attribute DOMString code; + [CEReactions] attribute boolean declare; + [CEReactions] attribute unsigned long hspace; + [CEReactions] attribute DOMString standby; + [CEReactions] attribute unsigned long vspace; + [CEReactions] attribute DOMString codeBase; + [CEReactions] attribute DOMString codeType; + + [CEReactions] attribute [LegacyNullToEmptyString] DOMString border; +}; + +partial interface HTMLOListElement { + [CEReactions] attribute boolean compact; +}; + +partial interface HTMLParagraphElement { + [CEReactions] attribute DOMString align; +}; + +partial interface HTMLParamElement { + [CEReactions] attribute DOMString type; + [CEReactions] attribute DOMString valueType; +}; + +partial interface HTMLPreElement { + [CEReactions] attribute long width; +}; + +partial interface HTMLStyleElement { + [CEReactions] attribute DOMString type; +}; + +partial interface HTMLScriptElement { + [CEReactions] attribute DOMString charset; + [CEReactions] attribute DOMString event; + [CEReactions] attribute DOMString htmlFor; +}; + +partial interface HTMLTableElement { + [CEReactions] attribute DOMString align; + [CEReactions] attribute DOMString border; + [CEReactions] attribute DOMString frame; + [CEReactions] attribute DOMString rules; + [CEReactions] attribute DOMString summary; + [CEReactions] attribute DOMString width; + + [CEReactions] attribute [LegacyNullToEmptyString] DOMString bgColor; + [CEReactions] attribute [LegacyNullToEmptyString] DOMString cellPadding; + [CEReactions] attribute [LegacyNullToEmptyString] DOMString cellSpacing; +}; + +partial interface HTMLTableSectionElement { + [CEReactions] attribute DOMString align; + [CEReactions] attribute DOMString ch; + [CEReactions] attribute DOMString chOff; + [CEReactions] attribute DOMString vAlign; +}; + +partial interface HTMLTableCellElement { + [CEReactions] attribute DOMString align; + [CEReactions] attribute DOMString axis; + [CEReactions] attribute DOMString height; + [CEReactions] attribute DOMString width; + + [CEReactions] attribute DOMString ch; + [CEReactions] attribute DOMString chOff; + [CEReactions] attribute boolean noWrap; + [CEReactions] attribute DOMString vAlign; + + [CEReactions] attribute [LegacyNullToEmptyString] DOMString bgColor; +}; + +partial interface HTMLTableRowElement { + [CEReactions] attribute DOMString align; + [CEReactions] attribute DOMString ch; + [CEReactions] attribute DOMString chOff; + [CEReactions] attribute DOMString vAlign; + + [CEReactions] attribute [LegacyNullToEmptyString] DOMString bgColor; +}; + +partial interface HTMLUListElement { + [CEReactions] attribute boolean compact; + [CEReactions] attribute DOMString type; +}; + +partial interface Document { + [CEReactions] attribute [LegacyNullToEmptyString] DOMString fgColor; + [CEReactions] attribute [LegacyNullToEmptyString] DOMString linkColor; + [CEReactions] attribute [LegacyNullToEmptyString] DOMString vlinkColor; + [CEReactions] attribute [LegacyNullToEmptyString] DOMString alinkColor; + [CEReactions] attribute [LegacyNullToEmptyString] DOMString bgColor; + + [SameObject] readonly attribute HTMLCollection anchors; + [SameObject] readonly attribute HTMLCollection applets; + + void clear(); + void captureEvents(); + void releaseEvents(); + + [SameObject] readonly attribute HTMLAllCollection all; +}; + +partial interface Window { + void captureEvents(); + void releaseEvents(); + + [Replaceable, SameObject] readonly attribute External external; +}; + +[Exposed=Window] +interface External { + void AddSearchProvider(); + void IsSearchProviderInstalled(); +}; diff --git a/test/fixtures/wpt/interfaces/url.idl b/test/fixtures/wpt/interfaces/url.idl index 998052da6ef1b3..b0b237e8524a86 100644 --- a/test/fixtures/wpt/interfaces/url.idl +++ b/test/fixtures/wpt/interfaces/url.idl @@ -3,10 +3,11 @@ // (https://github.com/tidoust/reffy-reports) // Source: URL Standard (https://url.spec.whatwg.org/) -[Constructor(USVString url, optional USVString base), - Exposed=(Window,Worker), +[Exposed=(Window,Worker), LegacyWindowAlias=webkitURL] interface URL { + constructor(USVString url, optional USVString base); + stringifier attribute USVString href; readonly attribute USVString origin; attribute USVString protocol; @@ -23,9 +24,10 @@ interface URL { USVString toJSON(); }; -[Constructor(optional (sequence> or record or USVString) init = ""), - Exposed=(Window,Worker)] +[Exposed=(Window,Worker)] interface URLSearchParams { + constructor(optional (sequence> or record or USVString) init = ""); + void append(USVString name, USVString value); void delete(USVString name); USVString? get(USVString name); diff --git a/test/fixtures/wpt/resources/SVGAnimationTestCase-testharness.js b/test/fixtures/wpt/resources/SVGAnimationTestCase-testharness.js new file mode 100644 index 00000000000000..9ebaf6803922e9 --- /dev/null +++ b/test/fixtures/wpt/resources/SVGAnimationTestCase-testharness.js @@ -0,0 +1,102 @@ +// NOTE(edvardt): +// This file is a slimmed down wrapper for the old SVGAnimationTestCase.js, +// it has some convenience functions and should not be used for new tests. +// New tests should not build on this API as it's just meant to keep things +// working. + +// Helper functions +const xlinkNS = "http://www.w3.org/1999/xlink" + +function expectFillColor(element, red, green, blue, message) { + let color = window.getComputedStyle(element, null).fill; + var re = new RegExp("rgba?\\(([^, ]*), ([^, ]*), ([^, ]*)(?:, )?([^, ]*)\\)"); + rgb = re.exec(color); + + assert_approx_equals(Number(rgb[1]), red, 2.0, message); + assert_approx_equals(Number(rgb[2]), green, 2.0, message); + assert_approx_equals(Number(rgb[3]), blue, 2.0, message); +} + +function expectColor(element, red, green, blue, property) { + if (typeof property != "string") + color = getComputedStyle(element).getPropertyValue("color"); + else + color = getComputedStyle(element).getPropertyValue(property); + var re = new RegExp("rgba?\\(([^, ]*), ([^, ]*), ([^, ]*)(?:, )?([^, ]*)\\)"); + rgb = re.exec(color); + assert_approx_equals(Number(rgb[1]), red, 2.0); + assert_approx_equals(Number(rgb[2]), green, 2.0); + assert_approx_equals(Number(rgb[3]), blue, 2.0); +} + +function createSVGElement(type) { + return document.createElementNS("http://www.w3.org/2000/svg", type); +} + +// Inspired by Layoutests/animations/animation-test-helpers.js +function moveAnimationTimelineAndSample(index) { + var animationId = expectedResults[index][0]; + var time = expectedResults[index][1]; + var sampleCallback = expectedResults[index][2]; + var animation = rootSVGElement.ownerDocument.getElementById(animationId); + + // If we want to sample the animation end, add a small delta, to reliable point past the end of the animation. + newTime = time; + + // The sample time is relative to the start time of the animation, take that into account. + rootSVGElement.setCurrentTime(newTime); + + // NOTE(edvardt): + // This is a dumb hack, some of the old tests sampled before the animation start, this + // isn't technically part of the animation tests and is "impossible" to translate since + // tests start automatically. Thus I solved it by skipping it. + if (time != 0.0) + sampleCallback(); +} + +var currentTest = 0; +var expectedResults; + +function sampleAnimation(t) { + if (currentTest == expectedResults.length) { + t.done(); + return; + } + + moveAnimationTimelineAndSample(currentTest); + ++currentTest; + + step_timeout(t.step_func(function () { sampleAnimation(t); }), 0); +} + +function runAnimationTest(t, expected) { + if (!expected) + throw("Expected results are missing!"); + if (currentTest > 0) + throw("Not allowed to call runAnimationTest() twice"); + + expectedResults = expected; + testCount = expectedResults.length; + currentTest = 0; + + step_timeout(t.step_func(function () { sampleAnimation(this); }), 50); +} + +function smil_async_test(func) { + async_test(t => { + window.onload = t.step_func(function () { + // Pause animations, we'll drive them manually. + // This also ensures that the timeline is paused before + // it starts. This should make the instance time of the below + // 'click' (for instance) 0, and hence minimize rounding + // errors for the addition in moveAnimationTimelineAndSample. + rootSVGElement.pauseAnimations(); + + // If eg. an animation is running with begin="0s", and + // we want to sample the first time, before the animation + // starts, then we can't delay the testing by using an + // onclick event, as the animation would be past start time. + func(t); + }); + }); +} diff --git a/test/fixtures/wpt/resources/webidl2/lib/README.md b/test/fixtures/wpt/resources/webidl2/lib/README.md new file mode 100644 index 00000000000000..1bd583269d2929 --- /dev/null +++ b/test/fixtures/wpt/resources/webidl2/lib/README.md @@ -0,0 +1,4 @@ +This directory contains a built version of the [webidl2.js library](https://github.com/w3c/webidl2.js). +It is built by running `npm run build-debug` at the root of that repository. + +The `webidl2.js.headers` file is a local addition to ensure the script is interpreted as UTF-8. diff --git a/test/fixtures/wpt/versions.json b/test/fixtures/wpt/versions.json index c560f6844e9e3d..566041b6362862 100644 --- a/test/fixtures/wpt/versions.json +++ b/test/fixtures/wpt/versions.json @@ -16,7 +16,7 @@ "path": "resources" }, "interfaces": { - "commit": "712c9f275e83997884749dbcaa503f12c0ff5bba", + "commit": "8ada332aeac03764f73ec7ff66f682c5c0b454b4", "path": "interfaces" }, "html/webappapis/microtask-queuing": { @@ -26,5 +26,9 @@ "html/webappapis/timers": { "commit": "ddfe9c089bab565a9d3aa37bdef63d8012c1a94c", "path": "html/webappapis/timers" + }, + "hr-time": { + "commit": "a5d1774ecf41751d1c9357c27c709ee33bf3e279", + "path": "hr-time" } } \ No newline at end of file diff --git a/test/internet/test-dns-idna2008.js b/test/internet/test-dns-idna2008.js index 5a6a48b6fac39e..88c156303a06a0 100644 --- a/test/internet/test-dns-idna2008.js +++ b/test/internet/test-dns-idna2008.js @@ -16,31 +16,37 @@ const { addresses } = require('../common/internet'); const fixture = { hostname: 'straße.de', expectedAddress: '81.169.145.78', - dnsServer: addresses.DNS4_SERVER + dnsServer: addresses.DNS4_SERVER, + family: 4, }; -// Explicitly use well behaved DNS servers that are known to be able to resolve +// Explicitly use well-behaved DNS servers that are known to be able to resolve // the query (which is a.k.a xn--strae-oqa.de). dns.setServers([fixture.dnsServer]); -dns.lookup(fixture.hostname, mustCall((err, address) => { - if (err && err.errno === 'ESERVFAIL') { - assert.ok(err.message.includes('queryA ESERVFAIL straße.de')); - return; - } - assert.ifError(err); - assert.strictEqual(address, fixture.expectedAddress); -})); +dns.lookup( + fixture.hostname, + { family: fixture.family }, + mustCall((err, address) => { + if (err && err.errno === 'ESERVFAIL') { + assert.ok(err.message.includes('queryA ESERVFAIL straße.de')); + return; + } + assert.ifError(err); + assert.strictEqual(address, fixture.expectedAddress); + }) +); -dns.promises.lookup(fixture.hostname).then(({ address }) => { - assert.strictEqual(address, fixture.expectedAddress); -}, (err) => { - if (err && err.errno === 'ESERVFAIL') { - assert.ok(err.message.includes('queryA ESERVFAIL straße.de')); - } else { - throw err; - } -}).finally(mustCall()); +dns.promises.lookup(fixture.hostname, { family: fixture.family }) + .then(({ address }) => { + assert.strictEqual(address, fixture.expectedAddress); + }, (err) => { + if (err && err.errno === 'ESERVFAIL') { + assert.ok(err.message.includes('queryA ESERVFAIL straße.de')); + } else { + throw err; + } + }).finally(mustCall()); dns.resolve4(fixture.hostname, mustCall((err, addresses) => { if (err && err.errno === 'ESERVFAIL') { diff --git a/test/js-native-api/test_number/test.js b/test/js-native-api/test_number/test.js index 808d1d9d5c374f..8ab8ad5e8be7f3 100644 --- a/test/js-native-api/test_number/test.js +++ b/test/js-native-api/test_number/test.js @@ -48,6 +48,7 @@ testUint32(4294967295); testUint32(4294967296, 0); testUint32(4294967297, 1); testUint32(17 * 4294967296 + 1, 1); +testUint32(-1, 0xffffffff); // Validate documented behavior when value is retrieved as 32-bit integer with // `napi_get_value_int32` diff --git a/test/node-api/test_buffer/test.js b/test/node-api/test_buffer/test.js index 6b6c2089afa76e..fe668a3ef9a879 100644 --- a/test/node-api/test_buffer/test.js +++ b/test/node-api/test_buffer/test.js @@ -1,10 +1,10 @@ 'use strict'; -// Flags: --expose-gc +// Flags: --expose-gc --no-concurrent-array-buffer-freeing --no-concurrent-array-buffer-sweeping const common = require('../../common'); const binding = require(`./build/${common.buildType}/test_buffer`); const assert = require('assert'); -const setImmediatePromise = require('util').promisify(setImmediate); +const tick = require('util').promisify(require('../../common/tick')); (async function() { assert.strictEqual(binding.newBuffer().toString(), binding.theText); @@ -12,7 +12,7 @@ const setImmediatePromise = require('util').promisify(setImmediate); console.log('gc1'); global.gc(); assert.strictEqual(binding.getDeleterCallCount(), 0); - await setImmediatePromise(); + await tick(10); assert.strictEqual(binding.getDeleterCallCount(), 1); assert.strictEqual(binding.copyBuffer().toString(), binding.theText); @@ -22,7 +22,7 @@ const setImmediatePromise = require('util').promisify(setImmediate); buffer = null; global.gc(); assert.strictEqual(binding.getDeleterCallCount(), 1); - await setImmediatePromise(); + await tick(10); console.log('gc2'); assert.strictEqual(binding.getDeleterCallCount(), 2); })().then(common.mustCall()); diff --git a/test/parallel/test-async-hooks-promise.js b/test/parallel/test-async-hooks-promise.js index 637d287b506ba9..9db510e329ffad 100644 --- a/test/parallel/test-async-hooks-promise.js +++ b/test/parallel/test-async-hooks-promise.js @@ -24,6 +24,4 @@ const a = Promise.resolve(42); a.then(common.mustCall()); assert.strictEqual(initCalls[0].triggerId, 1); -assert.strictEqual(initCalls[0].resource.isChainedPromise, false); assert.strictEqual(initCalls[1].triggerId, initCalls[0].id); -assert.strictEqual(initCalls[1].resource.isChainedPromise, true); diff --git a/test/parallel/test-async-hooks-worker-asyncfn-terminate-1.js b/test/parallel/test-async-hooks-worker-asyncfn-terminate-1.js new file mode 100644 index 00000000000000..eb1664591308a3 --- /dev/null +++ b/test/parallel/test-async-hooks-worker-asyncfn-terminate-1.js @@ -0,0 +1,15 @@ +'use strict'; +const common = require('../common'); +const { Worker } = require('worker_threads'); + +const w = new Worker(` +const { createHook } = require('async_hooks'); + +setImmediate(async () => { + createHook({ init() {} }).enable(); + await 0; + process.exit(); +}); +`, { eval: true }); + +w.on('exit', common.mustCall()); diff --git a/test/parallel/test-async-hooks-worker-asyncfn-terminate-2.js b/test/parallel/test-async-hooks-worker-asyncfn-terminate-2.js new file mode 100644 index 00000000000000..049264d3e8aef5 --- /dev/null +++ b/test/parallel/test-async-hooks-worker-asyncfn-terminate-2.js @@ -0,0 +1,21 @@ +'use strict'; +const common = require('../common'); +const { Worker } = require('worker_threads'); + +// Like test-async-hooks-worker-promise.js but with the `await` and `createHook` +// lines switched, because that resulted in different assertion failures +// (one a Node.js assertion and one a V8 DCHECK) and it seems prudent to +// cover both of those failures. + +const w = new Worker(` +const { createHook } = require('async_hooks'); + +setImmediate(async () => { + await 0; + createHook({ init() {} }).enable(); + process.exit(); +}); +`, { eval: true }); + +w.postMessage({}); +w.on('exit', common.mustCall()); diff --git a/test/parallel/test-async-hooks-worker-asyncfn-terminate-3.js b/test/parallel/test-async-hooks-worker-asyncfn-terminate-3.js new file mode 100644 index 00000000000000..40c7d85835ae44 --- /dev/null +++ b/test/parallel/test-async-hooks-worker-asyncfn-terminate-3.js @@ -0,0 +1,20 @@ +'use strict'; +const common = require('../common'); +const { Worker } = require('worker_threads'); + +// Like test-async-hooks-worker-promise.js but with an additional statement +// after the `process.exit()` call, that shouldn’t really make a difference +// but apparently does. + +const w = new Worker(` +const { createHook } = require('async_hooks'); + +setImmediate(async () => { + createHook({ init() {} }).enable(); + await 0; + process.exit(); + process._rawDebug('THIS SHOULD NEVER BE REACHED'); +}); +`, { eval: true }); + +w.on('exit', common.mustCall()); diff --git a/test/parallel/test-async-hooks-worker-asyncfn-terminate-4.js b/test/parallel/test-async-hooks-worker-asyncfn-terminate-4.js new file mode 100644 index 00000000000000..dc641471b691e0 --- /dev/null +++ b/test/parallel/test-async-hooks-worker-asyncfn-terminate-4.js @@ -0,0 +1,24 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const { Worker } = require('worker_threads'); + +// Like test-async-hooks-worker-promise.js but doing a trivial counter increase +// after process.exit(). This should not make a difference, but apparently it +// does. This is *also* different from test-async-hooks-worker-promise-3.js, +// in that the statement is an ArrayBuffer access rather than a full method, +// which *also* makes a difference even though it shouldn’t. + +const workerData = new Int32Array(new SharedArrayBuffer(4)); +const w = new Worker(` +const { createHook } = require('async_hooks'); + +setImmediate(async () => { + createHook({ init() {} }).enable(); + await 0; + process.exit(); + workerData[0]++; +}); +`, { eval: true, workerData }); + +w.on('exit', common.mustCall(() => assert.strictEqual(workerData[0], 0))); diff --git a/test/parallel/test-bootstrap-modules.js b/test/parallel/test-bootstrap-modules.js index e07ca03e807b5d..5c719d803cf427 100644 --- a/test/parallel/test-bootstrap-modules.js +++ b/test/parallel/test-bootstrap-modules.js @@ -17,13 +17,13 @@ const expectedModules = new Set([ 'Internal Binding credentials', 'Internal Binding fs', 'Internal Binding fs_dir', - 'Internal Binding inspector', 'Internal Binding module_wrap', 'Internal Binding native_module', 'Internal Binding options', 'Internal Binding process_methods', 'Internal Binding report', 'Internal Binding string_decoder', + 'Internal Binding symbols', 'Internal Binding task_queue', 'Internal Binding timers', 'Internal Binding trace_events', @@ -86,26 +86,28 @@ const expectedModules = new Set([ ]); if (!common.isMainThread) { - expectedModules.add('Internal Binding messaging'); - expectedModules.add('Internal Binding symbols'); - expectedModules.add('Internal Binding worker'); - expectedModules.add('NativeModule _stream_duplex'); - expectedModules.add('NativeModule _stream_passthrough'); - expectedModules.add('NativeModule _stream_readable'); - expectedModules.add('NativeModule _stream_transform'); - expectedModules.add('NativeModule _stream_writable'); - expectedModules.add('NativeModule internal/error-serdes'); - expectedModules.add('NativeModule internal/process/worker_thread_only'); - expectedModules.add('NativeModule internal/streams/buffer_list'); - expectedModules.add('NativeModule internal/streams/destroy'); - expectedModules.add('NativeModule internal/streams/end-of-stream'); - expectedModules.add('NativeModule internal/streams/legacy'); - expectedModules.add('NativeModule internal/streams/pipeline'); - expectedModules.add('NativeModule internal/streams/state'); - expectedModules.add('NativeModule internal/worker'); - expectedModules.add('NativeModule internal/worker/io'); - expectedModules.add('NativeModule stream'); - expectedModules.add('NativeModule worker_threads'); + [ + 'Internal Binding messaging', + 'Internal Binding symbols', + 'Internal Binding worker', + 'NativeModule _stream_duplex', + 'NativeModule _stream_passthrough', + 'NativeModule _stream_readable', + 'NativeModule _stream_transform', + 'NativeModule _stream_writable', + 'NativeModule internal/error-serdes', + 'NativeModule internal/process/worker_thread_only', + 'NativeModule internal/streams/buffer_list', + 'NativeModule internal/streams/destroy', + 'NativeModule internal/streams/end-of-stream', + 'NativeModule internal/streams/legacy', + 'NativeModule internal/streams/pipeline', + 'NativeModule internal/streams/state', + 'NativeModule internal/worker', + 'NativeModule internal/worker/io', + 'NativeModule stream', + 'NativeModule worker_threads', + ].forEach(expectedModules.add.bind(expectedModules)); } if (common.hasIntl) { @@ -115,6 +117,7 @@ if (common.hasIntl) { } if (process.features.inspector) { + expectedModules.add('Internal Binding inspector'); expectedModules.add('NativeModule internal/inspector_async_hook'); expectedModules.add('NativeModule internal/util/inspector'); } diff --git a/test/parallel/test-cli-eval.js b/test/parallel/test-cli-eval.js index 65d31642055627..cbe0a09887f8eb 100644 --- a/test/parallel/test-cli-eval.js +++ b/test/parallel/test-cli-eval.js @@ -245,9 +245,10 @@ child.exec( // Assert that "42\n" is written to stdout with print option. child.exec( `${nodejs} ${execOptions} --print --eval "42"`, - common.mustCall((err, stdout) => { - assert.ifError(err); - assert.strictEqual(stdout, '42\n'); + common.mustCall((err, stdout, stderr) => { + assert.ok(err); + assert.strictEqual(stdout, ''); + assert.ok(stderr.includes('--print cannot be used with ESM input')); })); // Assert that error is written to stderr on invalid input. diff --git a/test/parallel/test-console-clear.js b/test/parallel/test-console-clear.js index b6fc003165dc66..5975602547922a 100644 --- a/test/parallel/test-console-clear.js +++ b/test/parallel/test-console-clear.js @@ -1,6 +1,6 @@ 'use strict'; -require('../common'); +const common = require('../common'); const assert = require('assert'); const stdoutWrite = process.stdout.write; @@ -18,5 +18,7 @@ function doTest(isTTY, check) { } // Fake TTY -doTest(true, check); +if (!common.isDumbTerminal) { + doTest(true, check); +} doTest(false, ''); diff --git a/test/parallel/test-directory-import.js b/test/parallel/test-directory-import.js new file mode 100644 index 00000000000000..83fd01f6a0f214 --- /dev/null +++ b/test/parallel/test-directory-import.js @@ -0,0 +1,14 @@ +'use strict'; + +require('../common'); +const fixtures = require('../common/fixtures'); +const assert = require('assert'); +const { pathToFileURL } = require('url'); + +{ + assert.rejects(import('./'), /ERR_UNSUPPORTED_DIR_IMPORT/); + assert.rejects( + import(pathToFileURL(fixtures.path('packages', 'main'))), + /Did you mean/, + ); +} diff --git a/test/parallel/test-dns-promises-lookupService.js b/test/parallel/test-dns-lookupService-promises.js similarity index 100% rename from test/parallel/test-dns-promises-lookupService.js rename to test/parallel/test-dns-lookupService-promises.js diff --git a/test/parallel/test-finalization-group-error.js b/test/parallel/test-finalization-group-error.js deleted file mode 100644 index 0685811f55b7f8..00000000000000 --- a/test/parallel/test-finalization-group-error.js +++ /dev/null @@ -1,27 +0,0 @@ -'use strict'; - -// Flags: --expose-gc --harmony-weak-refs - -const common = require('../common'); -const assert = require('assert'); - -const g = new globalThis.FinalizationGroup(common.mustCallAtLeast(() => { - throw new Error('test'); -}, 1)); -g.register({}, 42); - -setTimeout(() => { - globalThis.gc(); - assert.throws(() => { - g.cleanupSome(); - }, { - name: 'Error', - message: 'test', - }); - - // Give the callbacks scheduled by global.gc() time to run, as the underlying - // uv_async_t is unref’ed. - setTimeout(() => {}, 200); -}, 200); - -process.on('uncaughtException', common.mustCall()); diff --git a/test/parallel/test-finalization-group-regular-gc.js b/test/parallel/test-finalization-group-regular-gc.js deleted file mode 100644 index 7a4a4797eadcf0..00000000000000 --- a/test/parallel/test-finalization-group-regular-gc.js +++ /dev/null @@ -1,25 +0,0 @@ -// Flags: --harmony-weak-refs -'use strict'; -require('../common'); -const assert = require('assert'); - -// Test that finalization callbacks do not crash when caused through a regular -// GC (not global.gc()). - -const start = Date.now(); -const g = new globalThis.FinalizationGroup(() => { - const diff = Date.now() - start; - assert(diff < 10000, `${diff} >= 10000`); -}); -g.register({}, 42); - -setImmediate(() => { - const arr = []; - // Build up enough memory usage to hopefully trigger a platform task but not - // enough to trigger GC as an interrupt. - while (arr.length < 1000000) arr.push([]); - - setTimeout(() => { - g; // Keep reference alive. - }, 200000).unref(); -}); diff --git a/test/parallel/test-finalization-group.js b/test/parallel/test-finalization-group.js deleted file mode 100644 index 3e6b9d72e35648..00000000000000 --- a/test/parallel/test-finalization-group.js +++ /dev/null @@ -1,13 +0,0 @@ -'use strict'; - -// Flags: --expose-gc --harmony-weak-refs - -const common = require('../common'); - -const g = new globalThis.FinalizationGroup(common.mustCallAtLeast(1)); -g.register({}, 42); - -setTimeout(() => { - globalThis.gc(); - g.cleanupSome(); -}, 200); diff --git a/test/parallel/test-fs-mkdir-mode-mask.js b/test/parallel/test-fs-mkdir-mode-mask.js index 515b982054b82b..40bd7bec441373 100644 --- a/test/parallel/test-fs-mkdir-mode-mask.js +++ b/test/parallel/test-fs-mkdir-mode-mask.js @@ -7,15 +7,12 @@ const assert = require('assert'); const path = require('path'); const fs = require('fs'); -let mode; - if (common.isWindows) { common.skip('mode is not supported in mkdir on Windows'); return; -} else { - mode = 0o644; } +const mode = 0o644; const maskToIgnore = 0o10000; const tmpdir = require('../common/tmpdir'); diff --git a/test/parallel/test-fs-opendir.js b/test/parallel/test-fs-opendir.js index 733d9c7f3e0487..e5233e3a10914a 100644 --- a/test/parallel/test-fs-opendir.js +++ b/test/parallel/test-fs-opendir.js @@ -33,6 +33,10 @@ const dirclosedError = { code: 'ERR_DIR_CLOSED' }; +const dirconcurrentError = { + code: 'ERR_DIR_CONCURRENT_OPERATION' +}; + const invalidCallbackObj = { code: 'ERR_INVALID_CALLBACK', name: 'TypeError' @@ -230,3 +234,39 @@ async function doAsyncIterDirClosedTest() { assert.throws(() => dir.close(), dirclosedError); } doAsyncIterDirClosedTest().then(common.mustCall()); + +// Check that readSync() and closeSync() during read() throw exceptions +async function doConcurrentAsyncAndSyncOps() { + const dir = await fs.promises.opendir(testDir); + const promise = dir.read(); + + assert.throws(() => dir.closeSync(), dirconcurrentError); + assert.throws(() => dir.readSync(), dirconcurrentError); + + await promise; + dir.closeSync(); +} +doConcurrentAsyncAndSyncOps().then(common.mustCall()); + +// Check that concurrent read() operations don't do weird things. +async function doConcurrentAsyncOps() { + const dir = await fs.promises.opendir(testDir); + const promise1 = dir.read(); + const promise2 = dir.read(); + + assertDirent(await promise1); + assertDirent(await promise2); + dir.closeSync(); +} +doConcurrentAsyncOps().then(common.mustCall()); + +// Check that concurrent read() + close() operations don't do weird things. +async function doConcurrentAsyncMixedOps() { + const dir = await fs.promises.opendir(testDir); + const promise1 = dir.read(); + const promise2 = dir.close(); + + assertDirent(await promise1); + await promise2; +} +doConcurrentAsyncMixedOps().then(common.mustCall()); diff --git a/test/parallel/test-fs-stream-fs-options.js b/test/parallel/test-fs-stream-fs-options.js new file mode 100644 index 00000000000000..65144c0d617e9b --- /dev/null +++ b/test/parallel/test-fs-stream-fs-options.js @@ -0,0 +1,73 @@ +'use strict'; + +require('../common'); +const fixtures = require('../common/fixtures'); +const path = require('path'); +const fs = require('fs'); +const assert = require('assert'); + +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); + +const streamOpts = ['open', 'close']; +const writeStreamOptions = [...streamOpts, 'write']; +const readStreamOptions = [...streamOpts, 'read']; +const originalFs = { fs }; + +{ + const file = path.join(tmpdir.path, 'write-end-test0.txt'); + + writeStreamOptions.forEach((fn) => { + const overrideFs = Object.assign({}, originalFs.fs, { [fn]: null }); + if (fn === 'write') overrideFs.writev = null; + + const opts = { + fs: overrideFs + }; + assert.throws( + () => fs.createWriteStream(file, opts), { + code: 'ERR_INVALID_ARG_TYPE', + name: 'TypeError', + message: `The "options.fs.${fn}" property must be of type function. ` + + 'Received null' + }, + `createWriteStream options.fs.${fn} should throw if isn't a function` + ); + }); +} + +{ + const file = path.join(tmpdir.path, 'write-end-test0.txt'); + const overrideFs = Object.assign({}, originalFs.fs, { writev: 'not a fn' }); + const opts = { + fs: overrideFs + }; + assert.throws( + () => fs.createWriteStream(file, opts), { + code: 'ERR_INVALID_ARG_TYPE', + name: 'TypeError', + message: 'The "options.fs.writev" property must be of type function. ' + + 'Received type string (\'not a fn\')' + }, + 'createWriteStream options.fs.writev should throw if isn\'t a function' + ); +} + +{ + const file = fixtures.path('x.txt'); + readStreamOptions.forEach((fn) => { + const overrideFs = Object.assign({}, originalFs.fs, { [fn]: null }); + const opts = { + fs: overrideFs + }; + assert.throws( + () => fs.createReadStream(file, opts), { + code: 'ERR_INVALID_ARG_TYPE', + name: 'TypeError', + message: `The "options.fs.${fn}" property must be of type function. ` + + 'Received null' + }, + `createReadStream options.fs.${fn} should throw if isn't a function` + ); + }); +} diff --git a/test/parallel/test-fs-utimes.js b/test/parallel/test-fs-utimes.js index c5ed73733c5c40..b72d263cf6ce50 100644 --- a/test/parallel/test-fs-utimes.js +++ b/test/parallel/test-fs-utimes.js @@ -31,15 +31,14 @@ tmpdir.refresh(); function stat_resource(resource) { if (typeof resource === 'string') { return fs.statSync(resource); - } else { - const stats = fs.fstatSync(resource); - // Ensure mtime has been written to disk - // except for directories on AIX where it cannot be synced - if (common.isAIX && stats.isDirectory()) - return stats; - fs.fsyncSync(resource); - return fs.fstatSync(resource); } + const stats = fs.fstatSync(resource); + // Ensure mtime has been written to disk + // except for directories on AIX where it cannot be synced + if (common.isAIX && stats.isDirectory()) + return stats; + fs.fsyncSync(resource); + return fs.fstatSync(resource); } function check_mtime(resource, mtime) { diff --git a/test/parallel/test-fs-watch-ref-unref.js b/test/parallel/test-fs-watch-ref-unref.js new file mode 100644 index 00000000000000..e51ecaf5b2fcc1 --- /dev/null +++ b/test/parallel/test-fs-watch-ref-unref.js @@ -0,0 +1,20 @@ +'use strict'; + +const common = require('../common'); + +if (common.isIBMi) + common.skip('IBMi does not support `fs.watch()`'); + +const fs = require('fs'); + +const watcher = fs.watch(__filename, common.mustNotCall()); + +watcher.unref(); + +setTimeout( + common.mustCall(() => { + watcher.ref(); + watcher.unref(); + }), + common.platformTimeout(100) +); diff --git a/test/parallel/test-fs-watchfile-ref-unref.js b/test/parallel/test-fs-watchfile-ref-unref.js new file mode 100644 index 00000000000000..4ac2691ea9d702 --- /dev/null +++ b/test/parallel/test-fs-watchfile-ref-unref.js @@ -0,0 +1,35 @@ +'use strict'; + +const common = require('../common'); + +const fs = require('fs'); +const assert = require('assert'); + +const uncalledListener = common.mustNotCall(); +const uncalledListener2 = common.mustNotCall(); +const watcher = fs.watchFile(__filename, uncalledListener); + +watcher.unref(); +watcher.unref(); +watcher.ref(); +watcher.unref(); +watcher.ref(); +watcher.ref(); +watcher.unref(); + +fs.unwatchFile(__filename, uncalledListener); + +// Watch the file with two different listeners. +fs.watchFile(__filename, uncalledListener); +const watcher2 = fs.watchFile(__filename, uncalledListener2); + +setTimeout( + common.mustCall(() => { + fs.unwatchFile(__filename, common.mustNotCall()); + assert.strictEqual(watcher2.listenerCount('change'), 2); + fs.unwatchFile(__filename, uncalledListener); + assert.strictEqual(watcher2.listenerCount('change'), 1); + watcher2.unref(); + }), + common.platformTimeout(100) +); diff --git a/test/parallel/test-http-client-agent-abort-close-event.js b/test/parallel/test-http-client-agent-abort-close-event.js index 437d2aad222780..69a48da232c369 100644 --- a/test/parallel/test-http-client-agent-abort-close-event.js +++ b/test/parallel/test-http-client-agent-abort-close-event.js @@ -1,5 +1,6 @@ 'use strict'; const common = require('../common'); +const assert = require('assert'); const http = require('http'); const server = http.createServer(common.mustNotCall()); @@ -16,6 +17,7 @@ server.listen(0, common.mustCall(() => { .on('socket', common.mustNotCall()) .on('response', common.mustNotCall()) .on('close', common.mustCall(() => { + assert.strictEqual(req.destroyed, true); server.close(); keepAliveAgent.destroy(); })) diff --git a/test/parallel/test-http-client-agent-end-close-event.js b/test/parallel/test-http-client-agent-end-close-event.js index de3ce193fbba9d..ce202f4d2f283c 100644 --- a/test/parallel/test-http-client-agent-end-close-event.js +++ b/test/parallel/test-http-client-agent-end-close-event.js @@ -1,5 +1,6 @@ 'use strict'; const common = require('../common'); +const assert = require('assert'); const http = require('http'); const server = http.createServer(common.mustCall((req, res) => { @@ -18,6 +19,7 @@ server.listen(0, common.mustCall(() => { .on('response', common.mustCall((res) => { res .on('close', common.mustCall(() => { + assert.strictEqual(req.destroyed, true); server.close(); keepAliveAgent.destroy(); })) diff --git a/test/parallel/test-http-client-close-event.js b/test/parallel/test-http-client-close-event.js index b539423a80f8b5..7097a247859f5e 100644 --- a/test/parallel/test-http-client-close-event.js +++ b/test/parallel/test-http-client-close-event.js @@ -22,6 +22,7 @@ server.listen(0, common.mustCall(() => { })); req.on('close', common.mustCall(() => { + assert.strictEqual(req.destroyed, true); assert.strictEqual(errorEmitted, true); server.close(); })); diff --git a/test/parallel/test-http-client-override-global-agent.js b/test/parallel/test-http-client-override-global-agent.js index f046abaa74e45d..0efaded5e419b0 100644 --- a/test/parallel/test-http-client-override-global-agent.js +++ b/test/parallel/test-http-client-override-global-agent.js @@ -21,6 +21,8 @@ function makeRequest() { const req = http.get({ port: server.address().port }); - req.on('close', () => - server.close()); + req.on('close', () => { + assert.strictEqual(req.destroyed, true); + server.close(); + }); } diff --git a/test/parallel/test-http-client-res-destroyed.js b/test/parallel/test-http-client-res-destroyed.js new file mode 100644 index 00000000000000..188ab06c155731 --- /dev/null +++ b/test/parallel/test-http-client-res-destroyed.js @@ -0,0 +1,41 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const http = require('http'); + +{ + const server = http.createServer(common.mustCall((req, res) => { + res.end('asd'); + })); + + server.listen(0, common.mustCall(() => { + http.get({ + port: server.address().port + }, common.mustCall((res) => { + assert.strictEqual(res.destroyed, false); + res.destroy(); + assert.strictEqual(res.destroyed, true); + res.on('close', common.mustCall(() => { + server.close(); + })); + })); + })); +} + +{ + const server = http.createServer(common.mustCall((req, res) => { + res.end('asd'); + })); + + server.listen(0, common.mustCall(() => { + http.get({ + port: server.address().port + }, common.mustCall((res) => { + assert.strictEqual(res.destroyed, false); + res.on('close', common.mustCall(() => { + assert.strictEqual(res.destroyed, true); + server.close(); + })).resume(); + })); + })); +} diff --git a/test/parallel/test-http-client-set-timeout.js b/test/parallel/test-http-client-set-timeout.js index 51b6622a6b71cc..8cb83e3f1869d0 100644 --- a/test/parallel/test-http-client-set-timeout.js +++ b/test/parallel/test-http-client-set-timeout.js @@ -38,6 +38,7 @@ server.listen(0, mustCall(() => { })); req.on('close', mustCall(() => { + strictEqual(req.destroyed, true); server.close(); })); diff --git a/test/parallel/test-http-client-timeout-event.js b/test/parallel/test-http-client-timeout-event.js index 71767bef8f1641..d5a63622bad03b 100644 --- a/test/parallel/test-http-client-timeout-event.js +++ b/test/parallel/test-http-client-timeout-event.js @@ -21,6 +21,7 @@ 'use strict'; const common = require('../common'); +const assert = require('assert'); const http = require('http'); const options = { @@ -38,7 +39,10 @@ server.listen(0, options.host, function() { req.on('error', function() { // This space is intentionally left blank }); - req.on('close', common.mustCall(() => server.close())); + req.on('close', common.mustCall(() => { + assert.strictEqual(req.destroyed, true); + server.close(); + })); req.setTimeout(1); req.on('timeout', common.mustCall(() => { diff --git a/test/parallel/test-http-client-timeout-option.js b/test/parallel/test-http-client-timeout-option.js index c21ec88e855208..1003c28b5def56 100644 --- a/test/parallel/test-http-client-timeout-option.js +++ b/test/parallel/test-http-client-timeout-option.js @@ -23,7 +23,10 @@ server.listen(0, options.host, function() { req.on('error', function() { // This space is intentionally left blank }); - req.on('close', common.mustCall(() => server.close())); + req.on('close', common.mustCall(() => { + assert.strictEqual(req.destroyed, true); + server.close(); + })); let timeout_events = 0; req.on('timeout', common.mustCall(() => timeout_events += 1)); diff --git a/test/parallel/test-http-client-timeout.js b/test/parallel/test-http-client-timeout.js index 90a3bebebc9e13..b83bd1ddf010fe 100644 --- a/test/parallel/test-http-client-timeout.js +++ b/test/parallel/test-http-client-timeout.js @@ -41,6 +41,7 @@ server.listen(0, options.host, function() { // This space intentionally left blank }); req.on('close', function() { + assert.strictEqual(req.destroyed, true); server.close(); }); function destroy() { diff --git a/test/parallel/test-http-connect-req-res.js b/test/parallel/test-http-connect-req-res.js index 893c621852be89..cd6e55e0898c66 100644 --- a/test/parallel/test-http-connect-req-res.js +++ b/test/parallel/test-http-connect-req-res.js @@ -33,7 +33,10 @@ server.listen(0, common.mustCall(function() { path: 'example.com:443' }, common.mustNotCall()); - req.on('close', common.mustCall()); + assert.strictEqual(req.destroyed, false); + req.on('close', common.mustCall(() => { + assert.strictEqual(req.destroyed, true); + })); req.on('connect', common.mustCall(function(res, socket, firstBodyChunk) { console.error('Client got CONNECT request'); diff --git a/test/parallel/test-http-connect.js b/test/parallel/test-http-connect.js index be853de347e0cb..47fd7316d0cf1d 100644 --- a/test/parallel/test-http-connect.js +++ b/test/parallel/test-http-connect.js @@ -62,7 +62,10 @@ server.listen(0, common.mustCall(() => { assert.strictEqual(socket._httpMessage, req); })); - req.on('close', common.mustCall()); + assert.strictEqual(req.destroyed, false); + req.on('close', common.mustCall(() => { + assert.strictEqual(req.destroyed, true); + })); req.on('connect', common.mustCall((res, socket, firstBodyChunk) => { // Make sure this request got removed from the pool. diff --git a/test/parallel/test-http-header-validators.js b/test/parallel/test-http-header-validators.js new file mode 100644 index 00000000000000..fb23bd4885c766 --- /dev/null +++ b/test/parallel/test-http-header-validators.js @@ -0,0 +1,62 @@ +'use strict'; +require('../common'); +const assert = require('assert'); +const { validateHeaderName, validateHeaderValue } = require('http'); + +// Expected static methods +isFunc(validateHeaderName, 'validateHeaderName'); +isFunc(validateHeaderValue, 'validateHeaderValue'); + +// Expected to be useful as static methods +console.log('validateHeaderName'); +// - when used with valid header names - should not throw +[ + 'user-agent', + 'USER-AGENT', + 'User-Agent', + 'x-forwarded-for' +].forEach((name) => { + console.log('does not throw for "%s"', name); + validateHeaderName(name); +}); + +// - when used with invalid header names: +[ + 'איקס-פורוורד-פור', + 'x-forwarded-fםr', +].forEach((name) => { + console.log('throws for: "%s"', name.slice(0, 50)); + assert.throws( + () => validateHeaderName(name), + { code: 'ERR_INVALID_HTTP_TOKEN' } + ); +}); + +console.log('validateHeaderValue'); +// - when used with valid header values - should not throw +[ + ['x-valid', 1], + ['x-valid', '1'], + ['x-valid', 'string'], +].forEach(([name, value]) => { + console.log('does not throw for "%s"', name); + validateHeaderValue(name, value); +}); + +// - when used with invalid header values: +[ + // [header, value, expectedCode] + ['x-undefined', undefined, 'ERR_HTTP_INVALID_HEADER_VALUE'], + ['x-bad-char', 'לא תקין', 'ERR_INVALID_CHAR'], +].forEach(([name, value, code]) => { + console.log('throws %s for: "%s: %s"', code, name, value); + assert.throws( + () => validateHeaderValue(name, value), + { code } + ); +}); + +// Misc. +function isFunc(v, ttl) { + assert.ok(v.constructor === Function, `${ttl} is expected to be a function`); +} diff --git a/test/parallel/test-http-keepalive-free.js b/test/parallel/test-http-keepalive-free.js new file mode 100644 index 00000000000000..0252c284962b39 --- /dev/null +++ b/test/parallel/test-http-keepalive-free.js @@ -0,0 +1,36 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); + +const http = require('http'); + +for (const method of ['abort', 'destroy']) { + const server = http.createServer(common.mustCall((req, res) => { + res.end(req.url); + })); + server.listen(0, common.mustCall(() => { + const agent = http.Agent({ keepAlive: true }); + + const req = http + .request({ + port: server.address().port, + agent + }) + .on('socket', common.mustCall((socket) => { + socket.on('free', common.mustCall()); + })) + .on('response', common.mustCall((res) => { + assert.strictEqual(req.destroyed, false); + res.on('end', () => { + assert.strictEqual(req.destroyed, true); + req[method](); + assert.strictEqual(req.socket.destroyed, false); + agent.destroy(); + server.close(); + }).resume(); + })) + .end(); + assert.strictEqual(req.destroyed, false); + })); +} diff --git a/test/parallel/test-http-parser-memory-retention.js b/test/parallel/test-http-parser-memory-retention.js new file mode 100644 index 00000000000000..3a6d34221e0bda --- /dev/null +++ b/test/parallel/test-http-parser-memory-retention.js @@ -0,0 +1,42 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const http = require('http'); +const { HTTPParser } = require('_http_common'); + +// Test that the `HTTPParser` instance is cleaned up before being returned to +// the pool to avoid memory retention issues. + +const kOnTimeout = HTTPParser.kOnTimeout | 0; +const server = http.createServer(); + +server.on('request', common.mustCall((request, response) => { + const parser = request.socket.parser; + + assert.strictEqual(typeof parser[kOnTimeout], 'function'); + + request.socket.on('close', common.mustCall(() => { + assert.strictEqual(parser[kOnTimeout], null); + })); + + response.end(); + server.close(); +})); + +server.listen(common.mustCall(() => { + const request = http.get({ port: server.address().port }); + let parser; + + request.on('socket', common.mustCall(() => { + parser = request.parser; + assert.strictEqual(typeof parser.onIncoming, 'function'); + })); + + request.on('response', common.mustCall((response) => { + response.resume(); + response.on('end', common.mustCall(() => { + assert.strictEqual(parser.onIncoming, null); + })); + })); +})); diff --git a/test/parallel/test-http-pause-resume-one-end.js b/test/parallel/test-http-pause-resume-one-end.js index 4886a7d490e413..34bf3be478f09c 100644 --- a/test/parallel/test-http-pause-resume-one-end.js +++ b/test/parallel/test-http-pause-resume-one-end.js @@ -22,6 +22,7 @@ 'use strict'; const common = require('../common'); const http = require('http'); +const assert = require('assert'); const server = http.Server(function(req, res) { res.writeHead(200, { 'Content-Type': 'text/plain' }); @@ -43,6 +44,12 @@ server.listen(0, common.mustCall(function() { }); })); - res.on('end', common.mustCall()); + res.on('end', common.mustCall(() => { + assert.strictEqual(res.destroyed, false); + })); + assert.strictEqual(res.destroyed, false); + res.on('close', common.mustCall(() => { + assert.strictEqual(res.destroyed, true); + })); })); })); diff --git a/test/parallel/test-http-req-res-close.js b/test/parallel/test-http-req-res-close.js index daba55f43427c2..329515ccd76ffb 100644 --- a/test/parallel/test-http-req-res-close.js +++ b/test/parallel/test-http-req-res-close.js @@ -8,13 +8,25 @@ const server = http.Server(common.mustCall((req, res) => { let resClosed = false; res.end(); + let resFinished = false; res.on('finish', common.mustCall(() => { + resFinished = true; + assert.strictEqual(resClosed, false); + assert.strictEqual(res.destroyed, false); assert.strictEqual(resClosed, false); })); + assert.strictEqual(req.destroyed, false); res.on('close', common.mustCall(() => { resClosed = true; + assert.strictEqual(resFinished, true); + assert.strictEqual(res.destroyed, true); + })); + assert.strictEqual(req.destroyed, false); + req.on('end', common.mustCall(() => { + assert.strictEqual(req.destroyed, false); })); req.on('close', common.mustCall(() => { + assert.strictEqual(req.destroyed, true); assert.strictEqual(req._readableState.ended, true); })); res.socket.on('close', () => server.close()); diff --git a/test/parallel/test-http-response-close.js b/test/parallel/test-http-response-close.js index 4c36003357980b..0435cd0ee37da5 100644 --- a/test/parallel/test-http-response-close.js +++ b/test/parallel/test-http-response-close.js @@ -22,6 +22,7 @@ 'use strict'; const common = require('../common'); const http = require('http'); +const assert = require('assert'); { const server = http.createServer( @@ -39,7 +40,9 @@ const http = require('http'); res.on('data', common.mustCall(() => { res.destroy(); })); + assert.strictEqual(res.destroyed, false); res.on('close', common.mustCall(() => { + assert.strictEqual(res.destroyed, true); server.close(); })); }) @@ -61,7 +64,12 @@ const http = require('http'); http.get( { port: server.address().port }, common.mustCall((res) => { + assert.strictEqual(res.destroyed, false); + res.on('end', common.mustCall(() => { + assert.strictEqual(res.destroyed, false); + })); res.on('close', common.mustCall(() => { + assert.strictEqual(res.destroyed, true); server.close(); })); res.resume(); diff --git a/test/parallel/test-http-server-stale-close.js b/test/parallel/test-http-server-stale-close.js index d67c4d31c36e37..b9322ed9fcf83a 100644 --- a/test/parallel/test-http-server-stale-close.js +++ b/test/parallel/test-http-server-stale-close.js @@ -23,6 +23,7 @@ require('../common'); const http = require('http'); const fork = require('child_process').fork; +const assert = require('assert'); if (process.env.NODE_TEST_FORK_PORT) { const req = http.request({ @@ -37,7 +38,9 @@ if (process.env.NODE_TEST_FORK_PORT) { const server = http.createServer((req, res) => { res.writeHead(200, { 'Content-Length': '42' }); req.pipe(res); + assert.strictEqual(req.destroyed, false); req.on('close', () => { + assert.strictEqual(req.destroyed, true); server.close(); res.end(); }); diff --git a/test/parallel/test-http2-byteswritten-server.js b/test/parallel/test-http2-byteswritten-server.js new file mode 100644 index 00000000000000..3077687fbf9a3b --- /dev/null +++ b/test/parallel/test-http2-byteswritten-server.js @@ -0,0 +1,28 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); +const assert = require('assert'); +const http2 = require('http2'); + +const http2Server = http2.createServer(common.mustCall(function(req, res) { + res.socket.on('finish', common.mustCall(() => { + assert(req.socket.bytesWritten > 0); // 1094 + })); + res.writeHead(200, { 'Content-Type': 'text/plain' }); + res.write(Buffer.from('1'.repeat(1024))); + res.end(); +})); + +http2Server.listen(0, common.mustCall(function() { + const URL = `http://localhost:${http2Server.address().port}`; + const http2client = http2.connect(URL, { protocol: 'http:' }); + const req = http2client.request({ ':method': 'GET', ':path': '/' }); + req.on('data', common.mustCall()); + req.on('end', common.mustCall(function() { + http2client.close(); + http2Server.close(); + })); + req.end(); +})); diff --git a/test/parallel/test-http2-connect.js b/test/parallel/test-http2-connect.js index 6f62f55a93b7f2..9ee2e4347f600b 100644 --- a/test/parallel/test-http2-connect.js +++ b/test/parallel/test-http2-connect.js @@ -9,9 +9,11 @@ const { } = require('../common'); if (!hasCrypto) skip('missing crypto'); +const fixtures = require('../common/fixtures'); const assert = require('assert'); -const { createServer, connect } = require('http2'); +const { createServer, createSecureServer, connect } = require('http2'); const { connect: netConnect } = require('net'); +const { connect: tlsConnect } = require('tls'); // Check for session connect callback and event { @@ -70,6 +72,36 @@ const { connect: netConnect } = require('net'); connect(authority).on('error', () => {}); } +// Check for session connect callback on already connected TLS socket +{ + const serverOptions = { + key: fixtures.readKey('agent1-key.pem'), + cert: fixtures.readKey('agent1-cert.pem') + }; + const server = createSecureServer(serverOptions); + server.listen(0, mustCall(() => { + const { port } = server.address(); + + const onSocketConnect = () => { + const authority = `https://localhost:${port}`; + const createConnection = mustCall(() => socket); + const options = { createConnection }; + connect(authority, options, mustCall(onSessionConnect)); + }; + + const onSessionConnect = (session) => { + session.close(); + server.close(); + }; + + const clientOptions = { + port, + rejectUnauthorized: false + }; + const socket = tlsConnect(clientOptions, mustCall(onSocketConnect)); + })); +} + // Check for error for init settings error { createServer(function() { diff --git a/test/parallel/test-internal-module-wrap.js b/test/parallel/test-internal-module-wrap.js index b0cc3a1cf02d8a..09cccba76de004 100644 --- a/test/parallel/test-internal-module-wrap.js +++ b/test/parallel/test-internal-module-wrap.js @@ -10,7 +10,7 @@ const { ModuleWrap } = internalBinding('module_wrap'); const { getPromiseDetails, isPromise } = internalBinding('util'); const setTimeoutAsync = require('util').promisify(setTimeout); -const foo = new ModuleWrap('foo', undefined, 'export * from "bar"; 6;', 0, 0); +const foo = new ModuleWrap('foo', undefined, 'export * from "bar";', 0, 0); const bar = new ModuleWrap('bar', undefined, 'export const five = 5', 0, 0); (async () => { @@ -24,6 +24,6 @@ const bar = new ModuleWrap('bar', undefined, 'export const five = 5', 0, 0); foo.instantiate(); - assert.strictEqual(await foo.evaluate(-1, false), 6); + assert.strictEqual(await foo.evaluate(-1, false), undefined); assert.strictEqual(foo.getNamespace().five, 5); })(); diff --git a/test/parallel/test-module-circular-dependency-warning.js b/test/parallel/test-module-circular-dependency-warning.js index 1fe82c2b0288d5..6e2924c45eefff 100644 --- a/test/parallel/test-module-circular-dependency-warning.js +++ b/test/parallel/test-module-circular-dependency-warning.js @@ -38,3 +38,8 @@ assert.strictEqual(esmTranspiledExport.__esModule, true); const halfTranspiledExport = require(fixtures.path('cycles', 'warning-esm-half-transpiled-a.js')); assert.strictEqual(halfTranspiledExport.__esModule, undefined); + +// No circular check is done to prevent triggering proxy traps, if +// module.exports is set to a proxy that contains a `getPrototypeOf` or +// `setPrototypeOf` trap. +require(fixtures.path('cycles', 'warning-skip-proxy-traps-a.js')); diff --git a/test/parallel/test-module-cjs-helpers.js b/test/parallel/test-module-cjs-helpers.js deleted file mode 100644 index 12de65598e54e1..00000000000000 --- a/test/parallel/test-module-cjs-helpers.js +++ /dev/null @@ -1,9 +0,0 @@ -'use strict'; -// Flags: --expose-internals - -require('../common'); -const assert = require('assert'); -const { builtinLibs } = require('internal/modules/cjs/helpers'); - -const expectedLibs = process.features.inspector ? 34 : 33; -assert.strictEqual(builtinLibs.length, expectedLibs); diff --git a/test/parallel/test-net-pingpong.js b/test/parallel/test-net-pingpong.js index 99a02eda22fb1d..e87ee10e43df84 100644 --- a/test/parallel/test-net-pingpong.js +++ b/test/parallel/test-net-pingpong.js @@ -103,10 +103,9 @@ function pingPongTest(port, host) { assert.strictEqual(client.writable, false); assert.strictEqual(client.readable, true); return; - } else { - assert.strictEqual(client.writable, true); - assert.strictEqual(client.readable, true); } + assert.strictEqual(client.writable, true); + assert.strictEqual(client.readable, true); if (count < N) { client.write('PING'); diff --git a/test/parallel/test-performanceobserver.js b/test/parallel/test-performanceobserver.js index c68de859b6b654..3b2f94411f3df3 100644 --- a/test/parallel/test-performanceobserver.js +++ b/test/parallel/test-performanceobserver.js @@ -58,7 +58,7 @@ assert.strictEqual(counts[NODE_PERFORMANCE_ENTRY_TYPE_FUNCTION], 0); { code: 'ERR_INVALID_OPT_VALUE', name: 'TypeError', - message: 'The value "[object Object]" is invalid ' + + message: `The value "${i}" is invalid ` + 'for option "entryTypes"' }); }); diff --git a/test/parallel/test-readable-from.js b/test/parallel/test-readable-from.js index 6cc9216a306378..94bc2c1ae4b926 100644 --- a/test/parallel/test-readable-from.js +++ b/test/parallel/test-readable-from.js @@ -159,6 +159,29 @@ async function asTransformStream() { } } +async function endWithError() { + async function* generate() { + yield 1; + yield 2; + yield Promise.reject('Boum'); + } + + const stream = Readable.from(generate()); + + const expected = [1, 2]; + + try { + for await (const chunk of stream) { + strictEqual(chunk, expected.shift()); + } + throw new Error(); + } catch (err) { + strictEqual(expected.length, 0); + strictEqual(err, 'Boum'); + } +} + + Promise.all([ toReadableBasicSupport(), toReadableSyncIterator(), @@ -168,5 +191,6 @@ Promise.all([ toReadableOnData(), toReadableOnDataNonObject(), destroysTheStreamWhenThrowing(), - asTransformStream() + asTransformStream(), + endWithError() ]).then(mustCall()); diff --git a/test/parallel/test-readline-interface.js b/test/parallel/test-readline-interface.js index 59a65e8ca2020e..e7247a65c04319 100644 --- a/test/parallel/test-readline-interface.js +++ b/test/parallel/test-readline-interface.js @@ -22,6 +22,7 @@ // Flags: --expose-internals 'use strict'; const common = require('../common'); +common.skipIfDumbTerminal(); const assert = require('assert'); const readline = require('readline'); diff --git a/test/parallel/test-readline-position.js b/test/parallel/test-readline-position.js index 88e4d6104b5047..f01786eaf19d3c 100644 --- a/test/parallel/test-readline-position.js +++ b/test/parallel/test-readline-position.js @@ -1,6 +1,6 @@ // Flags: --expose-internals 'use strict'; -require('../common'); +const common = require('../common'); const { internalBinding } = require('internal/test/binding'); const { PassThrough } = require('stream'); const readline = require('readline'); @@ -8,6 +8,8 @@ const assert = require('assert'); const ctrlU = { ctrl: true, name: 'u' }; +common.skipIfDumbTerminal(); + { const input = new PassThrough(); const rl = readline.createInterface({ diff --git a/test/parallel/test-readline-tab-complete.js b/test/parallel/test-readline-tab-complete.js index d7a4bb7a9a0690..e8871863402cb1 100644 --- a/test/parallel/test-readline-tab-complete.js +++ b/test/parallel/test-readline-tab-complete.js @@ -8,6 +8,8 @@ const assert = require('assert'); const EventEmitter = require('events').EventEmitter; const { getStringWidth } = require('internal/util/inspect'); +common.skipIfDumbTerminal(); + // This test verifies that the tab completion supports unicode and the writes // are limited to the minimum. [ diff --git a/test/parallel/test-readline-undefined-columns.js b/test/parallel/test-readline-undefined-columns.js index 40fe2c16d609e9..f1ef7b5bba2eee 100644 --- a/test/parallel/test-readline-undefined-columns.js +++ b/test/parallel/test-readline-undefined-columns.js @@ -5,6 +5,8 @@ const assert = require('assert'); const PassThrough = require('stream').PassThrough; const readline = require('readline'); +common.skipIfDumbTerminal(); + // Checks that tab completion still works // when output column size is undefined diff --git a/test/parallel/test-readline.js b/test/parallel/test-readline.js index d464fdc440c58b..b336996cd2e53e 100644 --- a/test/parallel/test-readline.js +++ b/test/parallel/test-readline.js @@ -4,6 +4,8 @@ const { PassThrough } = require('stream'); const readline = require('readline'); const assert = require('assert'); +common.skipIfDumbTerminal(); + { const input = new PassThrough(); const rl = readline.createInterface({ diff --git a/test/parallel/test-repl-editor.js b/test/parallel/test-repl-editor.js index 6871fbdcb1a882..41685f06e72c06 100644 --- a/test/parallel/test-repl-editor.js +++ b/test/parallel/test-repl-editor.js @@ -1,10 +1,12 @@ 'use strict'; -require('../common'); +const common = require('../common'); const assert = require('assert'); const repl = require('repl'); const ArrayStream = require('../common/arraystream'); +common.skipIfDumbTerminal(); + // \u001b[nG - Moves the cursor to n st column // \u001b[0J - Clear screen // \u001b[0K - Clear to line end diff --git a/test/parallel/test-repl-history-navigation.js b/test/parallel/test-repl-history-navigation.js index 8eda8e3ceceeef..9155ad722b8710 100644 --- a/test/parallel/test-repl-history-navigation.js +++ b/test/parallel/test-repl-history-navigation.js @@ -10,9 +10,13 @@ const fs = require('fs'); const path = require('path'); const { inspect } = require('util'); +common.skipIfDumbTerminal(); + const tmpdir = require('../common/tmpdir'); tmpdir.refresh(); +process.throwDeprecation = true; + const defaultHistoryPath = path.join(tmpdir.path, '.node_repl_history'); // Create an input stream specialized for testing an array of actions @@ -55,6 +59,7 @@ const WORD_RIGHT = { name: 'right', ctrl: true }; const GO_TO_END = { name: 'end' }; const DELETE_WORD_LEFT = { name: 'backspace', ctrl: true }; const SIGINT = { name: 'c', ctrl: true }; +const ESCAPE = { name: 'escape', meta: true }; const prompt = '> '; const WAIT = '€'; @@ -180,8 +185,10 @@ const tests = [ 'veryLongName'.repeat(30), ENTER, `${'\x1B[90m \x1B[39m'.repeat(235)} fun`, + ESCAPE, ENTER, `${' '.repeat(236)} fun`, + ESCAPE, ENTER ], expected: [], @@ -316,6 +323,7 @@ const tests = [ env: { NODE_REPL_HISTORY: defaultHistoryPath }, showEscapeCodes: true, skip: !process.features.inspector, + checkTotal: true, test: [ 'fu', 'n', @@ -329,6 +337,12 @@ const tests = [ BACKSPACE, WORD_LEFT, WORD_RIGHT, + ESCAPE, + ENTER, + UP, + LEFT, + ENTER, + UP, ENTER ], // C = Cursor n forward @@ -377,12 +391,36 @@ const tests = [ '\x1B[0K', '\x1B[7D', '\x1B[10G', ' // n', '\x1B[3G', '\x1B[10G', // 10. Word right. Cleanup '\x1B[0K', '\x1B[3G', '\x1B[7C', ' // n', '\x1B[10G', - '\x1B[0K', - // 11. ENTER + // 11. ESCAPE + '\x1B[0K', ' // n', '\x1B[10G', '\x1B[0K', + // 12. ENTER + '\r\n', + 'Uncaught ReferenceError: functio is not defined\n', + '\x1B[1G', '\x1B[0J', + // 13. UP + prompt, '\x1B[3G', '\x1B[1G', '\x1B[0J', + `${prompt}functio`, '\x1B[10G', + ' // n', '\x1B[10G', + ' // n', '\x1B[10G', + // 14. LEFT + '\x1B[0K', '\x1B[1D', + '\x1B[10G', ' // n', '\x1B[9G', '\x1B[10G', + // 15. ENTER + '\x1B[0K', '\x1B[9G', '\x1B[1C', '\r\n', 'Uncaught ReferenceError: functio is not defined\n', '\x1B[1G', '\x1B[0J', - prompt, '\x1B[3G', '\r\n' + '> ', '\x1B[3G', + // 16. UP + '\x1B[1G', '\x1B[0J', + '> functio', '\x1B[10G', + ' // n', '\x1B[10G', + ' // n', '\x1B[10G', '\x1B[0K', + // 17. ENTER + 'n', '\r\n', + '\x1B[1G', '\x1B[0J', + '... ', '\x1B[5G', + '\r\n' ], clean: true }, diff --git a/test/parallel/test-repl-load-multiline.js b/test/parallel/test-repl-load-multiline.js index b2bee8d6e4647e..4fcf206bef1be1 100644 --- a/test/parallel/test-repl-load-multiline.js +++ b/test/parallel/test-repl-load-multiline.js @@ -1,10 +1,12 @@ 'use strict'; -require('../common'); +const common = require('../common'); const ArrayStream = require('../common/arraystream'); const fixtures = require('../common/fixtures'); const assert = require('assert'); const repl = require('repl'); +common.skipIfDumbTerminal(); + const command = `.load ${fixtures.path('repl-load-multiline.js')}`; const terminalCode = '\u001b[1G\u001b[0J \u001b[1G'; const terminalCodeRegex = new RegExp(terminalCode.replace(/\[/g, '\\['), 'g'); diff --git a/test/parallel/test-repl-mode.js b/test/parallel/test-repl-mode.js index df84d86a3c8dc3..d8131d34f93b44 100644 --- a/test/parallel/test-repl-mode.js +++ b/test/parallel/test-repl-mode.js @@ -7,7 +7,8 @@ const repl = require('repl'); const tests = [ testSloppyMode, testStrictMode, - testAutoMode + testAutoMode, + testStrictModeTerminal, ]; tests.forEach(function(test) { @@ -37,6 +38,22 @@ function testStrictMode() { assert.strictEqual(cli.output.accumulator.join(''), 'undefined\n> '); } +function testStrictModeTerminal() { + if (!process.features.inspector) { + console.warn('Test skipped: V8 inspector is disabled'); + return; + } + // Verify that ReferenceErrors are reported in strict mode previews. + const cli = initRepl(repl.REPL_MODE_STRICT, { + terminal: true + }); + + cli.input.emit('data', 'xyz '); + assert.ok( + cli.output.accumulator.includes('\n// ReferenceError: xyz is not defined') + ); +} + function testAutoMode() { const cli = initRepl(repl.REPL_MODE_MAGIC); @@ -48,7 +65,7 @@ function testAutoMode() { assert.strictEqual(cli.output.accumulator.join(''), 'undefined\n> '); } -function initRepl(mode) { +function initRepl(mode, options) { const input = new Stream(); input.write = input.pause = input.resume = () => {}; input.readable = true; @@ -65,6 +82,7 @@ function initRepl(mode) { output: output, useColors: false, terminal: false, - replMode: mode + replMode: mode, + ...options }); } diff --git a/test/parallel/test-repl-options.js b/test/parallel/test-repl-options.js index 99f9fa8a605142..cb7b2f08b65468 100644 --- a/test/parallel/test-repl-options.js +++ b/test/parallel/test-repl-options.js @@ -19,6 +19,8 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. +// Flags: --pending-deprecation + 'use strict'; const common = require('../common'); const ArrayStream = require('../common/arraystream'); @@ -27,10 +29,15 @@ const repl = require('repl'); const cp = require('child_process'); assert.strictEqual(repl.repl, undefined); +repl._builtinLibs; common.expectWarning({ DeprecationWarning: { - DEP0124: 'REPLServer.rli is deprecated' + DEP0142: + 'repl._builtinLibs is deprecated. Check module.builtinModules instead', + DEP0141: 'repl.inputStream and repl.outputStream is deprecated. ' + + 'Use repl.input and repl.output instead', + DEP0124: 'REPLServer.rli is deprecated', } }); diff --git a/test/parallel/test-repl-persistent-history.js b/test/parallel/test-repl-persistent-history.js index 1d1261a3752365..705a7c7c236fb0 100644 --- a/test/parallel/test-repl-persistent-history.js +++ b/test/parallel/test-repl-persistent-history.js @@ -12,6 +12,8 @@ const path = require('path'); const os = require('os'); const util = require('util'); +common.skipIfDumbTerminal(); + const tmpdir = require('../common/tmpdir'); tmpdir.refresh(); diff --git a/test/parallel/test-repl-preview.js b/test/parallel/test-repl-preview.js index b8dbbf3f9a993d..02c1ec31cd5020 100644 --- a/test/parallel/test-repl-preview.js +++ b/test/parallel/test-repl-preview.js @@ -7,6 +7,7 @@ const { Stream } = require('stream'); const { inspect } = require('util'); common.skipIfInspectorDisabled(); +common.skipIfDumbTerminal(); const PROMPT = 'repl > '; @@ -90,7 +91,11 @@ async function tests(options) { input: 'koo', noPreview: '[Function: koo]', preview: [ - 'k\x1B[90moo\x1B[39m\x1B[9G\x1B[0Ko\x1B[90mo\x1B[39m\x1B[10G\x1B[0Ko', + 'k\x1B[90moo\x1B[39m\x1B[9G', + '\x1B[90m[Function: koo]\x1B[39m\x1B[9G\x1B[1A\x1B[1B\x1B[2K\x1B[1A' + + '\x1B[0Ko\x1B[90mo\x1B[39m\x1B[10G', + '\x1B[90m[Function: koo]\x1B[39m\x1B[10G\x1B[1A\x1B[1B\x1B[2K\x1B[1A' + + '\x1B[0Ko', '\x1B[90m[Function: koo]\x1B[39m\x1B[11G\x1B[1A\x1B[1B\x1B[2K\x1B[1A\r', '\x1B[36m[Function: koo]\x1B[39m' ] diff --git a/test/parallel/test-repl-programmatic-history.js b/test/parallel/test-repl-programmatic-history.js index 5307ae0556ae74..0eccea655263cd 100644 --- a/test/parallel/test-repl-programmatic-history.js +++ b/test/parallel/test-repl-programmatic-history.js @@ -10,6 +10,8 @@ const path = require('path'); const os = require('os'); const util = require('util'); +common.skipIfDumbTerminal(); + const tmpdir = require('../common/tmpdir'); tmpdir.refresh(); diff --git a/test/parallel/test-repl-reverse-search.js b/test/parallel/test-repl-reverse-search.js index 45a7ec327f7232..5027bd7da497fe 100644 --- a/test/parallel/test-repl-reverse-search.js +++ b/test/parallel/test-repl-reverse-search.js @@ -10,6 +10,7 @@ const fs = require('fs'); const path = require('path'); const { inspect } = require('util'); +common.skipIfDumbTerminal(); common.allowGlobals('aaaa'); const tmpdir = require('../common/tmpdir'); diff --git a/test/parallel/test-repl-strict-mode-previews.js b/test/parallel/test-repl-strict-mode-previews.js new file mode 100644 index 00000000000000..8da4029e186b3c --- /dev/null +++ b/test/parallel/test-repl-strict-mode-previews.js @@ -0,0 +1,46 @@ +// Previews in strict mode should indicate ReferenceErrors. + +'use strict'; + +const common = require('../common'); + +common.skipIfInspectorDisabled(); + +if (process.argv[2] === 'child') { + const stream = require('stream'); + const repl = require('repl'); + class ActionStream extends stream.Stream { + readable = true; + run(data) { + this.emit('data', `${data}`); + this.emit('keypress', '', { ctrl: true, name: 'd' }); + } + resume() {} + pause() {} + } + + repl.start({ + input: new ActionStream(), + output: new stream.Writable({ + write(chunk, _, next) { + console.log(chunk.toString()); + next(); + } + }), + useColors: false, + terminal: true + }).inputStream.run('xyz'); +} else { + const assert = require('assert'); + const { spawnSync } = require('child_process'); + + const result = spawnSync( + process.execPath, + ['--use-strict', `${__filename}`, 'child'] + ); + + assert.match( + result.stdout.toString(), + /\/\/ ReferenceError: xyz is not defined/ + ); +} diff --git a/test/parallel/test-repl-tab-complete.js b/test/parallel/test-repl-tab-complete.js index 6cf689c4b11074..c40485ce3f5eac 100644 --- a/test/parallel/test-repl-tab-complete.js +++ b/test/parallel/test-repl-tab-complete.js @@ -30,6 +30,7 @@ const { const assert = require('assert'); const path = require('path'); const fixtures = require('../common/fixtures'); +const { builtinModules } = require('module'); const hasInspector = process.features.inspector; if (!common.isMainThread) @@ -222,29 +223,52 @@ putIn.run(['.clear']); testMe.complete('require(\'', common.mustCall(function(error, data) { assert.strictEqual(error, null); - repl._builtinLibs.forEach(function(lib) { - assert(data[0].includes(lib), `${lib} not found`); + builtinModules.forEach((lib) => { + if (!lib.startsWith('_')) + assert(data[0].includes(lib), `${lib} not found`); }); })); -testMe.complete('require(\'n', common.mustCall(function(error, data) { +testMe.complete("require\t( 'n", common.mustCall(function(error, data) { assert.strictEqual(error, null); assert.strictEqual(data.length, 2); assert.strictEqual(data[1], 'n'); - assert(data[0].includes('net')); + // There is only one Node.js module that starts with n: + assert.strictEqual(data[0][0], 'net'); + assert.strictEqual(data[0][1], ''); // It's possible to pick up non-core modules too - data[0].forEach(function(completion) { - if (completion) - assert(/^n/.test(completion)); + data[0].slice(2).forEach((completion) => { + assert.match(completion, /^n/); }); })); { const expected = ['@nodejsscope', '@nodejsscope/']; + // Require calls should handle all types of quotation marks. + for (const quotationMark of ["'", '"', '`']) { + putIn.run(['.clear']); + testMe.complete('require(`@nodejs', common.mustCall((err, data) => { + assert.strictEqual(err, null); + assert.deepStrictEqual(data, [expected, '@nodejs']); + })); + + putIn.run(['.clear']); + // Completions should not be greedy in case the quotation ends. + const input = `require(${quotationMark}@nodejsscope${quotationMark}`; + testMe.complete(input, common.mustCall((err, data) => { + assert.strictEqual(err, null); + assert.deepStrictEqual(data, [[], undefined]); + })); + } +} + +{ putIn.run(['.clear']); - testMe.complete('require(\'@nodejs', common.mustCall((err, data) => { + // Completions should find modules and handle whitespace after the opening + // bracket. + testMe.complete('require \t("no_ind', common.mustCall((err, data) => { assert.strictEqual(err, null); - assert.deepStrictEqual(data, [expected, '@nodejs']); + assert.deepStrictEqual(data, [['no_index', 'no_index/'], 'no_ind']); })); } diff --git a/test/parallel/test-stream2-readable-empty-buffer-no-eof.js b/test/parallel/test-stream2-readable-empty-buffer-no-eof.js index f1e74ad949c590..7be2c358eedd95 100644 --- a/test/parallel/test-stream2-readable-empty-buffer-no-eof.js +++ b/test/parallel/test-stream2-readable-empty-buffer-no-eof.js @@ -95,8 +95,7 @@ function test2() { r._read = function(n) { if (!reads--) return r.push(null); // EOF - else - return r.push(Buffer.from('x')); + return r.push(Buffer.from('x')); }; const results = []; diff --git a/test/parallel/test-tls-enable-keylog-cli.js b/test/parallel/test-tls-enable-keylog-cli.js index 5d05069b15f87c..128d9a096a0532 100644 --- a/test/parallel/test-tls-enable-keylog-cli.js +++ b/test/parallel/test-tls-enable-keylog-cli.js @@ -24,8 +24,11 @@ const child = fork(__filename, ['test'], { child.on('close', common.mustCall((code, signal) => { assert.strictEqual(code, 0); assert.strictEqual(signal, null); - const log = fs.readFileSync(file, 'utf8'); - assert(/SECRET/.test(log)); + const log = fs.readFileSync(file, 'utf8').trim().split('\n'); + // Both client and server should log their secrets, + // so we should have two identical lines in the log + assert.strictEqual(log.length, 2); + assert.strictEqual(log[0], log[1]); })); function test() { @@ -40,7 +43,9 @@ function test() { }, server: { cert: keys.agent6.cert, - key: keys.agent6.key + key: keys.agent6.key, + // Number of keylog events is dependent on protocol version + maxVersion: 'TLSv1.2', }, }, common.mustCall((err, pair, cleanup) => { if (pair.server.err) { diff --git a/test/parallel/test-trace-atomics-wait.js b/test/parallel/test-trace-atomics-wait.js new file mode 100644 index 00000000000000..4681b77b597b87 --- /dev/null +++ b/test/parallel/test-trace-atomics-wait.js @@ -0,0 +1,79 @@ +'use strict'; +require('../common'); +const assert = require('assert'); +const child_process = require('child_process'); +const { Worker } = require('worker_threads'); + +if (process.argv[2] === 'child') { + const i32arr = new Int32Array(new SharedArrayBuffer(8)); + assert.strictEqual(Atomics.wait(i32arr, 0, 1), 'not-equal'); + assert.strictEqual(Atomics.wait(i32arr, 0, 0, 10), 'timed-out'); + + new Worker(` + const i32arr = require('worker_threads').workerData; + Atomics.store(i32arr, 1, -1); + Atomics.notify(i32arr, 1); + Atomics.wait(i32arr, 1, -1); + `, { eval: true, workerData: i32arr }); + + Atomics.wait(i32arr, 1, 0); + assert.strictEqual(Atomics.load(i32arr, 1), -1); + Atomics.store(i32arr, 1, 0); + Atomics.notify(i32arr, 1); + return; +} + +const proc = child_process.spawnSync( + process.execPath, + [ '--trace-atomics-wait', __filename, 'child' ], + { encoding: 'utf8', stdio: [ 'inherit', 'inherit', 'pipe' ] }); + +if (proc.status !== 0) console.log(proc); +assert.strictEqual(proc.status, 0); + +const SABAddress = proc.stderr.match(/Atomics\.wait\((?.+) \+/).groups.SAB; +const actualTimeline = proc.stderr + .replace(new RegExp(SABAddress, 'g'), '
') + .replace(new RegExp(`\\(node:${proc.pid}\\) `, 'g'), '') + .replace(/\binf(inity)?\b/gi, 'inf') + .replace(/\r/g, '') + .trim(); +console.log('+++ normalized stdout +++'); +console.log(actualTimeline); +console.log('--- normalized stdout ---'); + +const begin = +`[Thread 0] Atomics.wait(
+ 0, 1, inf) started +[Thread 0] Atomics.wait(
+ 0, 1, inf) did not wait because the \ +values mismatched +[Thread 0] Atomics.wait(
+ 0, 0, 10) started +[Thread 0] Atomics.wait(
+ 0, 0, 10) timed out`; + +const expectedTimelines = [ + `${begin} +[Thread 0] Atomics.wait(
+ 4, 0, inf) started +[Thread 1] Atomics.wait(
+ 4, -1, inf) started +[Thread 0] Atomics.wait(
+ 4, 0, inf) was woken up by another thread +[Thread 1] Atomics.wait(
+ 4, -1, inf) was woken up by another thread`, + `${begin} +[Thread 0] Atomics.wait(
+ 4, 0, inf) started +[Thread 0] Atomics.wait(
+ 4, 0, inf) was woken up by another thread +[Thread 1] Atomics.wait(
+ 4, -1, inf) started +[Thread 1] Atomics.wait(
+ 4, -1, inf) did not wait because the \ +values mismatched`, + `${begin} +[Thread 0] Atomics.wait(
+ 4, 0, inf) started +[Thread 1] Atomics.wait(
+ 4, -1, inf) started +[Thread 0] Atomics.wait(
+ 4, 0, inf) was woken up by another thread +[Thread 1] Atomics.wait(
+ 4, -1, inf) did not wait because the \ +values mismatched`, + `${begin} +[Thread 0] Atomics.wait(
+ 4, 0, inf) started +[Thread 0] Atomics.wait(
+ 4, 0, inf) did not wait because the \ +values mismatched +[Thread 1] Atomics.wait(
+ 4, -1, inf) started +[Thread 1] Atomics.wait(
+ 4, -1, inf) did not wait because the \ +values mismatched` +]; + +assert(expectedTimelines.includes(actualTimeline)); diff --git a/test/parallel/test-trace-events-api.js b/test/parallel/test-trace-events-api.js index 676e7f31e13710..e45f374bab642c 100644 --- a/test/parallel/test-trace-events-api.js +++ b/test/parallel/test-trace-events-api.js @@ -25,9 +25,8 @@ function getEnabledCategoriesFromCommandLine() { const indexOfCatFlag = process.execArgv.indexOf('--trace-event-categories'); if (indexOfCatFlag === -1) { return undefined; - } else { - return process.execArgv[indexOfCatFlag + 1]; } + return process.execArgv[indexOfCatFlag + 1]; } const isChild = process.argv[2] === 'child'; diff --git a/test/parallel/test-vm-module-basic.js b/test/parallel/test-vm-module-basic.js index 26751fd0b58e31..3e5e7759c1a9cb 100644 --- a/test/parallel/test-vm-module-basic.js +++ b/test/parallel/test-vm-module-basic.js @@ -8,8 +8,7 @@ const { Module, SourceTextModule, SyntheticModule, - createContext, - compileFunction, + createContext } = require('vm'); const util = require('util'); @@ -26,26 +25,26 @@ const util = require('util'); assert.strictEqual(m.status, 'unlinked'); await m.link(common.mustNotCall()); assert.strictEqual(m.status, 'linked'); - const result = await m.evaluate(); + assert.strictEqual(await m.evaluate(), undefined); assert.strictEqual(m.status, 'evaluated'); - assert.strictEqual(Object.getPrototypeOf(result), null); assert.deepStrictEqual(context, { foo: 'bar', baz: 'bar', typeofProcess: 'undefined' }); - assert.strictEqual(result.result, 'function'); }()); (async () => { - const m = new SourceTextModule( - 'global.vmResult = "foo"; Object.prototype.toString.call(process);' - ); + const m = new SourceTextModule(` + global.vmResultFoo = "foo"; + global.vmResultTypeofProcess = Object.prototype.toString.call(process); + `); await m.link(common.mustNotCall()); - const { result } = await m.evaluate(); - assert.strictEqual(global.vmResult, 'foo'); - assert.strictEqual(result, '[object process]'); - delete global.vmResult; + await m.evaluate(); + assert.strictEqual(global.vmResultFoo, 'foo'); + assert.strictEqual(global.vmResultTypeofProcess, '[object process]'); + delete global.vmResultFoo; + delete global.vmResultTypeofProcess; })(); (async () => { @@ -158,19 +157,3 @@ const util = require('util'); name: 'TypeError' }); } - -// Test compileFunction importModuleDynamically -{ - const module = new SyntheticModule([], () => {}); - module.link(() => {}); - const f = compileFunction('return import("x")', [], { - importModuleDynamically(specifier, referrer) { - assert.strictEqual(specifier, 'x'); - assert.strictEqual(referrer, f); - return module; - }, - }); - f().then((ns) => { - assert.strictEqual(ns, module.namespace); - }); -} diff --git a/test/parallel/test-vm-module-dynamic-import.js b/test/parallel/test-vm-module-dynamic-import.js index 70229b3897874b..9d04cf96e6f979 100644 --- a/test/parallel/test-vm-module-dynamic-import.js +++ b/test/parallel/test-vm-module-dynamic-import.js @@ -5,19 +5,23 @@ const common = require('../common'); const assert = require('assert'); -const { Script, SourceTextModule, createContext } = require('vm'); +const { Script, SourceTextModule } = require('vm'); async function testNoCallback() { - const m = new SourceTextModule('import("foo")', { context: createContext() }); + const m = new SourceTextModule(` + globalThis.importResult = import("foo"); + globalThis.importResult.catch(() => {}); + `); await m.link(common.mustNotCall()); - const { result } = await m.evaluate(); + await m.evaluate(); let threw = false; try { - await result; + await globalThis.importResult; } catch (err) { threw = true; assert.strictEqual(err.code, 'ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING'); } + delete globalThis.importResult; assert(threw); } @@ -40,7 +44,7 @@ async function test() { } { - const m = new SourceTextModule('import("foo")', { + const m = new SourceTextModule('globalThis.fooResult = import("foo")', { importModuleDynamically: common.mustCall((specifier, wrap) => { assert.strictEqual(specifier, 'foo'); assert.strictEqual(wrap, m); @@ -48,24 +52,26 @@ async function test() { }), }); await m.link(common.mustNotCall()); - const { result } = await m.evaluate(); - assert.strictEqual(foo.namespace, await result); + await m.evaluate(); + assert.strictEqual(foo.namespace, await globalThis.fooResult); + delete globalThis.fooResult; } } async function testInvalid() { - const m = new SourceTextModule('import("foo")', { + const m = new SourceTextModule('globalThis.fooResult = import("foo")', { importModuleDynamically: common.mustCall((specifier, wrap) => { return 5; }), }); await m.link(common.mustNotCall()); - const { result } = await m.evaluate(); - await result.catch(common.mustCall((e) => { + await m.evaluate(); + await globalThis.fooResult.catch(common.mustCall((e) => { assert.strictEqual(e.code, 'ERR_VM_MODULE_NOT_MODULE'); })); + delete globalThis.fooResult; - const s = new Script('import("foo")', { + const s = new Script('import("bar")', { importModuleDynamically: common.mustCall((specifier, wrap) => { return undefined; }), diff --git a/test/parallel/test-vm-module-dynamic-namespace.js b/test/parallel/test-vm-module-dynamic-namespace.js index 987b21f2ec1151..84937cd78de4af 100644 --- a/test/parallel/test-vm-module-dynamic-namespace.js +++ b/test/parallel/test-vm-module-dynamic-namespace.js @@ -9,22 +9,18 @@ const assert = require('assert'); const { types } = require('util'); const { SourceTextModule } = require('vm'); -async function getNamespace() { - const m = new SourceTextModule(''); - await m.link(() => 0); - await m.evaluate(); - return m.namespace; -} - (async () => { - const namespace = await getNamespace(); - const m = new SourceTextModule('export const A = "A"; import("");', { - importModuleDynamically: common.mustCall((specifier, wrap) => { - return namespace; - }) + const m = new SourceTextModule('globalThis.importResult = import("");', { + importModuleDynamically: common.mustCall(async (specifier, wrap) => { + const m = new SourceTextModule(''); + await m.link(() => 0); + await m.evaluate(); + return m.namespace; + }), }); await m.link(() => 0); - const { result } = await m.evaluate(); - const ns = await result; + await m.evaluate(); + const ns = await globalThis.importResult; + delete globalThis.importResult; assert.ok(types.isModuleNamespaceObject(ns)); })().then(common.mustCall()); diff --git a/test/parallel/test-vm-module-errors.js b/test/parallel/test-vm-module-errors.js index d14296b1e9ebde..fee243f101113b 100644 --- a/test/parallel/test-vm-module-errors.js +++ b/test/parallel/test-vm-module-errors.js @@ -182,13 +182,11 @@ async function checkExecution() { await (async () => { const m = new SourceTextModule('throw new Error();'); await m.link(common.mustNotCall()); - const evaluatePromise = m.evaluate(); - await evaluatePromise.catch(() => {}); - assert.strictEqual(m.status, 'errored'); try { - await evaluatePromise; + await m.evaluate(); } catch (err) { assert.strictEqual(m.error, err); + assert.strictEqual(m.status, 'errored'); return; } assert.fail('Missing expected exception'); diff --git a/test/parallel/test-vm-module-import-meta.js b/test/parallel/test-vm-module-import-meta.js index 0f86f2fa646914..baf6c5b37d1b3b 100644 --- a/test/parallel/test-vm-module-import-meta.js +++ b/test/parallel/test-vm-module-import-meta.js @@ -7,14 +7,16 @@ const assert = require('assert'); const { SourceTextModule } = require('vm'); async function testBasic() { - const m = new SourceTextModule('import.meta;', { + const m = new SourceTextModule('globalThis.importMeta = import.meta;', { initializeImportMeta: common.mustCall((meta, module) => { assert.strictEqual(module, m); meta.prop = 42; }) }); await m.link(common.mustNotCall()); - const { result } = await m.evaluate(); + await m.evaluate(); + const result = globalThis.importMeta; + delete globalThis.importMeta; assert.strictEqual(typeof result, 'object'); assert.strictEqual(Object.getPrototypeOf(result), null); assert.strictEqual(result.prop, 42); diff --git a/test/parallel/test-vm-module-link.js b/test/parallel/test-vm-module-link.js index 56443e3e1a73bc..48f06439b6dacf 100644 --- a/test/parallel/test-vm-module-link.js +++ b/test/parallel/test-vm-module-link.js @@ -13,7 +13,8 @@ async function simple() { const foo = new SourceTextModule('export default 5;'); await foo.link(common.mustNotCall()); - const bar = new SourceTextModule('import five from "foo"; five'); + globalThis.fiveResult = undefined; + const bar = new SourceTextModule('import five from "foo"; fiveResult = five'); assert.deepStrictEqual(bar.dependencySpecifiers, ['foo']); @@ -23,7 +24,9 @@ async function simple() { return foo; })); - assert.strictEqual((await bar.evaluate()).result, 5); + await bar.evaluate(); + assert.strictEqual(globalThis.fiveResult, 5); + delete globalThis.fiveResult; } async function depth() { diff --git a/test/parallel/test-vm-module-reevaluate.js b/test/parallel/test-vm-module-reevaluate.js index 4767541dd24c37..6208f140ffab88 100644 --- a/test/parallel/test-vm-module-reevaluate.js +++ b/test/parallel/test-vm-module-reevaluate.js @@ -12,11 +12,16 @@ const finished = common.mustCall(); (async function main() { { - const m = new SourceTextModule('1'); + globalThis.count = 0; + const m = new SourceTextModule('count += 1;'); await m.link(common.mustNotCall()); - assert.strictEqual((await m.evaluate()).result, 1); - assert.strictEqual((await m.evaluate()).result, undefined); - assert.strictEqual((await m.evaluate()).result, undefined); + assert.strictEqual(await m.evaluate(), undefined); + assert.strictEqual(globalThis.count, 1); + assert.strictEqual(await m.evaluate(), undefined); + assert.strictEqual(globalThis.count, 1); + assert.strictEqual(await m.evaluate(), undefined); + assert.strictEqual(globalThis.count, 1); + delete globalThis.count; } { diff --git a/test/parallel/test-vm-module-synthetic.js b/test/parallel/test-vm-module-synthetic.js index 83a78f2f3f5ba2..a3ca6630f7eab4 100644 --- a/test/parallel/test-vm-module-synthetic.js +++ b/test/parallel/test-vm-module-synthetic.js @@ -2,7 +2,7 @@ // Flags: --experimental-vm-modules -require('../common'); +const common = require('../common'); const { SyntheticModule, SourceTextModule } = require('vm'); const assert = require('assert'); @@ -26,6 +26,17 @@ const assert = require('assert'); assert.strictEqual(m.namespace.getX(), 42); } + { + const s = new SyntheticModule([], () => { + const p = Promise.reject(); + p.catch(() => {}); + return p; + }); + + await s.link(common.mustNotCall()); + assert.strictEqual(await s.evaluate(), undefined); + } + for (const invalidName of [1, Symbol.iterator, {}, [], null, true, 0]) { const s = new SyntheticModule([], () => {}); await s.link(() => {}); diff --git a/test/parallel/test-whatwg-url-custom-searchparams-stringifier.js b/test/parallel/test-whatwg-url-custom-searchparams-stringifier.js index 1fe936f5e293ab..35307fa914975a 100644 --- a/test/parallel/test-whatwg-url-custom-searchparams-stringifier.js +++ b/test/parallel/test-whatwg-url-custom-searchparams-stringifier.js @@ -16,3 +16,12 @@ const URLSearchParams = require('url').URLSearchParams; message: 'Value of "this" must be of type URLSearchParams' }); } + +// The URLSearchParams stringifier mutates the base URL using +// different percent-encoding rules than the URL itself. +{ + const myUrl = new URL('https://example.org?foo=~bar'); + assert.strictEqual(myUrl.search, '?foo=~bar'); + myUrl.searchParams.sort(); + assert.strictEqual(myUrl.search, '?foo=%7Ebar'); +} diff --git a/test/parallel/test-worker-unref-from-message-during-exit.js b/test/parallel/test-worker-unref-from-message-during-exit.js new file mode 100644 index 00000000000000..3e696f369e4179 --- /dev/null +++ b/test/parallel/test-worker-unref-from-message-during-exit.js @@ -0,0 +1,16 @@ +'use strict'; +const common = require('../common'); +const { Worker } = require('worker_threads'); + +// This used to crash because the `.unref()` was unexpected while the Worker +// was exiting. + +const w = new Worker(` +require('worker_threads').parentPort.postMessage({}); +`, { eval: true }); +w.on('message', common.mustCall(() => { + w.unref(); +})); + +// Wait a bit so that the 'message' event is emitted while the Worker exits. +Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 100); diff --git a/test/parallel/test-zlib-failed-init.js b/test/parallel/test-zlib-failed-init.js index 1f99a378fc6eda..95f401a3718f30 100644 --- a/test/parallel/test-zlib-failed-init.js +++ b/test/parallel/test-zlib-failed-init.js @@ -21,7 +21,7 @@ assert.throws( code: 'ERR_OUT_OF_RANGE', name: 'RangeError', message: 'The value of "options.windowBits" is out of range. It must ' + - 'be >= 8 and <= 15. Received 0' + 'be >= 9 and <= 15. Received 0' } ); diff --git a/test/parallel/test-zlib-zero-windowBits.js b/test/parallel/test-zlib-zero-windowBits.js index 730690a07c423f..a27fd6734a5425 100644 --- a/test/parallel/test-zlib-zero-windowBits.js +++ b/test/parallel/test-zlib-zero-windowBits.js @@ -28,6 +28,6 @@ const zlib = require('zlib'); code: 'ERR_OUT_OF_RANGE', name: 'RangeError', message: 'The value of "options.windowBits" is out of range. ' + - 'It must be >= 8 and <= 15. Received 0' + 'It must be >= 9 and <= 15. Received 0' }); } diff --git a/test/parallel/test-zlib.js b/test/parallel/test-zlib.js index 0d21cf6cc29e58..65050b85a036cf 100644 --- a/test/parallel/test-zlib.js +++ b/test/parallel/test-zlib.js @@ -27,6 +27,14 @@ const stream = require('stream'); const fs = require('fs'); const fixtures = require('../common/fixtures'); +// Should not segfault. +assert.throws(() => zlib.gzipSync(Buffer.alloc(0), { windowBits: 8 }), { + code: 'ERR_OUT_OF_RANGE', + name: 'RangeError', + message: 'The value of "options.windowBits" is out of range. ' + + 'It must be >= 9 and <= 15. Received 8', +}); + let zlibPairs = [ [zlib.Deflate, zlib.Inflate], [zlib.Gzip, zlib.Gunzip], diff --git a/test/pummel/test-net-pingpong.js b/test/pummel/test-net-pingpong.js index b9507d519d8e6d..f21160a1fa2a4d 100644 --- a/test/pummel/test-net-pingpong.js +++ b/test/pummel/test-net-pingpong.js @@ -88,9 +88,8 @@ function pingPongTest(host, on_complete) { if (sent_final_ping) { assert.strictEqual(client.readyState, 'readOnly'); return; - } else { - assert.strictEqual(client.readyState, 'open'); } + assert.strictEqual(client.readyState, 'open'); if (count < N) { client.write('PING'); diff --git a/test/pummel/test-net-throttle.js b/test/pummel/test-net-throttle.js index 9708d69f9621a3..c51272a09492d4 100644 --- a/test/pummel/test-net-throttle.js +++ b/test/pummel/test-net-throttle.js @@ -23,44 +23,53 @@ require('../common'); const assert = require('assert'); const net = require('net'); +const debuglog = require('util').debuglog('test'); -const N = 1024 * 1024; -const part_N = N / 3; let chars_recved = 0; let npauses = 0; - -console.log('build big string'); -const body = 'C'.repeat(N); +let totalLength = 0; const server = net.createServer((connection) => { - connection.write(body.slice(0, part_N)); - connection.write(body.slice(part_N, 2 * part_N)); - assert.strictEqual(connection.write(body.slice(2 * part_N, N)), false); - console.log(`bufferSize: ${connection.bufferSize}`, 'expecting', N); - assert.ok(connection.bufferSize >= 0 && - connection.writableLength <= N); + const body = 'C'.repeat(1024); + let n = 1; + debuglog('starting write loop'); + while (connection.write(body)) { + n++; + } + debuglog('ended write loop'); + // Now that we're throttled, do some more writes to make sure the data isn't + // lost. + connection.write(body); + connection.write(body); + n += 2; + totalLength = n * body.length; + assert.ok(connection.bufferSize >= 0, `bufferSize: ${connection.bufferSize}`); + assert.ok( + connection.writableLength <= totalLength, + `writableLength: ${connection.writableLength}, totalLength: ${totalLength}` + ); connection.end(); }); server.listen(0, () => { const port = server.address().port; - console.log(`server started on port ${port}`); + debuglog(`server started on port ${port}`); let paused = false; const client = net.createConnection(port); client.setEncoding('ascii'); client.on('data', (d) => { chars_recved += d.length; - console.log(`got ${chars_recved}`); + debuglog(`got ${chars_recved}`); if (!paused) { client.pause(); npauses += 1; paused = true; - console.log('pause'); + debuglog('pause'); const x = chars_recved; setTimeout(() => { assert.strictEqual(chars_recved, x); client.resume(); - console.log('resume'); + debuglog('resume'); paused = false; }, 100); } @@ -74,6 +83,6 @@ server.listen(0, () => { process.on('exit', () => { - assert.strictEqual(chars_recved, N); + assert.strictEqual(chars_recved, totalLength); assert.strictEqual(npauses > 2, true); }); diff --git a/test/sequential/test-util-debug.js b/test/sequential/test-util-debug.js index f791eb8a8d2513..6cad46f101c0af 100644 --- a/test/sequential/test-util-debug.js +++ b/test/sequential/test-util-debug.js @@ -117,6 +117,7 @@ function child(section) { Object.defineProperty(process.stderr, 'hasColors', { value: tty.WriteStream.prototype.hasColors }); + // eslint-disable-next-line no-restricted-syntax const debug = util.debuglog(section); debug('this', { is: 'a' }, /debugging/); debug('num=%d str=%s obj=%j', 1, 'a', { foo: 'bar' }); diff --git a/test/wasi/test-wasi-not-started.js b/test/wasi/test-wasi-not-started.js new file mode 100644 index 00000000000000..ad13e6d711802b --- /dev/null +++ b/test/wasi/test-wasi-not-started.js @@ -0,0 +1,40 @@ +'use strict'; +require('../common'); + +if (process.argv[2] === 'wasi-child') { + const assert = require('assert'); + const fs = require('fs'); + const path = require('path'); + + const { WASI } = require('wasi'); + const wasi = new WASI({ + args: ['foo', '-bar', '--baz=value'] + }); + const importObject = { wasi_snapshot_preview1: wasi.wasiImport }; + + const modulePath = path.join(__dirname, 'wasm', 'main_args.wasm'); + const buffer = fs.readFileSync(modulePath); + + assert.rejects(async () => { + const { instance } = await WebAssembly.instantiate(buffer, importObject); + instance.exports._start(); + }, { + name: 'Error', + code: 'ERR_WASI_NOT_STARTED', + message: 'wasi.start() has not been called' + }); +} else { + const assert = require('assert'); + const cp = require('child_process'); + + const child = cp.spawnSync(process.execPath, [ + '--experimental-wasi-unstable-preview1', + '--experimental-wasm-bigint', + __filename, + 'wasi-child' + ], { + env: { ...process.env, NODE_DEBUG_NATIVE: 'wasi' } + }); + assert.strictEqual(child.signal, null); + assert.strictEqual(child.status, 0); +} diff --git a/test/wpt/status/hr-time.json b/test/wpt/status/hr-time.json new file mode 100644 index 00000000000000..12a239ab398107 --- /dev/null +++ b/test/wpt/status/hr-time.json @@ -0,0 +1,8 @@ +{ + "window-worker-timeOrigin.window.js": { + "fail": "Blob is not defined" + }, + "idlharness.any.js": { + "skip": "TODO: update IDL parser" + } +} \ No newline at end of file diff --git a/test/wpt/test-hr-time.js b/test/wpt/test-hr-time.js new file mode 100644 index 00000000000000..eb9c68797dfcbf --- /dev/null +++ b/test/wpt/test-hr-time.js @@ -0,0 +1,27 @@ +'use strict'; + +// Flags: --expose-internals + +require('../common'); +const { WPTRunner } = require('../common/wpt'); +const { performance, PerformanceObserver } = require('perf_hooks'); + +const runner = new WPTRunner('hr-time'); + +runner.copyGlobalsFromObject(global, [ + 'setInterval', + 'clearInterval', + 'setTimeout', + 'clearTimeout' +]); + +runner.defineGlobal('performance', { + get() { + return performance; + } +}); +runner.defineGlobal('PerformanceObserver', { + value: PerformanceObserver +}); + +runner.runJsTests(); diff --git a/tools/doc/json.js b/tools/doc/json.js index 94241d9903ef45..66e07b3512befb 100644 --- a/tools/doc/json.js +++ b/tools/doc/json.js @@ -508,8 +508,7 @@ function textJoin(nodes, file) { return `_${textJoin(node.children, file)}_`; } else if (node.children) { return textJoin(node.children, file); - } else { - return node.value; } + return node.value; }).join(''); } diff --git a/tools/doc/type-parser.js b/tools/doc/type-parser.js index 6f98197a741653..08e9096a33e714 100644 --- a/tools/doc/type-parser.js +++ b/tools/doc/type-parser.js @@ -84,6 +84,7 @@ const customTypesMap = { 'fs.FSWatcher': 'fs.html#fs_class_fs_fswatcher', 'fs.ReadStream': 'fs.html#fs_class_fs_readstream', 'fs.Stats': 'fs.html#fs_class_fs_stats', + 'fs.StatWatcher': 'fs.html#fs_class_fs_statwatcher', 'fs.WriteStream': 'fs.html#fs_class_fs_writestream', 'http.Agent': 'http.html#http_class_http_agent', @@ -153,7 +154,6 @@ const customTypesMap = { 'URLSearchParams': 'url.html#url_class_urlsearchparams', 'vm.Module': 'vm.html#vm_class_vm_module', - 'vm.Script': 'vm.html#vm_class_vm_script', 'vm.SourceTextModule': 'vm.html#vm_class_vm_sourcetextmodule', 'MessagePort': 'worker_threads.html#worker_threads_class_messageport', diff --git a/tools/icu/current_ver.dep b/tools/icu/current_ver.dep index faffe75df53c65..f22f158c30bcfd 100644 --- a/tools/icu/current_ver.dep +++ b/tools/icu/current_ver.dep @@ -1,6 +1,6 @@ [ { - "url": "https://github.com/unicode-org/icu/releases/download/release-66-1/icu4c-66_1-src.tgz", - "md5": "b33dc6766711517c98d318447e5110f8" + "url": "https://github.com/unicode-org/icu/releases/download/release-67-1/icu4c-67_1-src.tgz", + "md5": "c4d62b497cbd89ab2a9ca6b543e57b30" } ] diff --git a/tools/lint-md.js b/tools/lint-md.js index a926298f025334..5335fafb1e8f6f 100644 --- a/tools/lint-md.js +++ b/tools/lint-md.js @@ -5,9 +5,9 @@ function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'defau var stream = _interopDefault(require('stream')); var path$1 = _interopDefault(require('path')); var module$1 = _interopDefault(require('module')); -var util$1 = _interopDefault(require('util')); -var tty = _interopDefault(require('tty')); +var util$2 = _interopDefault(require('util')); var os = _interopDefault(require('os')); +var tty = _interopDefault(require('tty')); var fs$1 = _interopDefault(require('fs')); var events = _interopDefault(require('events')); var assert = _interopDefault(require('assert')); @@ -4121,7 +4121,7 @@ var errorEx = function errorEx(name, properties) { Object.setPrototypeOf(errorExError.prototype, Error.prototype); Object.setPrototypeOf(errorExError, Error); } else { - util$1.inherits(errorExError, Error); + util$2.inherits(errorExError, Error); } return errorExError; @@ -4194,407 +4194,2870 @@ function parseJson (txt, reviver, context) { } } -const JSONError = errorEx_1('JSONError', { - fileName: errorEx_1.append('in %s') -}); - -var parseJson$1 = (input, reviver, filename) => { - if (typeof reviver === 'string') { - filename = reviver; - reviver = null; - } +var LF = '\n'; +var CR = '\r'; +var LinesAndColumns = (function () { + function LinesAndColumns(string) { + this.string = string; + var offsets = [0]; + for (var offset = 0; offset < string.length;) { + switch (string[offset]) { + case LF: + offset += LF.length; + offsets.push(offset); + break; + case CR: + offset += CR.length; + if (string[offset] === LF) { + offset += LF.length; + } + offsets.push(offset); + break; + default: + offset++; + break; + } + } + this.offsets = offsets; + } + LinesAndColumns.prototype.locationForIndex = function (index) { + if (index < 0 || index > this.string.length) { + return null; + } + var line = 0; + var offsets = this.offsets; + while (offsets[line + 1] <= index) { + line++; + } + var column = index - offsets[line]; + return { line: line, column: column }; + }; + LinesAndColumns.prototype.indexForLocation = function (location) { + var line = location.line, column = location.column; + if (line < 0 || line >= this.offsets.length) { + return null; + } + if (column < 0 || column > this.lengthOfLine(line)) { + return null; + } + return this.offsets[line] + column; + }; + LinesAndColumns.prototype.lengthOfLine = function (line) { + var offset = this.offsets[line]; + var nextOffset = line === this.offsets.length - 1 ? this.string.length : this.offsets[line + 1]; + return nextOffset - offset; + }; + return LinesAndColumns; +}()); - try { - try { - return JSON.parse(input, reviver); - } catch (err) { - jsonParseBetterErrors(input, reviver); +var dist = /*#__PURE__*/Object.freeze({ + __proto__: null, + 'default': LinesAndColumns +}); - throw err; - } - } catch (err) { - err.message = err.message.replace(/\n/g, ''); +var jsTokens = createCommonjsModule(function (module, exports) { +// Copyright 2014, 2015, 2016, 2017, 2018 Simon Lydell +// License: MIT. (See LICENSE.) - const jsonErr = new JSONError(err); - if (filename) { - jsonErr.fileName = filename; - } +Object.defineProperty(exports, "__esModule", { + value: true +}); - throw jsonErr; - } +// This regex comes from regex.coffee, and is inserted here by generate-index.js +// (run `npm run build`). +exports.default = /((['"])(?:(?!\2|\\).|\\(?:\r\n|[\s\S]))*(\2)?|`(?:[^`\\$]|\\[\s\S]|\$(?!\{)|\$\{(?:[^{}]|\{[^}]*\}?)*\}?)*(`)?)|(\/\/.*)|(\/\*(?:[^*]|\*(?!\/))*(\*\/)?)|(\/(?!\*)(?:\[(?:(?![\]\\]).|\\.)*\]|(?![\/\]\\]).|\\.)+\/(?:(?!\s*(?:\b|[\u0080-\uFFFF$\\'"~({]|[+\-!](?!=)|\.?\d))|[gmiyus]{1,6}\b(?![\u0080-\uFFFF$\\]|\s*(?:[+\-*%&|^<>!=?({]|\/(?![\/*])))))|(0[xX][\da-fA-F]+|0[oO][0-7]+|0[bB][01]+|(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?)|((?!\d)(?:(?!\s)[$\w\u0080-\uFFFF]|\\u[\da-fA-F]{4}|\\u\{[\da-fA-F]+\})+)|(--|\+\+|&&|\|\||=>|\.{3}|(?:[+\-\/%&|^]|\*{1,2}|<{1,2}|>{1,3}|!=?|={1,2})=?|[?~.,:;[\](){}])|(\s+)|(^$|[\s\S])/g; + +exports.matchToToken = function(match) { + var token = {type: "invalid", value: match[0], closed: undefined}; + if (match[ 1]) token.type = "string" , token.closed = !!(match[3] || match[4]); + else if (match[ 5]) token.type = "comment"; + else if (match[ 6]) token.type = "comment", token.closed = !!match[7]; + else if (match[ 8]) token.type = "regex"; + else if (match[ 9]) token.type = "number"; + else if (match[10]) token.type = "name"; + else if (match[11]) token.type = "punctuator"; + else if (match[12]) token.type = "whitespace"; + return token }; +}); -/** - * Helpers. - */ - -var s = 1000; -var m = s * 60; -var h = m * 60; -var d = h * 24; -var w = d * 7; -var y = d * 365.25; +unwrapExports(jsTokens); +var jsTokens_1 = jsTokens.matchToToken; -/** - * Parse or format the given `val`. - * - * Options: - * - * - `long` verbose formatting [false] - * - * @param {String|Number} val - * @param {Object} [options] - * @throws {Error} throw an error if val is not a non-empty string or a number - * @return {String|Number} - * @api public - */ +var identifier = createCommonjsModule(function (module, exports) { -var ms = function(val, options) { - options = options || {}; - var type = typeof val; - if (type === 'string' && val.length > 0) { - return parse$1(val); - } else if (type === 'number' && isFinite(val)) { - return options.long ? fmtLong(val) : fmtShort(val); +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.isIdentifierStart = isIdentifierStart; +exports.isIdentifierChar = isIdentifierChar; +exports.isIdentifierName = isIdentifierName; +let nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u08a0-\u08b4\u08b6-\u08c7\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d04-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400-\u4dbf\u4e00-\u9ffc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7bf\ua7c2-\ua7ca\ua7f5-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab69\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc"; +let nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08d3-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b55-\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d81-\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1abf\u1ac0\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf4\u1cf7-\u1cf9\u1dc0-\u1df9\u1dfb-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua82c\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f"; +const nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); +const nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); +nonASCIIidentifierStartChars = nonASCIIidentifierChars = null; +const astralIdentifierStartCodes = [0, 11, 2, 25, 2, 18, 2, 1, 2, 14, 3, 13, 35, 122, 70, 52, 268, 28, 4, 48, 48, 31, 14, 29, 6, 37, 11, 29, 3, 35, 5, 7, 2, 4, 43, 157, 19, 35, 5, 35, 5, 39, 9, 51, 157, 310, 10, 21, 11, 7, 153, 5, 3, 0, 2, 43, 2, 1, 4, 0, 3, 22, 11, 22, 10, 30, 66, 18, 2, 1, 11, 21, 11, 25, 71, 55, 7, 1, 65, 0, 16, 3, 2, 2, 2, 28, 43, 28, 4, 28, 36, 7, 2, 27, 28, 53, 11, 21, 11, 18, 14, 17, 111, 72, 56, 50, 14, 50, 14, 35, 349, 41, 7, 1, 79, 28, 11, 0, 9, 21, 107, 20, 28, 22, 13, 52, 76, 44, 33, 24, 27, 35, 30, 0, 3, 0, 9, 34, 4, 0, 13, 47, 15, 3, 22, 0, 2, 0, 36, 17, 2, 24, 85, 6, 2, 0, 2, 3, 2, 14, 2, 9, 8, 46, 39, 7, 3, 1, 3, 21, 2, 6, 2, 1, 2, 4, 4, 0, 19, 0, 13, 4, 159, 52, 19, 3, 21, 2, 31, 47, 21, 1, 2, 0, 185, 46, 42, 3, 37, 47, 21, 0, 60, 42, 14, 0, 72, 26, 230, 43, 117, 63, 32, 7, 3, 0, 3, 7, 2, 1, 2, 23, 16, 0, 2, 0, 95, 7, 3, 38, 17, 0, 2, 0, 29, 0, 11, 39, 8, 0, 22, 0, 12, 45, 20, 0, 35, 56, 264, 8, 2, 36, 18, 0, 50, 29, 113, 6, 2, 1, 2, 37, 22, 0, 26, 5, 2, 1, 2, 31, 15, 0, 328, 18, 190, 0, 80, 921, 103, 110, 18, 195, 2749, 1070, 4050, 582, 8634, 568, 8, 30, 114, 29, 19, 47, 17, 3, 32, 20, 6, 18, 689, 63, 129, 74, 6, 0, 67, 12, 65, 1, 2, 0, 29, 6135, 9, 1237, 43, 8, 8952, 286, 50, 2, 18, 3, 9, 395, 2309, 106, 6, 12, 4, 8, 8, 9, 5991, 84, 2, 70, 2, 1, 3, 0, 3, 1, 3, 3, 2, 11, 2, 0, 2, 6, 2, 64, 2, 3, 3, 7, 2, 6, 2, 27, 2, 3, 2, 4, 2, 0, 4, 6, 2, 339, 3, 24, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 7, 2357, 44, 11, 6, 17, 0, 370, 43, 1301, 196, 60, 67, 8, 0, 1205, 3, 2, 26, 2, 1, 2, 0, 3, 0, 2, 9, 2, 3, 2, 0, 2, 0, 7, 0, 5, 0, 2, 0, 2, 0, 2, 2, 2, 1, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 3, 3, 2, 6, 2, 3, 2, 3, 2, 0, 2, 9, 2, 16, 6, 2, 2, 4, 2, 16, 4421, 42717, 35, 4148, 12, 221, 3, 5761, 15, 7472, 3104, 541, 1507, 4938]; +const astralIdentifierCodes = [509, 0, 227, 0, 150, 4, 294, 9, 1368, 2, 2, 1, 6, 3, 41, 2, 5, 0, 166, 1, 574, 3, 9, 9, 370, 1, 154, 10, 176, 2, 54, 14, 32, 9, 16, 3, 46, 10, 54, 9, 7, 2, 37, 13, 2, 9, 6, 1, 45, 0, 13, 2, 49, 13, 9, 3, 2, 11, 83, 11, 7, 0, 161, 11, 6, 9, 7, 3, 56, 1, 2, 6, 3, 1, 3, 2, 10, 0, 11, 1, 3, 6, 4, 4, 193, 17, 10, 9, 5, 0, 82, 19, 13, 9, 214, 6, 3, 8, 28, 1, 83, 16, 16, 9, 82, 12, 9, 9, 84, 14, 5, 9, 243, 14, 166, 9, 71, 5, 2, 1, 3, 3, 2, 0, 2, 1, 13, 9, 120, 6, 3, 6, 4, 0, 29, 9, 41, 6, 2, 3, 9, 0, 10, 10, 47, 15, 406, 7, 2, 7, 17, 9, 57, 21, 2, 13, 123, 5, 4, 0, 2, 1, 2, 6, 2, 0, 9, 9, 49, 4, 2, 1, 2, 4, 9, 9, 330, 3, 19306, 9, 135, 4, 60, 6, 26, 9, 1014, 0, 2, 54, 8, 3, 82, 0, 12, 1, 19628, 1, 5319, 4, 4, 5, 9, 7, 3, 6, 31, 3, 149, 2, 1418, 49, 513, 54, 5, 49, 9, 0, 15, 0, 23, 4, 2, 14, 1361, 6, 2, 16, 3, 6, 2, 1, 2, 4, 262, 6, 10, 9, 419, 13, 1495, 6, 110, 6, 6, 9, 4759, 9, 787719, 239]; + +function isInAstralSet(code, set) { + let pos = 0x10000; + + for (let i = 0, length = set.length; i < length; i += 2) { + pos += set[i]; + if (pos > code) return false; + pos += set[i + 1]; + if (pos >= code) return true; } - throw new Error( - 'val is not a non-empty string or a valid number. val=' + - JSON.stringify(val) - ); -}; -/** - * Parse the given `str` and return milliseconds. - * - * @param {String} str - * @return {Number} - * @api private - */ + return false; +} -function parse$1(str) { - str = String(str); - if (str.length > 100) { - return; - } - var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec( - str - ); - if (!match) { - return; - } - var n = parseFloat(match[1]); - var type = (match[2] || 'ms').toLowerCase(); - switch (type) { - case 'years': - case 'year': - case 'yrs': - case 'yr': - case 'y': - return n * y; - case 'weeks': - case 'week': - case 'w': - return n * w; - case 'days': - case 'day': - case 'd': - return n * d; - case 'hours': - case 'hour': - case 'hrs': - case 'hr': - case 'h': - return n * h; - case 'minutes': - case 'minute': - case 'mins': - case 'min': - case 'm': - return n * m; - case 'seconds': - case 'second': - case 'secs': - case 'sec': - case 's': - return n * s; - case 'milliseconds': - case 'millisecond': - case 'msecs': - case 'msec': - case 'ms': - return n; - default: - return undefined; +function isIdentifierStart(code) { + if (code < 65) return code === 36; + if (code <= 90) return true; + if (code < 97) return code === 95; + if (code <= 122) return true; + + if (code <= 0xffff) { + return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)); } + + return isInAstralSet(code, astralIdentifierStartCodes); } -/** - * Short format for `ms`. - * - * @param {Number} ms - * @return {String} - * @api private - */ +function isIdentifierChar(code) { + if (code < 48) return code === 36; + if (code < 58) return true; + if (code < 65) return false; + if (code <= 90) return true; + if (code < 97) return code === 95; + if (code <= 122) return true; -function fmtShort(ms) { - var msAbs = Math.abs(ms); - if (msAbs >= d) { - return Math.round(ms / d) + 'd'; - } - if (msAbs >= h) { - return Math.round(ms / h) + 'h'; - } - if (msAbs >= m) { - return Math.round(ms / m) + 'm'; - } - if (msAbs >= s) { - return Math.round(ms / s) + 's'; + if (code <= 0xffff) { + return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)); } - return ms + 'ms'; + + return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes); } -/** - * Long format for `ms`. - * - * @param {Number} ms - * @return {String} - * @api private - */ +function isIdentifierName(name) { + let isFirst = true; -function fmtLong(ms) { - var msAbs = Math.abs(ms); - if (msAbs >= d) { - return plural(ms, msAbs, d, 'day'); - } - if (msAbs >= h) { - return plural(ms, msAbs, h, 'hour'); - } - if (msAbs >= m) { - return plural(ms, msAbs, m, 'minute'); - } - if (msAbs >= s) { - return plural(ms, msAbs, s, 'second'); + for (let _i = 0, _Array$from = Array.from(name); _i < _Array$from.length; _i++) { + const char = _Array$from[_i]; + const cp = char.codePointAt(0); + + if (isFirst) { + if (!isIdentifierStart(cp)) { + return false; + } + + isFirst = false; + } else if (!isIdentifierChar(cp)) { + return false; + } } - return ms + ' ms'; + + return !isFirst; } +}); -/** - * Pluralization helper. - */ +unwrapExports(identifier); +var identifier_1 = identifier.isIdentifierStart; +var identifier_2 = identifier.isIdentifierChar; +var identifier_3 = identifier.isIdentifierName; -function plural(ms, msAbs, n, name) { - var isPlural = msAbs >= n * 1.5; - return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : ''); -} +var keyword = createCommonjsModule(function (module, exports) { -/** - * This is the common logic for both the Node.js and web browser - * implementations of `debug()`. - */ +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.isReservedWord = isReservedWord; +exports.isStrictReservedWord = isStrictReservedWord; +exports.isStrictBindOnlyReservedWord = isStrictBindOnlyReservedWord; +exports.isStrictBindReservedWord = isStrictBindReservedWord; +exports.isKeyword = isKeyword; +const reservedWords = { + keyword: ["break", "case", "catch", "continue", "debugger", "default", "do", "else", "finally", "for", "function", "if", "return", "switch", "throw", "try", "var", "const", "while", "with", "new", "this", "super", "class", "extends", "export", "import", "null", "true", "false", "in", "instanceof", "typeof", "void", "delete"], + strict: ["implements", "interface", "let", "package", "private", "protected", "public", "static", "yield"], + strictBind: ["eval", "arguments"] +}; +const keywords = new Set(reservedWords.keyword); +const reservedWordsStrictSet = new Set(reservedWords.strict); +const reservedWordsStrictBindSet = new Set(reservedWords.strictBind); -function setup(env) { - createDebug.debug = createDebug; - createDebug.default = createDebug; - createDebug.coerce = coerce; - createDebug.disable = disable; - createDebug.enable = enable; - createDebug.enabled = enabled; - createDebug.humanize = ms; +function isReservedWord(word, inModule) { + return inModule && word === "await" || word === "enum"; +} - Object.keys(env).forEach(key => { - createDebug[key] = env[key]; - }); +function isStrictReservedWord(word, inModule) { + return isReservedWord(word, inModule) || reservedWordsStrictSet.has(word); +} - /** - * Active `debug` instances. - */ - createDebug.instances = []; +function isStrictBindOnlyReservedWord(word) { + return reservedWordsStrictBindSet.has(word); +} - /** - * The currently active debug mode names, and names to skip. - */ +function isStrictBindReservedWord(word, inModule) { + return isStrictReservedWord(word, inModule) || isStrictBindOnlyReservedWord(word); +} - createDebug.names = []; - createDebug.skips = []; +function isKeyword(word) { + return keywords.has(word); +} +}); - /** - * Map of special "%n" handling functions, for the debug "format" argument. - * - * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". - */ - createDebug.formatters = {}; +unwrapExports(keyword); +var keyword_1 = keyword.isReservedWord; +var keyword_2 = keyword.isStrictReservedWord; +var keyword_3 = keyword.isStrictBindOnlyReservedWord; +var keyword_4 = keyword.isStrictBindReservedWord; +var keyword_5 = keyword.isKeyword; - /** - * Selects a color for a debug namespace - * @param {String} namespace The namespace string for the for the debug instance to be colored - * @return {Number|String} An ANSI color code for the given namespace - * @api private - */ - function selectColor(namespace) { - let hash = 0; +var lib = createCommonjsModule(function (module, exports) { - for (let i = 0; i < namespace.length; i++) { - hash = ((hash << 5) - hash) + namespace.charCodeAt(i); - hash |= 0; // Convert to 32bit integer - } +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "isIdentifierName", { + enumerable: true, + get: function () { + return identifier.isIdentifierName; + } +}); +Object.defineProperty(exports, "isIdentifierChar", { + enumerable: true, + get: function () { + return identifier.isIdentifierChar; + } +}); +Object.defineProperty(exports, "isIdentifierStart", { + enumerable: true, + get: function () { + return identifier.isIdentifierStart; + } +}); +Object.defineProperty(exports, "isReservedWord", { + enumerable: true, + get: function () { + return keyword.isReservedWord; + } +}); +Object.defineProperty(exports, "isStrictBindOnlyReservedWord", { + enumerable: true, + get: function () { + return keyword.isStrictBindOnlyReservedWord; + } +}); +Object.defineProperty(exports, "isStrictBindReservedWord", { + enumerable: true, + get: function () { + return keyword.isStrictBindReservedWord; + } +}); +Object.defineProperty(exports, "isStrictReservedWord", { + enumerable: true, + get: function () { + return keyword.isStrictReservedWord; + } +}); +Object.defineProperty(exports, "isKeyword", { + enumerable: true, + get: function () { + return keyword.isKeyword; + } +}); +}); - return createDebug.colors[Math.abs(hash) % createDebug.colors.length]; - } - createDebug.selectColor = selectColor; +unwrapExports(lib); - /** - * Create a debugger with the given `namespace`. - * - * @param {String} namespace - * @return {Function} - * @api public - */ - function createDebug(namespace) { - let prevTime; +var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g; - function debug(...args) { - // Disabled? - if (!debug.enabled) { - return; - } +var escapeStringRegexp = function (str) { + if (typeof str !== 'string') { + throw new TypeError('Expected a string'); + } - const self = debug; + return str.replace(matchOperatorsRe, '\\$&'); +}; - // Set `diff` timestamp - const curr = Number(new Date()); - const ms = curr - (prevTime || curr); - self.diff = ms; - self.prev = prevTime; - self.curr = curr; - prevTime = curr; +var colorName = { + "aliceblue": [240, 248, 255], + "antiquewhite": [250, 235, 215], + "aqua": [0, 255, 255], + "aquamarine": [127, 255, 212], + "azure": [240, 255, 255], + "beige": [245, 245, 220], + "bisque": [255, 228, 196], + "black": [0, 0, 0], + "blanchedalmond": [255, 235, 205], + "blue": [0, 0, 255], + "blueviolet": [138, 43, 226], + "brown": [165, 42, 42], + "burlywood": [222, 184, 135], + "cadetblue": [95, 158, 160], + "chartreuse": [127, 255, 0], + "chocolate": [210, 105, 30], + "coral": [255, 127, 80], + "cornflowerblue": [100, 149, 237], + "cornsilk": [255, 248, 220], + "crimson": [220, 20, 60], + "cyan": [0, 255, 255], + "darkblue": [0, 0, 139], + "darkcyan": [0, 139, 139], + "darkgoldenrod": [184, 134, 11], + "darkgray": [169, 169, 169], + "darkgreen": [0, 100, 0], + "darkgrey": [169, 169, 169], + "darkkhaki": [189, 183, 107], + "darkmagenta": [139, 0, 139], + "darkolivegreen": [85, 107, 47], + "darkorange": [255, 140, 0], + "darkorchid": [153, 50, 204], + "darkred": [139, 0, 0], + "darksalmon": [233, 150, 122], + "darkseagreen": [143, 188, 143], + "darkslateblue": [72, 61, 139], + "darkslategray": [47, 79, 79], + "darkslategrey": [47, 79, 79], + "darkturquoise": [0, 206, 209], + "darkviolet": [148, 0, 211], + "deeppink": [255, 20, 147], + "deepskyblue": [0, 191, 255], + "dimgray": [105, 105, 105], + "dimgrey": [105, 105, 105], + "dodgerblue": [30, 144, 255], + "firebrick": [178, 34, 34], + "floralwhite": [255, 250, 240], + "forestgreen": [34, 139, 34], + "fuchsia": [255, 0, 255], + "gainsboro": [220, 220, 220], + "ghostwhite": [248, 248, 255], + "gold": [255, 215, 0], + "goldenrod": [218, 165, 32], + "gray": [128, 128, 128], + "green": [0, 128, 0], + "greenyellow": [173, 255, 47], + "grey": [128, 128, 128], + "honeydew": [240, 255, 240], + "hotpink": [255, 105, 180], + "indianred": [205, 92, 92], + "indigo": [75, 0, 130], + "ivory": [255, 255, 240], + "khaki": [240, 230, 140], + "lavender": [230, 230, 250], + "lavenderblush": [255, 240, 245], + "lawngreen": [124, 252, 0], + "lemonchiffon": [255, 250, 205], + "lightblue": [173, 216, 230], + "lightcoral": [240, 128, 128], + "lightcyan": [224, 255, 255], + "lightgoldenrodyellow": [250, 250, 210], + "lightgray": [211, 211, 211], + "lightgreen": [144, 238, 144], + "lightgrey": [211, 211, 211], + "lightpink": [255, 182, 193], + "lightsalmon": [255, 160, 122], + "lightseagreen": [32, 178, 170], + "lightskyblue": [135, 206, 250], + "lightslategray": [119, 136, 153], + "lightslategrey": [119, 136, 153], + "lightsteelblue": [176, 196, 222], + "lightyellow": [255, 255, 224], + "lime": [0, 255, 0], + "limegreen": [50, 205, 50], + "linen": [250, 240, 230], + "magenta": [255, 0, 255], + "maroon": [128, 0, 0], + "mediumaquamarine": [102, 205, 170], + "mediumblue": [0, 0, 205], + "mediumorchid": [186, 85, 211], + "mediumpurple": [147, 112, 219], + "mediumseagreen": [60, 179, 113], + "mediumslateblue": [123, 104, 238], + "mediumspringgreen": [0, 250, 154], + "mediumturquoise": [72, 209, 204], + "mediumvioletred": [199, 21, 133], + "midnightblue": [25, 25, 112], + "mintcream": [245, 255, 250], + "mistyrose": [255, 228, 225], + "moccasin": [255, 228, 181], + "navajowhite": [255, 222, 173], + "navy": [0, 0, 128], + "oldlace": [253, 245, 230], + "olive": [128, 128, 0], + "olivedrab": [107, 142, 35], + "orange": [255, 165, 0], + "orangered": [255, 69, 0], + "orchid": [218, 112, 214], + "palegoldenrod": [238, 232, 170], + "palegreen": [152, 251, 152], + "paleturquoise": [175, 238, 238], + "palevioletred": [219, 112, 147], + "papayawhip": [255, 239, 213], + "peachpuff": [255, 218, 185], + "peru": [205, 133, 63], + "pink": [255, 192, 203], + "plum": [221, 160, 221], + "powderblue": [176, 224, 230], + "purple": [128, 0, 128], + "rebeccapurple": [102, 51, 153], + "red": [255, 0, 0], + "rosybrown": [188, 143, 143], + "royalblue": [65, 105, 225], + "saddlebrown": [139, 69, 19], + "salmon": [250, 128, 114], + "sandybrown": [244, 164, 96], + "seagreen": [46, 139, 87], + "seashell": [255, 245, 238], + "sienna": [160, 82, 45], + "silver": [192, 192, 192], + "skyblue": [135, 206, 235], + "slateblue": [106, 90, 205], + "slategray": [112, 128, 144], + "slategrey": [112, 128, 144], + "snow": [255, 250, 250], + "springgreen": [0, 255, 127], + "steelblue": [70, 130, 180], + "tan": [210, 180, 140], + "teal": [0, 128, 128], + "thistle": [216, 191, 216], + "tomato": [255, 99, 71], + "turquoise": [64, 224, 208], + "violet": [238, 130, 238], + "wheat": [245, 222, 179], + "white": [255, 255, 255], + "whitesmoke": [245, 245, 245], + "yellow": [255, 255, 0], + "yellowgreen": [154, 205, 50] +}; - args[0] = createDebug.coerce(args[0]); +var conversions = createCommonjsModule(function (module) { +/* MIT license */ - if (typeof args[0] !== 'string') { - // Anything else let's inspect with %O - args.unshift('%O'); - } - // Apply any `formatters` transformations - let index = 0; - args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => { - // If we encounter an escaped % then don't increase the array index - if (match === '%%') { - return match; - } - index++; - const formatter = createDebug.formatters[format]; - if (typeof formatter === 'function') { - const val = args[index]; - match = formatter.call(self, val); +// NOTE: conversions should only return primitive values (i.e. arrays, or +// values that give correct `typeof` results). +// do not use box values types (i.e. Number(), String(), etc.) - // Now we need to remove `args[index]` since it's inlined in the `format` - args.splice(index, 1); - index--; - } - return match; - }); +var reverseKeywords = {}; +for (var key in colorName) { + if (colorName.hasOwnProperty(key)) { + reverseKeywords[colorName[key]] = key; + } +} - // Apply env-specific formatting (colors, etc.) - createDebug.formatArgs.call(self, args); +var convert = module.exports = { + rgb: {channels: 3, labels: 'rgb'}, + hsl: {channels: 3, labels: 'hsl'}, + hsv: {channels: 3, labels: 'hsv'}, + hwb: {channels: 3, labels: 'hwb'}, + cmyk: {channels: 4, labels: 'cmyk'}, + xyz: {channels: 3, labels: 'xyz'}, + lab: {channels: 3, labels: 'lab'}, + lch: {channels: 3, labels: 'lch'}, + hex: {channels: 1, labels: ['hex']}, + keyword: {channels: 1, labels: ['keyword']}, + ansi16: {channels: 1, labels: ['ansi16']}, + ansi256: {channels: 1, labels: ['ansi256']}, + hcg: {channels: 3, labels: ['h', 'c', 'g']}, + apple: {channels: 3, labels: ['r16', 'g16', 'b16']}, + gray: {channels: 1, labels: ['gray']} +}; - const logFn = self.log || createDebug.log; - logFn.apply(self, args); +// hide .channels and .labels properties +for (var model in convert) { + if (convert.hasOwnProperty(model)) { + if (!('channels' in convert[model])) { + throw new Error('missing channels property: ' + model); } - debug.namespace = namespace; - debug.enabled = createDebug.enabled(namespace); - debug.useColors = createDebug.useColors(); - debug.color = selectColor(namespace); - debug.destroy = destroy; - debug.extend = extend; - // Debug.formatArgs = formatArgs; - // debug.rawLog = rawLog; - - // env-specific initialization logic for debug instances - if (typeof createDebug.init === 'function') { - createDebug.init(debug); + if (!('labels' in convert[model])) { + throw new Error('missing channel labels property: ' + model); } - createDebug.instances.push(debug); + if (convert[model].labels.length !== convert[model].channels) { + throw new Error('channel and label counts mismatch: ' + model); + } - return debug; + var channels = convert[model].channels; + var labels = convert[model].labels; + delete convert[model].channels; + delete convert[model].labels; + Object.defineProperty(convert[model], 'channels', {value: channels}); + Object.defineProperty(convert[model], 'labels', {value: labels}); } +} - function destroy() { - const index = createDebug.instances.indexOf(this); - if (index !== -1) { - createDebug.instances.splice(index, 1); - return true; - } - return false; +convert.rgb.hsl = function (rgb) { + var r = rgb[0] / 255; + var g = rgb[1] / 255; + var b = rgb[2] / 255; + var min = Math.min(r, g, b); + var max = Math.max(r, g, b); + var delta = max - min; + var h; + var s; + var l; + + if (max === min) { + h = 0; + } else if (r === max) { + h = (g - b) / delta; + } else if (g === max) { + h = 2 + (b - r) / delta; + } else if (b === max) { + h = 4 + (r - g) / delta; } - function extend(namespace, delimiter) { - const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace); - newDebug.log = this.log; - return newDebug; + h = Math.min(h * 60, 360); + + if (h < 0) { + h += 360; } - /** - * Enables a debug mode by namespaces. This can include modes - * separated by a colon and wildcards. - * - * @param {String} namespaces - * @api public - */ - function enable(namespaces) { - createDebug.save(namespaces); + l = (min + max) / 2; - createDebug.names = []; - createDebug.skips = []; + if (max === min) { + s = 0; + } else if (l <= 0.5) { + s = delta / (max + min); + } else { + s = delta / (2 - max - min); + } - let i; - const split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); - const len = split.length; + return [h, s * 100, l * 100]; +}; - for (i = 0; i < len; i++) { - if (!split[i]) { - // ignore empty strings - continue; - } +convert.rgb.hsv = function (rgb) { + var rdif; + var gdif; + var bdif; + var h; + var s; - namespaces = split[i].replace(/\*/g, '.*?'); + var r = rgb[0] / 255; + var g = rgb[1] / 255; + var b = rgb[2] / 255; + var v = Math.max(r, g, b); + var diff = v - Math.min(r, g, b); + var diffc = function (c) { + return (v - c) / 6 / diff + 1 / 2; + }; - if (namespaces[0] === '-') { - createDebug.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); - } else { - createDebug.names.push(new RegExp('^' + namespaces + '$')); - } - } + if (diff === 0) { + h = s = 0; + } else { + s = diff / v; + rdif = diffc(r); + gdif = diffc(g); + bdif = diffc(b); - for (i = 0; i < createDebug.instances.length; i++) { - const instance = createDebug.instances[i]; - instance.enabled = createDebug.enabled(instance.namespace); + if (r === v) { + h = bdif - gdif; + } else if (g === v) { + h = (1 / 3) + rdif - bdif; + } else if (b === v) { + h = (2 / 3) + gdif - rdif; + } + if (h < 0) { + h += 1; + } else if (h > 1) { + h -= 1; } } - /** - * Disable debug output. - * - * @return {String} namespaces - * @api public - */ - function disable() { - const namespaces = [ - ...createDebug.names.map(toNamespace), - ...createDebug.skips.map(toNamespace).map(namespace => '-' + namespace) - ].join(','); - createDebug.enable(''); - return namespaces; - } + return [ + h * 360, + s * 100, + v * 100 + ]; +}; - /** - * Returns true if the given mode name is enabled, false otherwise. - * - * @param {String} name - * @return {Boolean} - * @api public +convert.rgb.hwb = function (rgb) { + var r = rgb[0]; + var g = rgb[1]; + var b = rgb[2]; + var h = convert.rgb.hsl(rgb)[0]; + var w = 1 / 255 * Math.min(r, Math.min(g, b)); + + b = 1 - 1 / 255 * Math.max(r, Math.max(g, b)); + + return [h, w * 100, b * 100]; +}; + +convert.rgb.cmyk = function (rgb) { + var r = rgb[0] / 255; + var g = rgb[1] / 255; + var b = rgb[2] / 255; + var c; + var m; + var y; + var k; + + k = Math.min(1 - r, 1 - g, 1 - b); + c = (1 - r - k) / (1 - k) || 0; + m = (1 - g - k) / (1 - k) || 0; + y = (1 - b - k) / (1 - k) || 0; + + return [c * 100, m * 100, y * 100, k * 100]; +}; + +/** + * See https://en.m.wikipedia.org/wiki/Euclidean_distance#Squared_Euclidean_distance + * */ +function comparativeDistance(x, y) { + return ( + Math.pow(x[0] - y[0], 2) + + Math.pow(x[1] - y[1], 2) + + Math.pow(x[2] - y[2], 2) + ); +} + +convert.rgb.keyword = function (rgb) { + var reversed = reverseKeywords[rgb]; + if (reversed) { + return reversed; + } + + var currentClosestDistance = Infinity; + var currentClosestKeyword; + + for (var keyword in colorName) { + if (colorName.hasOwnProperty(keyword)) { + var value = colorName[keyword]; + + // Compute comparative distance + var distance = comparativeDistance(rgb, value); + + // Check if its less, if so set as closest + if (distance < currentClosestDistance) { + currentClosestDistance = distance; + currentClosestKeyword = keyword; + } + } + } + + return currentClosestKeyword; +}; + +convert.keyword.rgb = function (keyword) { + return colorName[keyword]; +}; + +convert.rgb.xyz = function (rgb) { + var r = rgb[0] / 255; + var g = rgb[1] / 255; + var b = rgb[2] / 255; + + // assume sRGB + r = r > 0.04045 ? Math.pow(((r + 0.055) / 1.055), 2.4) : (r / 12.92); + g = g > 0.04045 ? Math.pow(((g + 0.055) / 1.055), 2.4) : (g / 12.92); + b = b > 0.04045 ? Math.pow(((b + 0.055) / 1.055), 2.4) : (b / 12.92); + + var x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805); + var y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722); + var z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505); + + return [x * 100, y * 100, z * 100]; +}; + +convert.rgb.lab = function (rgb) { + var xyz = convert.rgb.xyz(rgb); + var x = xyz[0]; + var y = xyz[1]; + var z = xyz[2]; + var l; + var a; + var b; + + x /= 95.047; + y /= 100; + z /= 108.883; + + x = x > 0.008856 ? Math.pow(x, 1 / 3) : (7.787 * x) + (16 / 116); + y = y > 0.008856 ? Math.pow(y, 1 / 3) : (7.787 * y) + (16 / 116); + z = z > 0.008856 ? Math.pow(z, 1 / 3) : (7.787 * z) + (16 / 116); + + l = (116 * y) - 16; + a = 500 * (x - y); + b = 200 * (y - z); + + return [l, a, b]; +}; + +convert.hsl.rgb = function (hsl) { + var h = hsl[0] / 360; + var s = hsl[1] / 100; + var l = hsl[2] / 100; + var t1; + var t2; + var t3; + var rgb; + var val; + + if (s === 0) { + val = l * 255; + return [val, val, val]; + } + + if (l < 0.5) { + t2 = l * (1 + s); + } else { + t2 = l + s - l * s; + } + + t1 = 2 * l - t2; + + rgb = [0, 0, 0]; + for (var i = 0; i < 3; i++) { + t3 = h + 1 / 3 * -(i - 1); + if (t3 < 0) { + t3++; + } + if (t3 > 1) { + t3--; + } + + if (6 * t3 < 1) { + val = t1 + (t2 - t1) * 6 * t3; + } else if (2 * t3 < 1) { + val = t2; + } else if (3 * t3 < 2) { + val = t1 + (t2 - t1) * (2 / 3 - t3) * 6; + } else { + val = t1; + } + + rgb[i] = val * 255; + } + + return rgb; +}; + +convert.hsl.hsv = function (hsl) { + var h = hsl[0]; + var s = hsl[1] / 100; + var l = hsl[2] / 100; + var smin = s; + var lmin = Math.max(l, 0.01); + var sv; + var v; + + l *= 2; + s *= (l <= 1) ? l : 2 - l; + smin *= lmin <= 1 ? lmin : 2 - lmin; + v = (l + s) / 2; + sv = l === 0 ? (2 * smin) / (lmin + smin) : (2 * s) / (l + s); + + return [h, sv * 100, v * 100]; +}; + +convert.hsv.rgb = function (hsv) { + var h = hsv[0] / 60; + var s = hsv[1] / 100; + var v = hsv[2] / 100; + var hi = Math.floor(h) % 6; + + var f = h - Math.floor(h); + var p = 255 * v * (1 - s); + var q = 255 * v * (1 - (s * f)); + var t = 255 * v * (1 - (s * (1 - f))); + v *= 255; + + switch (hi) { + case 0: + return [v, t, p]; + case 1: + return [q, v, p]; + case 2: + return [p, v, t]; + case 3: + return [p, q, v]; + case 4: + return [t, p, v]; + case 5: + return [v, p, q]; + } +}; + +convert.hsv.hsl = function (hsv) { + var h = hsv[0]; + var s = hsv[1] / 100; + var v = hsv[2] / 100; + var vmin = Math.max(v, 0.01); + var lmin; + var sl; + var l; + + l = (2 - s) * v; + lmin = (2 - s) * vmin; + sl = s * vmin; + sl /= (lmin <= 1) ? lmin : 2 - lmin; + sl = sl || 0; + l /= 2; + + return [h, sl * 100, l * 100]; +}; + +// http://dev.w3.org/csswg/css-color/#hwb-to-rgb +convert.hwb.rgb = function (hwb) { + var h = hwb[0] / 360; + var wh = hwb[1] / 100; + var bl = hwb[2] / 100; + var ratio = wh + bl; + var i; + var v; + var f; + var n; + + // wh + bl cant be > 1 + if (ratio > 1) { + wh /= ratio; + bl /= ratio; + } + + i = Math.floor(6 * h); + v = 1 - bl; + f = 6 * h - i; + + if ((i & 0x01) !== 0) { + f = 1 - f; + } + + n = wh + f * (v - wh); // linear interpolation + + var r; + var g; + var b; + switch (i) { + default: + case 6: + case 0: r = v; g = n; b = wh; break; + case 1: r = n; g = v; b = wh; break; + case 2: r = wh; g = v; b = n; break; + case 3: r = wh; g = n; b = v; break; + case 4: r = n; g = wh; b = v; break; + case 5: r = v; g = wh; b = n; break; + } + + return [r * 255, g * 255, b * 255]; +}; + +convert.cmyk.rgb = function (cmyk) { + var c = cmyk[0] / 100; + var m = cmyk[1] / 100; + var y = cmyk[2] / 100; + var k = cmyk[3] / 100; + var r; + var g; + var b; + + r = 1 - Math.min(1, c * (1 - k) + k); + g = 1 - Math.min(1, m * (1 - k) + k); + b = 1 - Math.min(1, y * (1 - k) + k); + + return [r * 255, g * 255, b * 255]; +}; + +convert.xyz.rgb = function (xyz) { + var x = xyz[0] / 100; + var y = xyz[1] / 100; + var z = xyz[2] / 100; + var r; + var g; + var b; + + r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986); + g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415); + b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570); + + // assume sRGB + r = r > 0.0031308 + ? ((1.055 * Math.pow(r, 1.0 / 2.4)) - 0.055) + : r * 12.92; + + g = g > 0.0031308 + ? ((1.055 * Math.pow(g, 1.0 / 2.4)) - 0.055) + : g * 12.92; + + b = b > 0.0031308 + ? ((1.055 * Math.pow(b, 1.0 / 2.4)) - 0.055) + : b * 12.92; + + r = Math.min(Math.max(0, r), 1); + g = Math.min(Math.max(0, g), 1); + b = Math.min(Math.max(0, b), 1); + + return [r * 255, g * 255, b * 255]; +}; + +convert.xyz.lab = function (xyz) { + var x = xyz[0]; + var y = xyz[1]; + var z = xyz[2]; + var l; + var a; + var b; + + x /= 95.047; + y /= 100; + z /= 108.883; + + x = x > 0.008856 ? Math.pow(x, 1 / 3) : (7.787 * x) + (16 / 116); + y = y > 0.008856 ? Math.pow(y, 1 / 3) : (7.787 * y) + (16 / 116); + z = z > 0.008856 ? Math.pow(z, 1 / 3) : (7.787 * z) + (16 / 116); + + l = (116 * y) - 16; + a = 500 * (x - y); + b = 200 * (y - z); + + return [l, a, b]; +}; + +convert.lab.xyz = function (lab) { + var l = lab[0]; + var a = lab[1]; + var b = lab[2]; + var x; + var y; + var z; + + y = (l + 16) / 116; + x = a / 500 + y; + z = y - b / 200; + + var y2 = Math.pow(y, 3); + var x2 = Math.pow(x, 3); + var z2 = Math.pow(z, 3); + y = y2 > 0.008856 ? y2 : (y - 16 / 116) / 7.787; + x = x2 > 0.008856 ? x2 : (x - 16 / 116) / 7.787; + z = z2 > 0.008856 ? z2 : (z - 16 / 116) / 7.787; + + x *= 95.047; + y *= 100; + z *= 108.883; + + return [x, y, z]; +}; + +convert.lab.lch = function (lab) { + var l = lab[0]; + var a = lab[1]; + var b = lab[2]; + var hr; + var h; + var c; + + hr = Math.atan2(b, a); + h = hr * 360 / 2 / Math.PI; + + if (h < 0) { + h += 360; + } + + c = Math.sqrt(a * a + b * b); + + return [l, c, h]; +}; + +convert.lch.lab = function (lch) { + var l = lch[0]; + var c = lch[1]; + var h = lch[2]; + var a; + var b; + var hr; + + hr = h / 360 * 2 * Math.PI; + a = c * Math.cos(hr); + b = c * Math.sin(hr); + + return [l, a, b]; +}; + +convert.rgb.ansi16 = function (args) { + var r = args[0]; + var g = args[1]; + var b = args[2]; + var value = 1 in arguments ? arguments[1] : convert.rgb.hsv(args)[2]; // hsv -> ansi16 optimization + + value = Math.round(value / 50); + + if (value === 0) { + return 30; + } + + var ansi = 30 + + ((Math.round(b / 255) << 2) + | (Math.round(g / 255) << 1) + | Math.round(r / 255)); + + if (value === 2) { + ansi += 60; + } + + return ansi; +}; + +convert.hsv.ansi16 = function (args) { + // optimization here; we already know the value and don't need to get + // it converted for us. + return convert.rgb.ansi16(convert.hsv.rgb(args), args[2]); +}; + +convert.rgb.ansi256 = function (args) { + var r = args[0]; + var g = args[1]; + var b = args[2]; + + // we use the extended greyscale palette here, with the exception of + // black and white. normal palette only has 4 greyscale shades. + if (r === g && g === b) { + if (r < 8) { + return 16; + } + + if (r > 248) { + return 231; + } + + return Math.round(((r - 8) / 247) * 24) + 232; + } + + var ansi = 16 + + (36 * Math.round(r / 255 * 5)) + + (6 * Math.round(g / 255 * 5)) + + Math.round(b / 255 * 5); + + return ansi; +}; + +convert.ansi16.rgb = function (args) { + var color = args % 10; + + // handle greyscale + if (color === 0 || color === 7) { + if (args > 50) { + color += 3.5; + } + + color = color / 10.5 * 255; + + return [color, color, color]; + } + + var mult = (~~(args > 50) + 1) * 0.5; + var r = ((color & 1) * mult) * 255; + var g = (((color >> 1) & 1) * mult) * 255; + var b = (((color >> 2) & 1) * mult) * 255; + + return [r, g, b]; +}; + +convert.ansi256.rgb = function (args) { + // handle greyscale + if (args >= 232) { + var c = (args - 232) * 10 + 8; + return [c, c, c]; + } + + args -= 16; + + var rem; + var r = Math.floor(args / 36) / 5 * 255; + var g = Math.floor((rem = args % 36) / 6) / 5 * 255; + var b = (rem % 6) / 5 * 255; + + return [r, g, b]; +}; + +convert.rgb.hex = function (args) { + var integer = ((Math.round(args[0]) & 0xFF) << 16) + + ((Math.round(args[1]) & 0xFF) << 8) + + (Math.round(args[2]) & 0xFF); + + var string = integer.toString(16).toUpperCase(); + return '000000'.substring(string.length) + string; +}; + +convert.hex.rgb = function (args) { + var match = args.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i); + if (!match) { + return [0, 0, 0]; + } + + var colorString = match[0]; + + if (match[0].length === 3) { + colorString = colorString.split('').map(function (char) { + return char + char; + }).join(''); + } + + var integer = parseInt(colorString, 16); + var r = (integer >> 16) & 0xFF; + var g = (integer >> 8) & 0xFF; + var b = integer & 0xFF; + + return [r, g, b]; +}; + +convert.rgb.hcg = function (rgb) { + var r = rgb[0] / 255; + var g = rgb[1] / 255; + var b = rgb[2] / 255; + var max = Math.max(Math.max(r, g), b); + var min = Math.min(Math.min(r, g), b); + var chroma = (max - min); + var grayscale; + var hue; + + if (chroma < 1) { + grayscale = min / (1 - chroma); + } else { + grayscale = 0; + } + + if (chroma <= 0) { + hue = 0; + } else + if (max === r) { + hue = ((g - b) / chroma) % 6; + } else + if (max === g) { + hue = 2 + (b - r) / chroma; + } else { + hue = 4 + (r - g) / chroma + 4; + } + + hue /= 6; + hue %= 1; + + return [hue * 360, chroma * 100, grayscale * 100]; +}; + +convert.hsl.hcg = function (hsl) { + var s = hsl[1] / 100; + var l = hsl[2] / 100; + var c = 1; + var f = 0; + + if (l < 0.5) { + c = 2.0 * s * l; + } else { + c = 2.0 * s * (1.0 - l); + } + + if (c < 1.0) { + f = (l - 0.5 * c) / (1.0 - c); + } + + return [hsl[0], c * 100, f * 100]; +}; + +convert.hsv.hcg = function (hsv) { + var s = hsv[1] / 100; + var v = hsv[2] / 100; + + var c = s * v; + var f = 0; + + if (c < 1.0) { + f = (v - c) / (1 - c); + } + + return [hsv[0], c * 100, f * 100]; +}; + +convert.hcg.rgb = function (hcg) { + var h = hcg[0] / 360; + var c = hcg[1] / 100; + var g = hcg[2] / 100; + + if (c === 0.0) { + return [g * 255, g * 255, g * 255]; + } + + var pure = [0, 0, 0]; + var hi = (h % 1) * 6; + var v = hi % 1; + var w = 1 - v; + var mg = 0; + + switch (Math.floor(hi)) { + case 0: + pure[0] = 1; pure[1] = v; pure[2] = 0; break; + case 1: + pure[0] = w; pure[1] = 1; pure[2] = 0; break; + case 2: + pure[0] = 0; pure[1] = 1; pure[2] = v; break; + case 3: + pure[0] = 0; pure[1] = w; pure[2] = 1; break; + case 4: + pure[0] = v; pure[1] = 0; pure[2] = 1; break; + default: + pure[0] = 1; pure[1] = 0; pure[2] = w; + } + + mg = (1.0 - c) * g; + + return [ + (c * pure[0] + mg) * 255, + (c * pure[1] + mg) * 255, + (c * pure[2] + mg) * 255 + ]; +}; + +convert.hcg.hsv = function (hcg) { + var c = hcg[1] / 100; + var g = hcg[2] / 100; + + var v = c + g * (1.0 - c); + var f = 0; + + if (v > 0.0) { + f = c / v; + } + + return [hcg[0], f * 100, v * 100]; +}; + +convert.hcg.hsl = function (hcg) { + var c = hcg[1] / 100; + var g = hcg[2] / 100; + + var l = g * (1.0 - c) + 0.5 * c; + var s = 0; + + if (l > 0.0 && l < 0.5) { + s = c / (2 * l); + } else + if (l >= 0.5 && l < 1.0) { + s = c / (2 * (1 - l)); + } + + return [hcg[0], s * 100, l * 100]; +}; + +convert.hcg.hwb = function (hcg) { + var c = hcg[1] / 100; + var g = hcg[2] / 100; + var v = c + g * (1.0 - c); + return [hcg[0], (v - c) * 100, (1 - v) * 100]; +}; + +convert.hwb.hcg = function (hwb) { + var w = hwb[1] / 100; + var b = hwb[2] / 100; + var v = 1 - b; + var c = v - w; + var g = 0; + + if (c < 1) { + g = (v - c) / (1 - c); + } + + return [hwb[0], c * 100, g * 100]; +}; + +convert.apple.rgb = function (apple) { + return [(apple[0] / 65535) * 255, (apple[1] / 65535) * 255, (apple[2] / 65535) * 255]; +}; + +convert.rgb.apple = function (rgb) { + return [(rgb[0] / 255) * 65535, (rgb[1] / 255) * 65535, (rgb[2] / 255) * 65535]; +}; + +convert.gray.rgb = function (args) { + return [args[0] / 100 * 255, args[0] / 100 * 255, args[0] / 100 * 255]; +}; + +convert.gray.hsl = convert.gray.hsv = function (args) { + return [0, 0, args[0]]; +}; + +convert.gray.hwb = function (gray) { + return [0, 100, gray[0]]; +}; + +convert.gray.cmyk = function (gray) { + return [0, 0, 0, gray[0]]; +}; + +convert.gray.lab = function (gray) { + return [gray[0], 0, 0]; +}; + +convert.gray.hex = function (gray) { + var val = Math.round(gray[0] / 100 * 255) & 0xFF; + var integer = (val << 16) + (val << 8) + val; + + var string = integer.toString(16).toUpperCase(); + return '000000'.substring(string.length) + string; +}; + +convert.rgb.gray = function (rgb) { + var val = (rgb[0] + rgb[1] + rgb[2]) / 3; + return [val / 255 * 100]; +}; +}); +var conversions_1 = conversions.rgb; +var conversions_2 = conversions.hsl; +var conversions_3 = conversions.hsv; +var conversions_4 = conversions.hwb; +var conversions_5 = conversions.cmyk; +var conversions_6 = conversions.xyz; +var conversions_7 = conversions.lab; +var conversions_8 = conversions.lch; +var conversions_9 = conversions.hex; +var conversions_10 = conversions.keyword; +var conversions_11 = conversions.ansi16; +var conversions_12 = conversions.ansi256; +var conversions_13 = conversions.hcg; +var conversions_14 = conversions.apple; +var conversions_15 = conversions.gray; + +/* + this function routes a model to all other models. + + all functions that are routed have a property `.conversion` attached + to the returned synthetic function. This property is an array + of strings, each with the steps in between the 'from' and 'to' + color models (inclusive). + + conversions that are not possible simply are not included. +*/ + +function buildGraph() { + var graph = {}; + // https://jsperf.com/object-keys-vs-for-in-with-closure/3 + var models = Object.keys(conversions); + + for (var len = models.length, i = 0; i < len; i++) { + graph[models[i]] = { + // http://jsperf.com/1-vs-infinity + // micro-opt, but this is simple. + distance: -1, + parent: null + }; + } + + return graph; +} + +// https://en.wikipedia.org/wiki/Breadth-first_search +function deriveBFS(fromModel) { + var graph = buildGraph(); + var queue = [fromModel]; // unshift -> queue -> pop + + graph[fromModel].distance = 0; + + while (queue.length) { + var current = queue.pop(); + var adjacents = Object.keys(conversions[current]); + + for (var len = adjacents.length, i = 0; i < len; i++) { + var adjacent = adjacents[i]; + var node = graph[adjacent]; + + if (node.distance === -1) { + node.distance = graph[current].distance + 1; + node.parent = current; + queue.unshift(adjacent); + } + } + } + + return graph; +} + +function link(from, to) { + return function (args) { + return to(from(args)); + }; +} + +function wrapConversion(toModel, graph) { + var path = [graph[toModel].parent, toModel]; + var fn = conversions[graph[toModel].parent][toModel]; + + var cur = graph[toModel].parent; + while (graph[cur].parent) { + path.unshift(graph[cur].parent); + fn = link(conversions[graph[cur].parent][cur], fn); + cur = graph[cur].parent; + } + + fn.conversion = path; + return fn; +} + +var route = function (fromModel) { + var graph = deriveBFS(fromModel); + var conversion = {}; + + var models = Object.keys(graph); + for (var len = models.length, i = 0; i < len; i++) { + var toModel = models[i]; + var node = graph[toModel]; + + if (node.parent === null) { + // no possible conversion, or this node is the source model. + continue; + } + + conversion[toModel] = wrapConversion(toModel, graph); + } + + return conversion; +}; + +var convert = {}; + +var models = Object.keys(conversions); + +function wrapRaw(fn) { + var wrappedFn = function (args) { + if (args === undefined || args === null) { + return args; + } + + if (arguments.length > 1) { + args = Array.prototype.slice.call(arguments); + } + + return fn(args); + }; + + // preserve .conversion property if there is one + if ('conversion' in fn) { + wrappedFn.conversion = fn.conversion; + } + + return wrappedFn; +} + +function wrapRounded(fn) { + var wrappedFn = function (args) { + if (args === undefined || args === null) { + return args; + } + + if (arguments.length > 1) { + args = Array.prototype.slice.call(arguments); + } + + var result = fn(args); + + // we're assuming the result is an array here. + // see notice in conversions.js; don't use box types + // in conversion functions. + if (typeof result === 'object') { + for (var len = result.length, i = 0; i < len; i++) { + result[i] = Math.round(result[i]); + } + } + + return result; + }; + + // preserve .conversion property if there is one + if ('conversion' in fn) { + wrappedFn.conversion = fn.conversion; + } + + return wrappedFn; +} + +models.forEach(function (fromModel) { + convert[fromModel] = {}; + + Object.defineProperty(convert[fromModel], 'channels', {value: conversions[fromModel].channels}); + Object.defineProperty(convert[fromModel], 'labels', {value: conversions[fromModel].labels}); + + var routes = route(fromModel); + var routeModels = Object.keys(routes); + + routeModels.forEach(function (toModel) { + var fn = routes[toModel]; + + convert[fromModel][toModel] = wrapRounded(fn); + convert[fromModel][toModel].raw = wrapRaw(fn); + }); +}); + +var colorConvert = convert; + +var ansiStyles = createCommonjsModule(function (module) { + + +const wrapAnsi16 = (fn, offset) => function () { + const code = fn.apply(colorConvert, arguments); + return `\u001B[${code + offset}m`; +}; + +const wrapAnsi256 = (fn, offset) => function () { + const code = fn.apply(colorConvert, arguments); + return `\u001B[${38 + offset};5;${code}m`; +}; + +const wrapAnsi16m = (fn, offset) => function () { + const rgb = fn.apply(colorConvert, arguments); + return `\u001B[${38 + offset};2;${rgb[0]};${rgb[1]};${rgb[2]}m`; +}; + +function assembleStyles() { + const codes = new Map(); + const styles = { + modifier: { + reset: [0, 0], + // 21 isn't widely supported and 22 does the same thing + bold: [1, 22], + dim: [2, 22], + italic: [3, 23], + underline: [4, 24], + inverse: [7, 27], + hidden: [8, 28], + strikethrough: [9, 29] + }, + color: { + black: [30, 39], + red: [31, 39], + green: [32, 39], + yellow: [33, 39], + blue: [34, 39], + magenta: [35, 39], + cyan: [36, 39], + white: [37, 39], + gray: [90, 39], + + // Bright color + redBright: [91, 39], + greenBright: [92, 39], + yellowBright: [93, 39], + blueBright: [94, 39], + magentaBright: [95, 39], + cyanBright: [96, 39], + whiteBright: [97, 39] + }, + bgColor: { + bgBlack: [40, 49], + bgRed: [41, 49], + bgGreen: [42, 49], + bgYellow: [43, 49], + bgBlue: [44, 49], + bgMagenta: [45, 49], + bgCyan: [46, 49], + bgWhite: [47, 49], + + // Bright color + bgBlackBright: [100, 49], + bgRedBright: [101, 49], + bgGreenBright: [102, 49], + bgYellowBright: [103, 49], + bgBlueBright: [104, 49], + bgMagentaBright: [105, 49], + bgCyanBright: [106, 49], + bgWhiteBright: [107, 49] + } + }; + + // Fix humans + styles.color.grey = styles.color.gray; + + for (const groupName of Object.keys(styles)) { + const group = styles[groupName]; + + for (const styleName of Object.keys(group)) { + const style = group[styleName]; + + styles[styleName] = { + open: `\u001B[${style[0]}m`, + close: `\u001B[${style[1]}m` + }; + + group[styleName] = styles[styleName]; + + codes.set(style[0], style[1]); + } + + Object.defineProperty(styles, groupName, { + value: group, + enumerable: false + }); + + Object.defineProperty(styles, 'codes', { + value: codes, + enumerable: false + }); + } + + const ansi2ansi = n => n; + const rgb2rgb = (r, g, b) => [r, g, b]; + + styles.color.close = '\u001B[39m'; + styles.bgColor.close = '\u001B[49m'; + + styles.color.ansi = { + ansi: wrapAnsi16(ansi2ansi, 0) + }; + styles.color.ansi256 = { + ansi256: wrapAnsi256(ansi2ansi, 0) + }; + styles.color.ansi16m = { + rgb: wrapAnsi16m(rgb2rgb, 0) + }; + + styles.bgColor.ansi = { + ansi: wrapAnsi16(ansi2ansi, 10) + }; + styles.bgColor.ansi256 = { + ansi256: wrapAnsi256(ansi2ansi, 10) + }; + styles.bgColor.ansi16m = { + rgb: wrapAnsi16m(rgb2rgb, 10) + }; + + for (let key of Object.keys(colorConvert)) { + if (typeof colorConvert[key] !== 'object') { + continue; + } + + const suite = colorConvert[key]; + + if (key === 'ansi16') { + key = 'ansi'; + } + + if ('ansi16' in suite) { + styles.color.ansi[key] = wrapAnsi16(suite.ansi16, 0); + styles.bgColor.ansi[key] = wrapAnsi16(suite.ansi16, 10); + } + + if ('ansi256' in suite) { + styles.color.ansi256[key] = wrapAnsi256(suite.ansi256, 0); + styles.bgColor.ansi256[key] = wrapAnsi256(suite.ansi256, 10); + } + + if ('rgb' in suite) { + styles.color.ansi16m[key] = wrapAnsi16m(suite.rgb, 0); + styles.bgColor.ansi16m[key] = wrapAnsi16m(suite.rgb, 10); + } + } + + return styles; +} + +// Make the export immutable +Object.defineProperty(module, 'exports', { + enumerable: true, + get: assembleStyles +}); +}); + +var hasFlag = (flag, argv) => { + argv = argv || process.argv; + const prefix = flag.startsWith('-') ? '' : (flag.length === 1 ? '-' : '--'); + const pos = argv.indexOf(prefix + flag); + const terminatorPos = argv.indexOf('--'); + return pos !== -1 && (terminatorPos === -1 ? true : pos < terminatorPos); +}; + +const env = process.env; + +let forceColor; +if (hasFlag('no-color') || + hasFlag('no-colors') || + hasFlag('color=false')) { + forceColor = false; +} else if (hasFlag('color') || + hasFlag('colors') || + hasFlag('color=true') || + hasFlag('color=always')) { + forceColor = true; +} +if ('FORCE_COLOR' in env) { + forceColor = env.FORCE_COLOR.length === 0 || parseInt(env.FORCE_COLOR, 10) !== 0; +} + +function translateLevel(level) { + if (level === 0) { + return false; + } + + return { + level, + hasBasic: true, + has256: level >= 2, + has16m: level >= 3 + }; +} + +function supportsColor(stream) { + if (forceColor === false) { + return 0; + } + + if (hasFlag('color=16m') || + hasFlag('color=full') || + hasFlag('color=truecolor')) { + return 3; + } + + if (hasFlag('color=256')) { + return 2; + } + + if (stream && !stream.isTTY && forceColor !== true) { + return 0; + } + + const min = forceColor ? 1 : 0; + + if (process.platform === 'win32') { + // Node.js 7.5.0 is the first version of Node.js to include a patch to + // libuv that enables 256 color output on Windows. Anything earlier and it + // won't work. However, here we target Node.js 8 at minimum as it is an LTS + // release, and Node.js 7 is not. Windows 10 build 10586 is the first Windows + // release that supports 256 colors. Windows 10 build 14931 is the first release + // that supports 16m/TrueColor. + const osRelease = os.release().split('.'); + if ( + Number(process.versions.node.split('.')[0]) >= 8 && + Number(osRelease[0]) >= 10 && + Number(osRelease[2]) >= 10586 + ) { + return Number(osRelease[2]) >= 14931 ? 3 : 2; + } + + return 1; + } + + if ('CI' in env) { + if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI'].some(sign => sign in env) || env.CI_NAME === 'codeship') { + return 1; + } + + return min; + } + + if ('TEAMCITY_VERSION' in env) { + return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0; + } + + if (env.COLORTERM === 'truecolor') { + return 3; + } + + if ('TERM_PROGRAM' in env) { + const version = parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10); + + switch (env.TERM_PROGRAM) { + case 'iTerm.app': + return version >= 3 ? 3 : 2; + case 'Apple_Terminal': + return 2; + // No default + } + } + + if (/-256(color)?$/i.test(env.TERM)) { + return 2; + } + + if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) { + return 1; + } + + if ('COLORTERM' in env) { + return 1; + } + + if (env.TERM === 'dumb') { + return min; + } + + return min; +} + +function getSupportLevel(stream) { + const level = supportsColor(stream); + return translateLevel(level); +} + +var supportsColor_1 = { + supportsColor: getSupportLevel, + stdout: getSupportLevel(process.stdout), + stderr: getSupportLevel(process.stderr) +}; + +const TEMPLATE_REGEX = /(?:\\(u[a-f\d]{4}|x[a-f\d]{2}|.))|(?:\{(~)?(\w+(?:\([^)]*\))?(?:\.\w+(?:\([^)]*\))?)*)(?:[ \t]|(?=\r?\n)))|(\})|((?:.|[\r\n\f])+?)/gi; +const STYLE_REGEX = /(?:^|\.)(\w+)(?:\(([^)]*)\))?/g; +const STRING_REGEX = /^(['"])((?:\\.|(?!\1)[^\\])*)\1$/; +const ESCAPE_REGEX = /\\(u[a-f\d]{4}|x[a-f\d]{2}|.)|([^\\])/gi; + +const ESCAPES = new Map([ + ['n', '\n'], + ['r', '\r'], + ['t', '\t'], + ['b', '\b'], + ['f', '\f'], + ['v', '\v'], + ['0', '\0'], + ['\\', '\\'], + ['e', '\u001B'], + ['a', '\u0007'] +]); + +function unescape(c) { + if ((c[0] === 'u' && c.length === 5) || (c[0] === 'x' && c.length === 3)) { + return String.fromCharCode(parseInt(c.slice(1), 16)); + } + + return ESCAPES.get(c) || c; +} + +function parseArguments(name, args) { + const results = []; + const chunks = args.trim().split(/\s*,\s*/g); + let matches; + + for (const chunk of chunks) { + if (!isNaN(chunk)) { + results.push(Number(chunk)); + } else if ((matches = chunk.match(STRING_REGEX))) { + results.push(matches[2].replace(ESCAPE_REGEX, (m, escape, chr) => escape ? unescape(escape) : chr)); + } else { + throw new Error(`Invalid Chalk template style argument: ${chunk} (in style '${name}')`); + } + } + + return results; +} + +function parseStyle(style) { + STYLE_REGEX.lastIndex = 0; + + const results = []; + let matches; + + while ((matches = STYLE_REGEX.exec(style)) !== null) { + const name = matches[1]; + + if (matches[2]) { + const args = parseArguments(name, matches[2]); + results.push([name].concat(args)); + } else { + results.push([name]); + } + } + + return results; +} + +function buildStyle(chalk, styles) { + const enabled = {}; + + for (const layer of styles) { + for (const style of layer.styles) { + enabled[style[0]] = layer.inverse ? null : style.slice(1); + } + } + + let current = chalk; + for (const styleName of Object.keys(enabled)) { + if (Array.isArray(enabled[styleName])) { + if (!(styleName in current)) { + throw new Error(`Unknown Chalk style: ${styleName}`); + } + + if (enabled[styleName].length > 0) { + current = current[styleName].apply(current, enabled[styleName]); + } else { + current = current[styleName]; + } + } + } + + return current; +} + +var templates = (chalk, tmp) => { + const styles = []; + const chunks = []; + let chunk = []; + + // eslint-disable-next-line max-params + tmp.replace(TEMPLATE_REGEX, (m, escapeChar, inverse, style, close, chr) => { + if (escapeChar) { + chunk.push(unescape(escapeChar)); + } else if (style) { + const str = chunk.join(''); + chunk = []; + chunks.push(styles.length === 0 ? str : buildStyle(chalk, styles)(str)); + styles.push({inverse, styles: parseStyle(style)}); + } else if (close) { + if (styles.length === 0) { + throw new Error('Found extraneous } in Chalk template literal'); + } + + chunks.push(buildStyle(chalk, styles)(chunk.join(''))); + chunk = []; + styles.pop(); + } else { + chunk.push(chr); + } + }); + + chunks.push(chunk.join('')); + + if (styles.length > 0) { + const errMsg = `Chalk template literal is missing ${styles.length} closing bracket${styles.length === 1 ? '' : 's'} (\`}\`)`; + throw new Error(errMsg); + } + + return chunks.join(''); +}; + +var chalk = createCommonjsModule(function (module) { + + +const stdoutColor = supportsColor_1.stdout; + + + +const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm'); + +// `supportsColor.level` → `ansiStyles.color[name]` mapping +const levelMapping = ['ansi', 'ansi', 'ansi256', 'ansi16m']; + +// `color-convert` models to exclude from the Chalk API due to conflicts and such +const skipModels = new Set(['gray']); + +const styles = Object.create(null); + +function applyOptions(obj, options) { + options = options || {}; + + // Detect level if not set manually + const scLevel = stdoutColor ? stdoutColor.level : 0; + obj.level = options.level === undefined ? scLevel : options.level; + obj.enabled = 'enabled' in options ? options.enabled : obj.level > 0; +} + +function Chalk(options) { + // We check for this.template here since calling `chalk.constructor()` + // by itself will have a `this` of a previously constructed chalk object + if (!this || !(this instanceof Chalk) || this.template) { + const chalk = {}; + applyOptions(chalk, options); + + chalk.template = function () { + const args = [].slice.call(arguments); + return chalkTag.apply(null, [chalk.template].concat(args)); + }; + + Object.setPrototypeOf(chalk, Chalk.prototype); + Object.setPrototypeOf(chalk.template, chalk); + + chalk.template.constructor = Chalk; + + return chalk.template; + } + + applyOptions(this, options); +} + +// Use bright blue on Windows as the normal blue color is illegible +if (isSimpleWindowsTerm) { + ansiStyles.blue.open = '\u001B[94m'; +} + +for (const key of Object.keys(ansiStyles)) { + ansiStyles[key].closeRe = new RegExp(escapeStringRegexp(ansiStyles[key].close), 'g'); + + styles[key] = { + get() { + const codes = ansiStyles[key]; + return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, key); + } + }; +} + +styles.visible = { + get() { + return build.call(this, this._styles || [], true, 'visible'); + } +}; + +ansiStyles.color.closeRe = new RegExp(escapeStringRegexp(ansiStyles.color.close), 'g'); +for (const model of Object.keys(ansiStyles.color.ansi)) { + if (skipModels.has(model)) { + continue; + } + + styles[model] = { + get() { + const level = this.level; + return function () { + const open = ansiStyles.color[levelMapping[level]][model].apply(null, arguments); + const codes = { + open, + close: ansiStyles.color.close, + closeRe: ansiStyles.color.closeRe + }; + return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, model); + }; + } + }; +} + +ansiStyles.bgColor.closeRe = new RegExp(escapeStringRegexp(ansiStyles.bgColor.close), 'g'); +for (const model of Object.keys(ansiStyles.bgColor.ansi)) { + if (skipModels.has(model)) { + continue; + } + + const bgModel = 'bg' + model[0].toUpperCase() + model.slice(1); + styles[bgModel] = { + get() { + const level = this.level; + return function () { + const open = ansiStyles.bgColor[levelMapping[level]][model].apply(null, arguments); + const codes = { + open, + close: ansiStyles.bgColor.close, + closeRe: ansiStyles.bgColor.closeRe + }; + return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, model); + }; + } + }; +} + +const proto = Object.defineProperties(() => {}, styles); + +function build(_styles, _empty, key) { + const builder = function () { + return applyStyle.apply(builder, arguments); + }; + + builder._styles = _styles; + builder._empty = _empty; + + const self = this; + + Object.defineProperty(builder, 'level', { + enumerable: true, + get() { + return self.level; + }, + set(level) { + self.level = level; + } + }); + + Object.defineProperty(builder, 'enabled', { + enumerable: true, + get() { + return self.enabled; + }, + set(enabled) { + self.enabled = enabled; + } + }); + + // See below for fix regarding invisible grey/dim combination on Windows + builder.hasGrey = this.hasGrey || key === 'gray' || key === 'grey'; + + // `__proto__` is used because we must return a function, but there is + // no way to create a function with a different prototype + builder.__proto__ = proto; // eslint-disable-line no-proto + + return builder; +} + +function applyStyle() { + // Support varags, but simply cast to string in case there's only one arg + const args = arguments; + const argsLen = args.length; + let str = String(arguments[0]); + + if (argsLen === 0) { + return ''; + } + + if (argsLen > 1) { + // Don't slice `arguments`, it prevents V8 optimizations + for (let a = 1; a < argsLen; a++) { + str += ' ' + args[a]; + } + } + + if (!this.enabled || this.level <= 0 || !str) { + return this._empty ? '' : str; + } + + // Turns out that on Windows dimmed gray text becomes invisible in cmd.exe, + // see https://github.com/chalk/chalk/issues/58 + // If we're on Windows and we're dealing with a gray color, temporarily make 'dim' a noop. + const originalDim = ansiStyles.dim.open; + if (isSimpleWindowsTerm && this.hasGrey) { + ansiStyles.dim.open = ''; + } + + for (const code of this._styles.slice().reverse()) { + // Replace any instances already present with a re-opening code + // otherwise only the part of the string until said closing code + // will be colored, and the rest will simply be 'plain'. + str = code.open + str.replace(code.closeRe, code.open) + code.close; + + // Close the styling before a linebreak and reopen + // after next line to fix a bleed issue on macOS + // https://github.com/chalk/chalk/pull/92 + str = str.replace(/\r?\n/g, `${code.close}$&${code.open}`); + } + + // Reset the original `dim` if we changed it to work around the Windows dimmed gray issue + ansiStyles.dim.open = originalDim; + + return str; +} + +function chalkTag(chalk, strings) { + if (!Array.isArray(strings)) { + // If chalk() was called by itself or with a string, + // return the string itself as a string. + return [].slice.call(arguments, 1).join(' '); + } + + const args = [].slice.call(arguments, 2); + const parts = [strings.raw[0]]; + + for (let i = 1; i < strings.length; i++) { + parts.push(String(args[i - 1]).replace(/[{}\\]/g, '\\$&')); + parts.push(String(strings.raw[i])); + } + + return templates(chalk, parts.join('')); +} + +Object.defineProperties(Chalk.prototype, styles); + +module.exports = Chalk(); // eslint-disable-line new-cap +module.exports.supportsColor = stdoutColor; +module.exports.default = module.exports; // For TypeScript +}); +var chalk_1 = chalk.supportsColor; + +var lib$1 = createCommonjsModule(function (module, exports) { + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.shouldHighlight = shouldHighlight; +exports.getChalk = getChalk; +exports.default = highlight; + +var _jsTokens = _interopRequireWildcard(jsTokens); + + + +var _chalk = _interopRequireDefault(chalk); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +function getDefs(chalk) { + return { + keyword: chalk.cyan, + capitalized: chalk.yellow, + jsx_tag: chalk.yellow, + punctuator: chalk.yellow, + number: chalk.magenta, + string: chalk.green, + regex: chalk.magenta, + comment: chalk.grey, + invalid: chalk.white.bgRed.bold + }; +} + +const NEWLINE = /\r\n|[\n\r\u2028\u2029]/; +const JSX_TAG = /^[a-z][\w-]*$/i; +const BRACKET = /^[()[\]{}]$/; + +function getTokenType(match) { + const [offset, text] = match.slice(-2); + const token = (0, _jsTokens.matchToToken)(match); + + if (token.type === "name") { + if ((0, lib.isKeyword)(token.value) || (0, lib.isReservedWord)(token.value)) { + return "keyword"; + } + + if (JSX_TAG.test(token.value) && (text[offset - 1] === "<" || text.substr(offset - 2, 2) == " colorize(str)).join("\n"); + } else { + return args[0]; + } + }); +} + +function shouldHighlight(options) { + return _chalk.default.supportsColor || options.forceColor; +} + +function getChalk(options) { + let chalk = _chalk.default; + + if (options.forceColor) { + chalk = new _chalk.default.constructor({ + enabled: true, + level: 1 + }); + } + + return chalk; +} + +function highlight(code, options = {}) { + if (shouldHighlight(options)) { + const chalk = getChalk(options); + const defs = getDefs(chalk); + return highlightTokens(defs, code); + } else { + return code; + } +} +}); + +unwrapExports(lib$1); +var lib_1 = lib$1.shouldHighlight; +var lib_2 = lib$1.getChalk; + +var lib$2 = createCommonjsModule(function (module, exports) { + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.codeFrameColumns = codeFrameColumns; +exports.default = _default; + +var _highlight = _interopRequireWildcard(lib$1); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +let deprecationWarningShown = false; + +function getDefs(chalk) { + return { + gutter: chalk.grey, + marker: chalk.red.bold, + message: chalk.red.bold + }; +} + +const NEWLINE = /\r\n|[\n\r\u2028\u2029]/; + +function getMarkerLines(loc, source, opts) { + const startLoc = Object.assign({ + column: 0, + line: -1 + }, loc.start); + const endLoc = Object.assign({}, startLoc, {}, loc.end); + const { + linesAbove = 2, + linesBelow = 3 + } = opts || {}; + const startLine = startLoc.line; + const startColumn = startLoc.column; + const endLine = endLoc.line; + const endColumn = endLoc.column; + let start = Math.max(startLine - (linesAbove + 1), 0); + let end = Math.min(source.length, endLine + linesBelow); + + if (startLine === -1) { + start = 0; + } + + if (endLine === -1) { + end = source.length; + } + + const lineDiff = endLine - startLine; + const markerLines = {}; + + if (lineDiff) { + for (let i = 0; i <= lineDiff; i++) { + const lineNumber = i + startLine; + + if (!startColumn) { + markerLines[lineNumber] = true; + } else if (i === 0) { + const sourceLength = source[lineNumber - 1].length; + markerLines[lineNumber] = [startColumn, sourceLength - startColumn + 1]; + } else if (i === lineDiff) { + markerLines[lineNumber] = [0, endColumn]; + } else { + const sourceLength = source[lineNumber - i].length; + markerLines[lineNumber] = [0, sourceLength]; + } + } + } else { + if (startColumn === endColumn) { + if (startColumn) { + markerLines[startLine] = [startColumn, 0]; + } else { + markerLines[startLine] = true; + } + } else { + markerLines[startLine] = [startColumn, endColumn - startColumn]; + } + } + + return { + start, + end, + markerLines + }; +} + +function codeFrameColumns(rawLines, loc, opts = {}) { + const highlighted = (opts.highlightCode || opts.forceColor) && (0, _highlight.shouldHighlight)(opts); + const chalk = (0, _highlight.getChalk)(opts); + const defs = getDefs(chalk); + + const maybeHighlight = (chalkFn, string) => { + return highlighted ? chalkFn(string) : string; + }; + + const lines = rawLines.split(NEWLINE); + const { + start, + end, + markerLines + } = getMarkerLines(loc, lines, opts); + const hasColumns = loc.start && typeof loc.start.column === "number"; + const numberMaxWidth = String(end).length; + const highlightedLines = highlighted ? (0, _highlight.default)(rawLines, opts) : rawLines; + let frame = highlightedLines.split(NEWLINE).slice(start, end).map((line, index) => { + const number = start + 1 + index; + const paddedNumber = ` ${number}`.slice(-numberMaxWidth); + const gutter = ` ${paddedNumber} | `; + const hasMarker = markerLines[number]; + const lastMarkerLine = !markerLines[number + 1]; + + if (hasMarker) { + let markerLine = ""; + + if (Array.isArray(hasMarker)) { + const markerSpacing = line.slice(0, Math.max(hasMarker[0] - 1, 0)).replace(/[^\t]/g, " "); + const numberOfMarkers = hasMarker[1] || 1; + markerLine = ["\n ", maybeHighlight(defs.gutter, gutter.replace(/\d/g, " ")), markerSpacing, maybeHighlight(defs.marker, "^").repeat(numberOfMarkers)].join(""); + + if (lastMarkerLine && opts.message) { + markerLine += " " + maybeHighlight(defs.message, opts.message); + } + } + + return [maybeHighlight(defs.marker, ">"), maybeHighlight(defs.gutter, gutter), line, markerLine].join(""); + } else { + return ` ${maybeHighlight(defs.gutter, gutter)}${line}`; + } + }).join("\n"); + + if (opts.message && !hasColumns) { + frame = `${" ".repeat(numberMaxWidth + 1)}${opts.message}\n${frame}`; + } + + if (highlighted) { + return chalk.reset(frame); + } else { + return frame; + } +} + +function _default(rawLines, lineNumber, colNumber, opts = {}) { + if (!deprecationWarningShown) { + deprecationWarningShown = true; + const message = "Passing lineNumber and colNumber is deprecated to @babel/code-frame. Please use `codeFrameColumns`."; + + if (process.emitWarning) { + process.emitWarning(message, "DeprecationWarning"); + } else { + const deprecationError = new Error(message); + deprecationError.name = "DeprecationWarning"; + console.warn(new Error(message)); + } + } + + colNumber = Math.max(colNumber, 0); + const location = { + start: { + column: colNumber, + line: lineNumber + } + }; + return codeFrameColumns(rawLines, location, opts); +} +}); + +unwrapExports(lib$2); +var lib_1$1 = lib$2.codeFrameColumns; + +var require$$0 = getCjsExportFromNamespace(dist); + +const {default: LinesAndColumns$1} = require$$0; +const {codeFrameColumns} = lib$2; + +const JSONError = errorEx_1('JSONError', { + fileName: errorEx_1.append('in %s'), + codeFrame: errorEx_1.append('\n\n%s\n') +}); + +var parseJson$1 = (string, reviver, filename) => { + if (typeof reviver === 'string') { + filename = reviver; + reviver = null; + } + + try { + try { + return JSON.parse(string, reviver); + } catch (error) { + jsonParseBetterErrors(string, reviver); + throw error; + } + } catch (error) { + error.message = error.message.replace(/\n/g, ''); + const indexMatch = error.message.match(/in JSON at position (\d+) while parsing near/); + + const jsonError = new JSONError(error); + if (filename) { + jsonError.fileName = filename; + } + + if (indexMatch && indexMatch.length > 0) { + const lines = new LinesAndColumns$1(string); + const index = Number(indexMatch[1]); + const location = lines.locationForIndex(index); + + const codeFrame = codeFrameColumns( + string, + {start: {line: location.line + 1, column: location.column + 1}}, + {highlightCode: true} + ); + + jsonError.codeFrame = codeFrame; + } + + throw jsonError; + } +}; + +/** + * Helpers. + */ + +var s = 1000; +var m = s * 60; +var h = m * 60; +var d = h * 24; +var w = d * 7; +var y = d * 365.25; + +/** + * Parse or format the given `val`. + * + * Options: + * + * - `long` verbose formatting [false] + * + * @param {String|Number} val + * @param {Object} [options] + * @throws {Error} throw an error if val is not a non-empty string or a number + * @return {String|Number} + * @api public + */ + +var ms = function(val, options) { + options = options || {}; + var type = typeof val; + if (type === 'string' && val.length > 0) { + return parse$1(val); + } else if (type === 'number' && isFinite(val)) { + return options.long ? fmtLong(val) : fmtShort(val); + } + throw new Error( + 'val is not a non-empty string or a valid number. val=' + + JSON.stringify(val) + ); +}; + +/** + * Parse the given `str` and return milliseconds. + * + * @param {String} str + * @return {Number} + * @api private + */ + +function parse$1(str) { + str = String(str); + if (str.length > 100) { + return; + } + var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec( + str + ); + if (!match) { + return; + } + var n = parseFloat(match[1]); + var type = (match[2] || 'ms').toLowerCase(); + switch (type) { + case 'years': + case 'year': + case 'yrs': + case 'yr': + case 'y': + return n * y; + case 'weeks': + case 'week': + case 'w': + return n * w; + case 'days': + case 'day': + case 'd': + return n * d; + case 'hours': + case 'hour': + case 'hrs': + case 'hr': + case 'h': + return n * h; + case 'minutes': + case 'minute': + case 'mins': + case 'min': + case 'm': + return n * m; + case 'seconds': + case 'second': + case 'secs': + case 'sec': + case 's': + return n * s; + case 'milliseconds': + case 'millisecond': + case 'msecs': + case 'msec': + case 'ms': + return n; + default: + return undefined; + } +} + +/** + * Short format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function fmtShort(ms) { + var msAbs = Math.abs(ms); + if (msAbs >= d) { + return Math.round(ms / d) + 'd'; + } + if (msAbs >= h) { + return Math.round(ms / h) + 'h'; + } + if (msAbs >= m) { + return Math.round(ms / m) + 'm'; + } + if (msAbs >= s) { + return Math.round(ms / s) + 's'; + } + return ms + 'ms'; +} + +/** + * Long format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function fmtLong(ms) { + var msAbs = Math.abs(ms); + if (msAbs >= d) { + return plural(ms, msAbs, d, 'day'); + } + if (msAbs >= h) { + return plural(ms, msAbs, h, 'hour'); + } + if (msAbs >= m) { + return plural(ms, msAbs, m, 'minute'); + } + if (msAbs >= s) { + return plural(ms, msAbs, s, 'second'); + } + return ms + ' ms'; +} + +/** + * Pluralization helper. + */ + +function plural(ms, msAbs, n, name) { + var isPlural = msAbs >= n * 1.5; + return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : ''); +} + +/** + * This is the common logic for both the Node.js and web browser + * implementations of `debug()`. + */ + +function setup(env) { + createDebug.debug = createDebug; + createDebug.default = createDebug; + createDebug.coerce = coerce; + createDebug.disable = disable; + createDebug.enable = enable; + createDebug.enabled = enabled; + createDebug.humanize = ms; + + Object.keys(env).forEach(key => { + createDebug[key] = env[key]; + }); + + /** + * Active `debug` instances. + */ + createDebug.instances = []; + + /** + * The currently active debug mode names, and names to skip. + */ + + createDebug.names = []; + createDebug.skips = []; + + /** + * Map of special "%n" handling functions, for the debug "format" argument. + * + * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". + */ + createDebug.formatters = {}; + + /** + * Selects a color for a debug namespace + * @param {String} namespace The namespace string for the for the debug instance to be colored + * @return {Number|String} An ANSI color code for the given namespace + * @api private + */ + function selectColor(namespace) { + let hash = 0; + + for (let i = 0; i < namespace.length; i++) { + hash = ((hash << 5) - hash) + namespace.charCodeAt(i); + hash |= 0; // Convert to 32bit integer + } + + return createDebug.colors[Math.abs(hash) % createDebug.colors.length]; + } + createDebug.selectColor = selectColor; + + /** + * Create a debugger with the given `namespace`. + * + * @param {String} namespace + * @return {Function} + * @api public + */ + function createDebug(namespace) { + let prevTime; + + function debug(...args) { + // Disabled? + if (!debug.enabled) { + return; + } + + const self = debug; + + // Set `diff` timestamp + const curr = Number(new Date()); + const ms = curr - (prevTime || curr); + self.diff = ms; + self.prev = prevTime; + self.curr = curr; + prevTime = curr; + + args[0] = createDebug.coerce(args[0]); + + if (typeof args[0] !== 'string') { + // Anything else let's inspect with %O + args.unshift('%O'); + } + + // Apply any `formatters` transformations + let index = 0; + args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => { + // If we encounter an escaped % then don't increase the array index + if (match === '%%') { + return match; + } + index++; + const formatter = createDebug.formatters[format]; + if (typeof formatter === 'function') { + const val = args[index]; + match = formatter.call(self, val); + + // Now we need to remove `args[index]` since it's inlined in the `format` + args.splice(index, 1); + index--; + } + return match; + }); + + // Apply env-specific formatting (colors, etc.) + createDebug.formatArgs.call(self, args); + + const logFn = self.log || createDebug.log; + logFn.apply(self, args); + } + + debug.namespace = namespace; + debug.enabled = createDebug.enabled(namespace); + debug.useColors = createDebug.useColors(); + debug.color = selectColor(namespace); + debug.destroy = destroy; + debug.extend = extend; + // Debug.formatArgs = formatArgs; + // debug.rawLog = rawLog; + + // env-specific initialization logic for debug instances + if (typeof createDebug.init === 'function') { + createDebug.init(debug); + } + + createDebug.instances.push(debug); + + return debug; + } + + function destroy() { + const index = createDebug.instances.indexOf(this); + if (index !== -1) { + createDebug.instances.splice(index, 1); + return true; + } + return false; + } + + function extend(namespace, delimiter) { + const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace); + newDebug.log = this.log; + return newDebug; + } + + /** + * Enables a debug mode by namespaces. This can include modes + * separated by a colon and wildcards. + * + * @param {String} namespaces + * @api public + */ + function enable(namespaces) { + createDebug.save(namespaces); + + createDebug.names = []; + createDebug.skips = []; + + let i; + const split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); + const len = split.length; + + for (i = 0; i < len; i++) { + if (!split[i]) { + // ignore empty strings + continue; + } + + namespaces = split[i].replace(/\*/g, '.*?'); + + if (namespaces[0] === '-') { + createDebug.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); + } else { + createDebug.names.push(new RegExp('^' + namespaces + '$')); + } + } + + for (i = 0; i < createDebug.instances.length; i++) { + const instance = createDebug.instances[i]; + instance.enabled = createDebug.enabled(instance.namespace); + } + } + + /** + * Disable debug output. + * + * @return {String} namespaces + * @api public + */ + function disable() { + const namespaces = [ + ...createDebug.names.map(toNamespace), + ...createDebug.skips.map(toNamespace).map(namespace => '-' + namespace) + ].join(','); + createDebug.enable(''); + return namespaces; + } + + /** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public */ function enabled(name) { if (name[name.length - 1] === '*') { @@ -4746,514 +7209,97 @@ exports.colors = [ '#FF6633', '#FF9900', '#FF9933', - '#FFCC00', - '#FFCC33' -]; - -/** - * Currently only WebKit-based Web Inspectors, Firefox >= v31, - * and the Firebug extension (any Firefox version) are known - * to support "%c" CSS customizations. - * - * TODO: add a `localStorage` variable to explicitly enable/disable colors - */ - -// eslint-disable-next-line complexity -function useColors() { - // NB: In an Electron preload script, document will be defined but not fully - // initialized. Since we know we're in Chrome, we'll just detect this case - // explicitly - if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) { - return true; - } - - // Internet Explorer and Edge do not support colors. - if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) { - return false; - } - - // Is webkit? http://stackoverflow.com/a/16459606/376773 - // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 - return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || - // Is firebug? http://stackoverflow.com/a/398120/376773 - (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || - // Is firefox >= v31? - // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages - (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) || - // Double check webkit in userAgent just in case we are in a worker - (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); -} - -/** - * Colorize log arguments if enabled. - * - * @api public - */ - -function formatArgs(args) { - args[0] = (this.useColors ? '%c' : '') + - this.namespace + - (this.useColors ? ' %c' : ' ') + - args[0] + - (this.useColors ? '%c ' : ' ') + - '+' + module.exports.humanize(this.diff); - - if (!this.useColors) { - return; - } - - const c = 'color: ' + this.color; - args.splice(1, 0, c, 'color: inherit'); - - // The final "%c" is somewhat tricky, because there could be other - // arguments passed either before or after the %c, so we need to - // figure out the correct index to insert the CSS into - let index = 0; - let lastC = 0; - args[0].replace(/%[a-zA-Z%]/g, match => { - if (match === '%%') { - return; - } - index++; - if (match === '%c') { - // We only are interested in the *last* %c - // (the user may have provided their own) - lastC = index; - } - }); - - args.splice(lastC, 0, c); -} - -/** - * Invokes `console.log()` when available. - * No-op when `console.log` is not a "function". - * - * @api public - */ -function log(...args) { - // This hackery is required for IE8/9, where - // the `console.log` function doesn't have 'apply' - return typeof console === 'object' && - console.log && - console.log(...args); -} - -/** - * Save `namespaces`. - * - * @param {String} namespaces - * @api private - */ -function save(namespaces) { - try { - if (namespaces) { - exports.storage.setItem('debug', namespaces); - } else { - exports.storage.removeItem('debug'); - } - } catch (error) { - // Swallow - // XXX (@Qix-) should we be logging these? - } -} - -/** - * Load `namespaces`. - * - * @return {String} returns the previously persisted debug modes - * @api private - */ -function load() { - let r; - try { - r = exports.storage.getItem('debug'); - } catch (error) { - // Swallow - // XXX (@Qix-) should we be logging these? - } - - // If debug isn't set in LS, and we're in Electron, try to load $DEBUG - if (!r && typeof process !== 'undefined' && 'env' in process) { - r = process.env.DEBUG; - } - - return r; -} - -/** - * Localstorage attempts to return the localstorage. - * - * This is necessary because safari throws - * when a user disables cookies/localstorage - * and you attempt to access it. - * - * @return {LocalStorage} - * @api private - */ - -function localstorage() { - try { - // TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context - // The Browser also has localStorage in the global context. - return localStorage; - } catch (error) { - // Swallow - // XXX (@Qix-) should we be logging these? - } -} - -module.exports = common$1(exports); - -const {formatters} = module.exports; - -/** - * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. - */ - -formatters.j = function (v) { - try { - return JSON.stringify(v); - } catch (error) { - return '[UnexpectedJSONParseError]: ' + error.message; - } -}; -}); -var browser_1 = browser.log; -var browser_2 = browser.formatArgs; -var browser_3 = browser.save; -var browser_4 = browser.load; -var browser_5 = browser.useColors; -var browser_6 = browser.storage; -var browser_7 = browser.colors; - -var hasFlag = (flag, argv) => { - argv = argv || process.argv; - const prefix = flag.startsWith('-') ? '' : (flag.length === 1 ? '-' : '--'); - const pos = argv.indexOf(prefix + flag); - const terminatorPos = argv.indexOf('--'); - return pos !== -1 && (terminatorPos === -1 ? true : pos < terminatorPos); -}; - -const env = process.env; - -let forceColor; -if (hasFlag('no-color') || - hasFlag('no-colors') || - hasFlag('color=false')) { - forceColor = false; -} else if (hasFlag('color') || - hasFlag('colors') || - hasFlag('color=true') || - hasFlag('color=always')) { - forceColor = true; -} -if ('FORCE_COLOR' in env) { - forceColor = env.FORCE_COLOR.length === 0 || parseInt(env.FORCE_COLOR, 10) !== 0; -} - -function translateLevel(level) { - if (level === 0) { - return false; - } - - return { - level, - hasBasic: true, - has256: level >= 2, - has16m: level >= 3 - }; -} - -function supportsColor(stream) { - if (forceColor === false) { - return 0; - } - - if (hasFlag('color=16m') || - hasFlag('color=full') || - hasFlag('color=truecolor')) { - return 3; - } - - if (hasFlag('color=256')) { - return 2; - } - - if (stream && !stream.isTTY && forceColor !== true) { - return 0; - } - - const min = forceColor ? 1 : 0; - - if (process.platform === 'win32') { - // Node.js 7.5.0 is the first version of Node.js to include a patch to - // libuv that enables 256 color output on Windows. Anything earlier and it - // won't work. However, here we target Node.js 8 at minimum as it is an LTS - // release, and Node.js 7 is not. Windows 10 build 10586 is the first Windows - // release that supports 256 colors. Windows 10 build 14931 is the first release - // that supports 16m/TrueColor. - const osRelease = os.release().split('.'); - if ( - Number(process.versions.node.split('.')[0]) >= 8 && - Number(osRelease[0]) >= 10 && - Number(osRelease[2]) >= 10586 - ) { - return Number(osRelease[2]) >= 14931 ? 3 : 2; - } - - return 1; - } - - if ('CI' in env) { - if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI'].some(sign => sign in env) || env.CI_NAME === 'codeship') { - return 1; - } - - return min; - } - - if ('TEAMCITY_VERSION' in env) { - return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0; - } - - if (env.COLORTERM === 'truecolor') { - return 3; - } - - if ('TERM_PROGRAM' in env) { - const version = parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10); - - switch (env.TERM_PROGRAM) { - case 'iTerm.app': - return version >= 3 ? 3 : 2; - case 'Apple_Terminal': - return 2; - // No default - } - } - - if (/-256(color)?$/i.test(env.TERM)) { - return 2; - } - - if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) { - return 1; - } - - if ('COLORTERM' in env) { - return 1; - } - - if (env.TERM === 'dumb') { - return min; - } - - return min; -} - -function getSupportLevel(stream) { - const level = supportsColor(stream); - return translateLevel(level); -} - -var supportsColor_1 = { - supportsColor: getSupportLevel, - stdout: getSupportLevel(process.stdout), - stderr: getSupportLevel(process.stderr) -}; - -var node = createCommonjsModule(function (module, exports) { -/** - * Module dependencies. - */ - - - - -/** - * This is the Node.js implementation of `debug()`. - */ - -exports.init = init; -exports.log = log; -exports.formatArgs = formatArgs; -exports.save = save; -exports.load = load; -exports.useColors = useColors; - -/** - * Colors. - */ - -exports.colors = [6, 2, 3, 4, 5, 1]; - -try { - // Optional dependency (as in, doesn't need to be installed, NOT like optionalDependencies in package.json) - // eslint-disable-next-line import/no-extraneous-dependencies - const supportsColor = supportsColor_1; - - if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) { - exports.colors = [ - 20, - 21, - 26, - 27, - 32, - 33, - 38, - 39, - 40, - 41, - 42, - 43, - 44, - 45, - 56, - 57, - 62, - 63, - 68, - 69, - 74, - 75, - 76, - 77, - 78, - 79, - 80, - 81, - 92, - 93, - 98, - 99, - 112, - 113, - 128, - 129, - 134, - 135, - 148, - 149, - 160, - 161, - 162, - 163, - 164, - 165, - 166, - 167, - 168, - 169, - 170, - 171, - 172, - 173, - 178, - 179, - 184, - 185, - 196, - 197, - 198, - 199, - 200, - 201, - 202, - 203, - 204, - 205, - 206, - 207, - 208, - 209, - 214, - 215, - 220, - 221 - ]; - } -} catch (error) { - // Swallow - we only care if `supports-color` is available; it doesn't have to be. -} - -/** - * Build up the default `inspectOpts` object from the environment variables. - * - * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js - */ - -exports.inspectOpts = Object.keys(process.env).filter(key => { - return /^debug_/i.test(key); -}).reduce((obj, key) => { - // Camel-case - const prop = key - .substring(6) - .toLowerCase() - .replace(/_([a-z])/g, (_, k) => { - return k.toUpperCase(); - }); - - // Coerce string value into JS value - let val = process.env[key]; - if (/^(yes|on|true|enabled)$/i.test(val)) { - val = true; - } else if (/^(no|off|false|disabled)$/i.test(val)) { - val = false; - } else if (val === 'null') { - val = null; - } else { - val = Number(val); - } - - obj[prop] = val; - return obj; -}, {}); + '#FFCC00', + '#FFCC33' +]; /** - * Is stdout a TTY? Colored output is enabled when `true`. + * Currently only WebKit-based Web Inspectors, Firefox >= v31, + * and the Firebug extension (any Firefox version) are known + * to support "%c" CSS customizations. + * + * TODO: add a `localStorage` variable to explicitly enable/disable colors */ +// eslint-disable-next-line complexity function useColors() { - return 'colors' in exports.inspectOpts ? - Boolean(exports.inspectOpts.colors) : - tty.isatty(process.stderr.fd); + // NB: In an Electron preload script, document will be defined but not fully + // initialized. Since we know we're in Chrome, we'll just detect this case + // explicitly + if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) { + return true; + } + + // Internet Explorer and Edge do not support colors. + if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) { + return false; + } + + // Is webkit? http://stackoverflow.com/a/16459606/376773 + // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 + return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || + // Is firebug? http://stackoverflow.com/a/398120/376773 + (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || + // Is firefox >= v31? + // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) || + // Double check webkit in userAgent just in case we are in a worker + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); } /** - * Adds ANSI color escape codes if enabled. + * Colorize log arguments if enabled. * * @api public */ function formatArgs(args) { - const {namespace: name, useColors} = this; - - if (useColors) { - const c = this.color; - const colorCode = '\u001B[3' + (c < 8 ? c : '8;5;' + c); - const prefix = ` ${colorCode};1m${name} \u001B[0m`; + args[0] = (this.useColors ? '%c' : '') + + this.namespace + + (this.useColors ? ' %c' : ' ') + + args[0] + + (this.useColors ? '%c ' : ' ') + + '+' + module.exports.humanize(this.diff); - args[0] = prefix + args[0].split('\n').join('\n' + prefix); - args.push(colorCode + 'm+' + module.exports.humanize(this.diff) + '\u001B[0m'); - } else { - args[0] = getDate() + name + ' ' + args[0]; + if (!this.useColors) { + return; } -} -function getDate() { - if (exports.inspectOpts.hideDate) { - return ''; - } - return new Date().toISOString() + ' '; + const c = 'color: ' + this.color; + args.splice(1, 0, c, 'color: inherit'); + + // The final "%c" is somewhat tricky, because there could be other + // arguments passed either before or after the %c, so we need to + // figure out the correct index to insert the CSS into + let index = 0; + let lastC = 0; + args[0].replace(/%[a-zA-Z%]/g, match => { + if (match === '%%') { + return; + } + index++; + if (match === '%c') { + // We only are interested in the *last* %c + // (the user may have provided their own) + lastC = index; + } + }); + + args.splice(lastC, 0, c); } /** - * Invokes `util.format()` with the specified arguments and writes to stderr. + * Invokes `console.log()` when available. + * No-op when `console.log` is not a "function". + * + * @api public */ - function log(...args) { - return process.stderr.write(util$1.format(...args) + '\n'); + // This hackery is required for IE8/9, where + // the `console.log` function doesn't have 'apply' + return typeof console === 'object' && + console.log && + console.log(...args); } /** @@ -5263,12 +7309,15 @@ function log(...args) { * @api private */ function save(namespaces) { - if (namespaces) { - process.env.DEBUG = namespaces; - } else { - // If you set a process.env field to null or undefined, it gets cast to the - // string 'null' or 'undefined'. Just delete instead. - delete process.env.DEBUG; + try { + if (namespaces) { + exports.storage.setItem('debug', namespaces); + } else { + exports.storage.removeItem('debug'); + } + } catch (error) { + // Swallow + // XXX (@Qix-) should we be logging these? } } @@ -5278,24 +7327,42 @@ function save(namespaces) { * @return {String} returns the previously persisted debug modes * @api private */ - function load() { - return process.env.DEBUG; + let r; + try { + r = exports.storage.getItem('debug'); + } catch (error) { + // Swallow + // XXX (@Qix-) should we be logging these? + } + + // If debug isn't set in LS, and we're in Electron, try to load $DEBUG + if (!r && typeof process !== 'undefined' && 'env' in process) { + r = process.env.DEBUG; + } + + return r; } /** - * Init logic for `debug` instances. + * Localstorage attempts to return the localstorage. * - * Create a new `inspectOpts` object in case `useColors` is set - * differently for a particular `debug` instance. + * This is necessary because safari throws + * when a user disables cookies/localstorage + * and you attempt to access it. + * + * @return {LocalStorage} + * @api private */ -function init(debug) { - debug.inspectOpts = {}; - - const keys = Object.keys(exports.inspectOpts); - for (let i = 0; i < keys.length; i++) { - debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]]; +function localstorage() { + try { + // TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context + // The Browser also has localStorage in the global context. + return localStorage; + } catch (error) { + // Swallow + // XXX (@Qix-) should we be logging these? } } @@ -5304,976 +7371,1226 @@ module.exports = common$1(exports); const {formatters} = module.exports; /** - * Map %o to `util.inspect()`, all on a single line. - */ - -formatters.o = function (v) { - this.inspectOpts.colors = this.useColors; - return util$1.inspect(v, this.inspectOpts) - .replace(/\s*\n\s*/g, ' '); -}; - -/** - * Map %O to `util.inspect()`, allowing multiple lines if needed. - */ - -formatters.O = function (v) { - this.inspectOpts.colors = this.useColors; - return util$1.inspect(v, this.inspectOpts); -}; -}); -var node_1 = node.init; -var node_2 = node.log; -var node_3 = node.formatArgs; -var node_4 = node.save; -var node_5 = node.load; -var node_6 = node.useColors; -var node_7 = node.colors; -var node_8 = node.inspectOpts; - -var src = createCommonjsModule(function (module) { -/** - * Detect Electron renderer / nwjs process, which is node, but we should - * treat as a browser. + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. */ -if (typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs) { - module.exports = browser; -} else { - module.exports = node; -} -}); - -const resolveFrom = (fromDirectory, moduleId, silent) => { - if (typeof fromDirectory !== 'string') { - throw new TypeError(`Expected \`fromDir\` to be of type \`string\`, got \`${typeof fromDirectory}\``); - } - - if (typeof moduleId !== 'string') { - throw new TypeError(`Expected \`moduleId\` to be of type \`string\`, got \`${typeof moduleId}\``); - } - +formatters.j = function (v) { try { - fromDirectory = fs$1.realpathSync(fromDirectory); + return JSON.stringify(v); } catch (error) { - if (error.code === 'ENOENT') { - fromDirectory = path$1.resolve(fromDirectory); - } else if (silent) { - return; - } else { - throw error; - } - } - - const fromFile = path$1.join(fromDirectory, 'noop.js'); - - const resolveFileName = () => module$1._resolveFilename(moduleId, { - id: fromFile, - filename: fromFile, - paths: module$1._nodeModulePaths(fromDirectory) - }); - - if (silent) { - try { - return resolveFileName(); - } catch (error) { - return; - } + return '[UnexpectedJSONParseError]: ' + error.message; } - - return resolveFileName(); }; +}); +var browser_1 = browser.log; +var browser_2 = browser.formatArgs; +var browser_3 = browser.save; +var browser_4 = browser.load; +var browser_5 = browser.useColors; +var browser_6 = browser.storage; +var browser_7 = browser.colors; -var resolveFrom_1 = (fromDirectory, moduleId) => resolveFrom(fromDirectory, moduleId); -var silent = (fromDirectory, moduleId) => resolveFrom(fromDirectory, moduleId, true); -resolveFrom_1.silent = silent; - -var ini = createCommonjsModule(function (module, exports) { -exports.parse = exports.decode = decode; - -exports.stringify = exports.encode = encode; - -exports.safe = safe; -exports.unsafe = unsafe; - -var eol = typeof process !== 'undefined' && - process.platform === 'win32' ? '\r\n' : '\n'; - -function encode (obj, opt) { - var children = []; - var out = ''; - - if (typeof opt === 'string') { - opt = { - section: opt, - whitespace: false - }; - } else { - opt = opt || {}; - opt.whitespace = opt.whitespace === true; - } - - var separator = opt.whitespace ? ' = ' : '='; - - Object.keys(obj).forEach(function (k, _, __) { - var val = obj[k]; - if (val && Array.isArray(val)) { - val.forEach(function (item) { - out += safe(k + '[]') + separator + safe(item) + '\n'; - }); - } else if (val && typeof val === 'object') { - children.push(k); - } else { - out += safe(k) + separator + safe(val) + eol; - } - }); - - if (opt.section && out.length) { - out = '[' + safe(opt.section) + ']' + eol + out; - } +var hasFlag$1 = (flag, argv = process.argv) => { + const prefix = flag.startsWith('-') ? '' : (flag.length === 1 ? '-' : '--'); + const position = argv.indexOf(prefix + flag); + const terminatorPosition = argv.indexOf('--'); + return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition); +}; - children.forEach(function (k, _, __) { - var nk = dotSplit(k).join('\\.'); - var section = (opt.section ? opt.section + '.' : '') + nk; - var child = encode(obj[k], { - section: section, - whitespace: opt.whitespace - }); - if (out.length && child.length) { - out += eol; - } - out += child; - }); +const {env: env$1} = process; - return out +let forceColor$1; +if (hasFlag$1('no-color') || + hasFlag$1('no-colors') || + hasFlag$1('color=false') || + hasFlag$1('color=never')) { + forceColor$1 = 0; +} else if (hasFlag$1('color') || + hasFlag$1('colors') || + hasFlag$1('color=true') || + hasFlag$1('color=always')) { + forceColor$1 = 1; } -function dotSplit (str) { - return str.replace(/\1/g, '\u0002LITERAL\\1LITERAL\u0002') - .replace(/\\\./g, '\u0001') - .split(/\./).map(function (part) { - return part.replace(/\1/g, '\\.') - .replace(/\2LITERAL\\1LITERAL\2/g, '\u0001') - }) +if ('FORCE_COLOR' in env$1) { + if (env$1.FORCE_COLOR === 'true') { + forceColor$1 = 1; + } else if (env$1.FORCE_COLOR === 'false') { + forceColor$1 = 0; + } else { + forceColor$1 = env$1.FORCE_COLOR.length === 0 ? 1 : Math.min(parseInt(env$1.FORCE_COLOR, 10), 3); + } } -function decode (str) { - var out = {}; - var p = out; - var section = null; - // section |key = value - var re = /^\[([^\]]*)\]$|^([^=]+)(=(.*))?$/i; - var lines = str.split(/[\r\n]+/g); - - lines.forEach(function (line, _, __) { - if (!line || line.match(/^\s*[;#]/)) return - var match = line.match(re); - if (!match) return - if (match[1] !== undefined) { - section = unsafe(match[1]); - p = out[section] = out[section] || {}; - return - } - var key = unsafe(match[2]); - var value = match[3] ? unsafe(match[4]) : true; - switch (value) { - case 'true': - case 'false': - case 'null': value = JSON.parse(value); - } - - // Convert keys with '[]' suffix to an array - if (key.length > 2 && key.slice(-2) === '[]') { - key = key.substring(0, key.length - 2); - if (!p[key]) { - p[key] = []; - } else if (!Array.isArray(p[key])) { - p[key] = [p[key]]; - } - } - - // safeguard against resetting a previously defined - // array by accidentally forgetting the brackets - if (Array.isArray(p[key])) { - p[key].push(value); - } else { - p[key] = value; - } - }); - - // {a:{y:1},"a.b":{x:2}} --> {a:{y:1,b:{x:2}}} - // use a filter to return the keys that have to be deleted. - Object.keys(out).filter(function (k, _, __) { - if (!out[k] || - typeof out[k] !== 'object' || - Array.isArray(out[k])) { - return false - } - // see if the parent section is also an object. - // if so, add it to that, and mark this one for deletion - var parts = dotSplit(k); - var p = out; - var l = parts.pop(); - var nl = l.replace(/\\\./g, '.'); - parts.forEach(function (part, _, __) { - if (!p[part] || typeof p[part] !== 'object') p[part] = {}; - p = p[part]; - }); - if (p === out && nl === l) { - return false - } - p[nl] = out[k]; - return true - }).forEach(function (del, _, __) { - delete out[del]; - }); - - return out -} +function translateLevel$1(level) { + if (level === 0) { + return false; + } -function isQuoted (val) { - return (val.charAt(0) === '"' && val.slice(-1) === '"') || - (val.charAt(0) === "'" && val.slice(-1) === "'") + return { + level, + hasBasic: true, + has256: level >= 2, + has16m: level >= 3 + }; } -function safe (val) { - return (typeof val !== 'string' || - val.match(/[=\r\n]/) || - val.match(/^\[/) || - (val.length > 1 && - isQuoted(val)) || - val !== val.trim()) - ? JSON.stringify(val) - : val.replace(/;/g, '\\;').replace(/#/g, '\\#') -} +function supportsColor$1(haveStream, streamIsTTY) { + if (forceColor$1 === 0) { + return 0; + } -function unsafe (val, doUnesc) { - val = (val || '').trim(); - if (isQuoted(val)) { - // remove the single quotes before calling JSON.parse - if (val.charAt(0) === "'") { - val = val.substr(1, val.length - 2); - } - try { val = JSON.parse(val); } catch (_) {} - } else { - // walk the val to find the first not-escaped ; character - var esc = false; - var unesc = ''; - for (var i = 0, l = val.length; i < l; i++) { - var c = val.charAt(i); - if (esc) { - if ('\\;#'.indexOf(c) !== -1) { - unesc += c; - } else { - unesc += '\\' + c; - } - esc = false; - } else if (';#'.indexOf(c) !== -1) { - break - } else if (c === '\\') { - esc = true; - } else { - unesc += c; - } - } - if (esc) { - unesc += '\\'; - } - return unesc.trim() - } - return val -} -}); -var ini_1 = ini.parse; -var ini_2 = ini.decode; -var ini_3 = ini.stringify; -var ini_4 = ini.encode; -var ini_5 = ini.safe; -var ini_6 = ini.unsafe; + if (hasFlag$1('color=16m') || + hasFlag$1('color=full') || + hasFlag$1('color=truecolor')) { + return 3; + } -var singleComment = 1; -var multiComment = 2; + if (hasFlag$1('color=256')) { + return 2; + } -function stripWithoutWhitespace() { - return ''; -} + if (haveStream && !streamIsTTY && forceColor$1 === undefined) { + return 0; + } -function stripWithWhitespace(str, start, end) { - return str.slice(start, end).replace(/\S/g, ' '); -} + const min = forceColor$1 || 0; -var stripJsonComments = function (str, opts) { - opts = opts || {}; + if (env$1.TERM === 'dumb') { + return min; + } - var currentChar; - var nextChar; - var insideString = false; - var insideComment = false; - var offset = 0; - var ret = ''; - var strip = opts.whitespace === false ? stripWithoutWhitespace : stripWithWhitespace; + if (process.platform === 'win32') { + // Windows 10 build 10586 is the first Windows release that supports 256 colors. + // Windows 10 build 14931 is the first release that supports 16m/TrueColor. + const osRelease = os.release().split('.'); + if ( + Number(osRelease[0]) >= 10 && + Number(osRelease[2]) >= 10586 + ) { + return Number(osRelease[2]) >= 14931 ? 3 : 2; + } - for (var i = 0; i < str.length; i++) { - currentChar = str[i]; - nextChar = str[i + 1]; + return 1; + } - if (!insideComment && currentChar === '"') { - var escaped = str[i - 1] === '\\' && str[i - 2] !== '\\'; - if (!escaped) { - insideString = !insideString; - } + if ('CI' in env$1) { + if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI'].some(sign => sign in env$1) || env$1.CI_NAME === 'codeship') { + return 1; } - if (insideString) { - continue; - } + return min; + } - if (!insideComment && currentChar + nextChar === '//') { - ret += str.slice(offset, i); - offset = i; - insideComment = singleComment; - i++; - } else if (insideComment === singleComment && currentChar + nextChar === '\r\n') { - i++; - insideComment = false; - ret += strip(str, offset, i); - offset = i; - continue; - } else if (insideComment === singleComment && currentChar === '\n') { - insideComment = false; - ret += strip(str, offset, i); - offset = i; - } else if (!insideComment && currentChar + nextChar === '/*') { - ret += str.slice(offset, i); - offset = i; - insideComment = multiComment; - i++; - continue; - } else if (insideComment === multiComment && currentChar + nextChar === '*/') { - i++; - insideComment = false; - ret += strip(str, offset, i + 1); - offset = i + 1; - continue; - } + if ('TEAMCITY_VERSION' in env$1) { + return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env$1.TEAMCITY_VERSION) ? 1 : 0; } - return ret + (insideComment ? strip(str.substr(offset)) : str.substr(offset)); -}; + if ('GITHUB_ACTIONS' in env$1) { + return 1; + } -var utils = createCommonjsModule(function (module, exports) { + if (env$1.COLORTERM === 'truecolor') { + return 3; + } + if ('TERM_PROGRAM' in env$1) { + const version = parseInt((env$1.TERM_PROGRAM_VERSION || '').split('.')[0], 10); + switch (env$1.TERM_PROGRAM) { + case 'iTerm.app': + return version >= 3 ? 3 : 2; + case 'Apple_Terminal': + return 2; + // No default + } + } + if (/-256(color)?$/i.test(env$1.TERM)) { + return 2; + } + if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env$1.TERM)) { + return 1; + } -var parse = exports.parse = function (content) { + if ('COLORTERM' in env$1) { + return 1; + } - //if it ends in .json or starts with { then it must be json. - //must be done this way, because ini accepts everything. - //can't just try and parse it and let it throw if it's not ini. - //everything is ini. even json with a syntax error. + return min; +} - if(/^\s*{/.test(content)) - return JSON.parse(stripJsonComments(content)) - return ini.parse(content) +function getSupportLevel$1(stream) { + const level = supportsColor$1(stream, stream && stream.isTTY); + return translateLevel$1(level); +} +var supportsColor_1$1 = { + supportsColor: getSupportLevel$1, + stdout: translateLevel$1(supportsColor$1(true, tty.isatty(1))), + stderr: translateLevel$1(supportsColor$1(true, tty.isatty(2))) }; -var file = exports.file = function () { - var args = [].slice.call(arguments).filter(function (arg) { return arg != null }); - - //path.join breaks if it's a not a string, so just skip this. - for(var i in args) - if('string' !== typeof args[i]) - return +var node = createCommonjsModule(function (module, exports) { +/** + * Module dependencies. + */ - var file = path$1.join.apply(null, args); - try { - return fs$1.readFileSync(file,'utf-8') - } catch (err) { - return - } -}; -var json = exports.json = function () { - var content = file.apply(null, arguments); - return content ? parse(content) : null -}; -var env = exports.env = function (prefix, env) { - env = env || process.env; - var obj = {}; - var l = prefix.length; - for(var k in env) { - if(k.toLowerCase().indexOf(prefix.toLowerCase()) === 0) { - var keypath = k.substring(l).split('__'); +/** + * This is the Node.js implementation of `debug()`. + */ - // Trim empty strings from keypath array - var _emptyStringIndex; - while ((_emptyStringIndex=keypath.indexOf('')) > -1) { - keypath.splice(_emptyStringIndex, 1); - } +exports.init = init; +exports.log = log; +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; - var cursor = obj; - keypath.forEach(function _buildSubObj(_subkey,i){ +/** + * Colors. + */ - // (check for _subkey first so we ignore empty strings) - // (check for cursor to avoid assignment to primitive objects) - if (!_subkey || typeof cursor !== 'object') - return +exports.colors = [6, 2, 3, 4, 5, 1]; - // If this is the last key, just stuff the value in there - // Assigns actual value from env variable to final key - // (unless it's just an empty string- in that case use the last valid key) - if (i === keypath.length-1) - cursor[_subkey] = env[k]; +try { + // Optional dependency (as in, doesn't need to be installed, NOT like optionalDependencies in package.json) + // eslint-disable-next-line import/no-extraneous-dependencies + const supportsColor = supportsColor_1$1; + if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) { + exports.colors = [ + 20, + 21, + 26, + 27, + 32, + 33, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 56, + 57, + 62, + 63, + 68, + 69, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 92, + 93, + 98, + 99, + 112, + 113, + 128, + 129, + 134, + 135, + 148, + 149, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 178, + 179, + 184, + 185, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 209, + 214, + 215, + 220, + 221 + ]; + } +} catch (error) { + // Swallow - we only care if `supports-color` is available; it doesn't have to be. +} - // Build sub-object if nothing already exists at the keypath - if (cursor[_subkey] === undefined) - cursor[_subkey] = {}; +/** + * Build up the default `inspectOpts` object from the environment variables. + * + * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js + */ - // Increment cursor used to track the object at the current depth - cursor = cursor[_subkey]; +exports.inspectOpts = Object.keys(process.env).filter(key => { + return /^debug_/i.test(key); +}).reduce((obj, key) => { + // Camel-case + const prop = key + .substring(6) + .toLowerCase() + .replace(/_([a-z])/g, (_, k) => { + return k.toUpperCase(); + }); - }); + // Coerce string value into JS value + let val = process.env[key]; + if (/^(yes|on|true|enabled)$/i.test(val)) { + val = true; + } else if (/^(no|off|false|disabled)$/i.test(val)) { + val = false; + } else if (val === 'null') { + val = null; + } else { + val = Number(val); + } - } + obj[prop] = val; + return obj; +}, {}); - } +/** + * Is stdout a TTY? Colored output is enabled when `true`. + */ - return obj -}; +function useColors() { + return 'colors' in exports.inspectOpts ? + Boolean(exports.inspectOpts.colors) : + tty.isatty(process.stderr.fd); +} -var find = exports.find = function () { - var rel = path$1.join.apply(null, [].slice.call(arguments)); +/** + * Adds ANSI color escape codes if enabled. + * + * @api public + */ - function find(start, rel) { - var file = path$1.join(start, rel); - try { - fs$1.statSync(file); - return file - } catch (err) { - if(path$1.dirname(start) !== start) // root - return find(path$1.dirname(start), rel) - } - } - return find(process.cwd(), rel) -}; -}); -var utils_1 = utils.parse; -var utils_2 = utils.file; -var utils_3 = utils.json; -var utils_4 = utils.env; -var utils_5 = utils.find; +function formatArgs(args) { + const {namespace: name, useColors} = this; -var deepExtend_1 = createCommonjsModule(function (module) { + if (useColors) { + const c = this.color; + const colorCode = '\u001B[3' + (c < 8 ? c : '8;5;' + c); + const prefix = ` ${colorCode};1m${name} \u001B[0m`; -function isSpecificValue(val) { - return ( - val instanceof Buffer - || val instanceof Date - || val instanceof RegExp - ) ? true : false; -} - -function cloneSpecificValue(val) { - if (val instanceof Buffer) { - var x = Buffer.alloc - ? Buffer.alloc(val.length) - : new Buffer(val.length); - val.copy(x); - return x; - } else if (val instanceof Date) { - return new Date(val.getTime()); - } else if (val instanceof RegExp) { - return new RegExp(val); + args[0] = prefix + args[0].split('\n').join('\n' + prefix); + args.push(colorCode + 'm+' + module.exports.humanize(this.diff) + '\u001B[0m'); } else { - throw new Error('Unexpected situation'); + args[0] = getDate() + name + ' ' + args[0]; + } +} + +function getDate() { + if (exports.inspectOpts.hideDate) { + return ''; } + return new Date().toISOString() + ' '; } /** - * Recursive cloning array. + * Invokes `util.format()` with the specified arguments and writes to stderr. */ -function deepCloneArray(arr) { - var clone = []; - arr.forEach(function (item, index) { - if (typeof item === 'object' && item !== null) { - if (Array.isArray(item)) { - clone[index] = deepCloneArray(item); - } else if (isSpecificValue(item)) { - clone[index] = cloneSpecificValue(item); - } else { - clone[index] = deepExtend({}, item); - } - } else { - clone[index] = item; - } - }); - return clone; -} -function safeGetProperty(object, property) { - return property === '__proto__' ? undefined : object[property]; +function log(...args) { + return process.stderr.write(util$2.format(...args) + '\n'); } /** - * Extening object that entered in first argument. - * - * Returns extended object or false if have no target object or incorrect type. + * Save `namespaces`. * - * If you wish to clone source object (without modify it), just use empty new - * object as first argument, like this: - * deepExtend({}, yourObj_1, [yourObj_N]); + * @param {String} namespaces + * @api private */ -var deepExtend = module.exports = function (/*obj_1, [obj_2], [obj_N]*/) { - if (arguments.length < 1 || typeof arguments[0] !== 'object') { - return false; - } - - if (arguments.length < 2) { - return arguments[0]; +function save(namespaces) { + if (namespaces) { + process.env.DEBUG = namespaces; + } else { + // If you set a process.env field to null or undefined, it gets cast to the + // string 'null' or 'undefined'. Just delete instead. + delete process.env.DEBUG; } +} - var target = arguments[0]; - - // convert arguments to array and cut off target object - var args = Array.prototype.slice.call(arguments, 1); +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ - var val, src; +function load() { + return process.env.DEBUG; +} - args.forEach(function (obj) { - // skip argument if isn't an object, is null, or is an array - if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) { - return; - } +/** + * Init logic for `debug` instances. + * + * Create a new `inspectOpts` object in case `useColors` is set + * differently for a particular `debug` instance. + */ - Object.keys(obj).forEach(function (key) { - src = safeGetProperty(target, key); // source value - val = safeGetProperty(obj, key); // new value +function init(debug) { + debug.inspectOpts = {}; - // recursion prevention - if (val === target) { - return; + const keys = Object.keys(exports.inspectOpts); + for (let i = 0; i < keys.length; i++) { + debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]]; + } +} - /** - * if new value isn't object then just overwrite by new value - * instead of extending. - */ - } else if (typeof val !== 'object' || val === null) { - target[key] = val; - return; +module.exports = common$1(exports); - // just clone arrays (and recursive clone objects inside) - } else if (Array.isArray(val)) { - target[key] = deepCloneArray(val); - return; +const {formatters} = module.exports; - // custom cloning and overwrite for specific objects - } else if (isSpecificValue(val)) { - target[key] = cloneSpecificValue(val); - return; +/** + * Map %o to `util.inspect()`, all on a single line. + */ - // overwrite by new value if source isn't object or array - } else if (typeof src !== 'object' || src === null || Array.isArray(src)) { - target[key] = deepExtend({}, val); - return; +formatters.o = function (v) { + this.inspectOpts.colors = this.useColors; + return util$2.inspect(v, this.inspectOpts) + .replace(/\s*\n\s*/g, ' '); +}; - // source value and new value is objects both, extending... - } else { - target[key] = deepExtend(src, val); - return; - } - }); - }); +/** + * Map %O to `util.inspect()`, allowing multiple lines if needed. + */ - return target; +formatters.O = function (v) { + this.inspectOpts.colors = this.useColors; + return util$2.inspect(v, this.inspectOpts); }; }); +var node_1 = node.init; +var node_2 = node.log; +var node_3 = node.formatArgs; +var node_4 = node.save; +var node_5 = node.load; +var node_6 = node.useColors; +var node_7 = node.colors; +var node_8 = node.inspectOpts; -var minimist = function (args, opts) { - if (!opts) opts = {}; - - var flags = { bools : {}, strings : {}, unknownFn: null }; +var src = createCommonjsModule(function (module) { +/** + * Detect Electron renderer / nwjs process, which is node, but we should + * treat as a browser. + */ - if (typeof opts['unknown'] === 'function') { - flags.unknownFn = opts['unknown']; - } +if (typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs) { + module.exports = browser; +} else { + module.exports = node; +} +}); - if (typeof opts['boolean'] === 'boolean' && opts['boolean']) { - flags.allBools = true; - } else { - [].concat(opts['boolean']).filter(Boolean).forEach(function (key) { - flags.bools[key] = true; - }); - } - - var aliases = {}; - Object.keys(opts.alias || {}).forEach(function (key) { - aliases[key] = [].concat(opts.alias[key]); - aliases[key].forEach(function (x) { - aliases[x] = [key].concat(aliases[key].filter(function (y) { - return x !== y; - })); - }); - }); +const resolveFrom = (fromDirectory, moduleId, silent) => { + if (typeof fromDirectory !== 'string') { + throw new TypeError(`Expected \`fromDir\` to be of type \`string\`, got \`${typeof fromDirectory}\``); + } - [].concat(opts.string).filter(Boolean).forEach(function (key) { - flags.strings[key] = true; - if (aliases[key]) { - flags.strings[aliases[key]] = true; - } - }); + if (typeof moduleId !== 'string') { + throw new TypeError(`Expected \`moduleId\` to be of type \`string\`, got \`${typeof moduleId}\``); + } - var defaults = opts['default'] || {}; - - var argv = { _ : [] }; - Object.keys(flags.bools).forEach(function (key) { - setArg(key, defaults[key] === undefined ? false : defaults[key]); - }); - - var notFlags = []; + try { + fromDirectory = fs$1.realpathSync(fromDirectory); + } catch (error) { + if (error.code === 'ENOENT') { + fromDirectory = path$1.resolve(fromDirectory); + } else if (silent) { + return; + } else { + throw error; + } + } - if (args.indexOf('--') !== -1) { - notFlags = args.slice(args.indexOf('--')+1); - args = args.slice(0, args.indexOf('--')); - } + const fromFile = path$1.join(fromDirectory, 'noop.js'); - function argDefined(key, arg) { - return (flags.allBools && /^--[^=]+$/.test(arg)) || - flags.strings[key] || flags.bools[key] || aliases[key]; - } + const resolveFileName = () => module$1._resolveFilename(moduleId, { + id: fromFile, + filename: fromFile, + paths: module$1._nodeModulePaths(fromDirectory) + }); - function setArg (key, val, arg) { - if (arg && flags.unknownFn && !argDefined(key, arg)) { - if (flags.unknownFn(arg) === false) return; - } + if (silent) { + try { + return resolveFileName(); + } catch (error) { + return; + } + } - var value = !flags.strings[key] && isNumber(val) - ? Number(val) : val - ; - setKey(argv, key.split('.'), value); - - (aliases[key] || []).forEach(function (x) { - setKey(argv, x.split('.'), value); - }); - } + return resolveFileName(); +}; - function setKey (obj, keys, value) { - var o = obj; - for (var i = 0; i < keys.length-1; i++) { - var key = keys[i]; - if (key === '__proto__') return; - if (o[key] === undefined) o[key] = {}; - if (o[key] === Object.prototype || o[key] === Number.prototype - || o[key] === String.prototype) o[key] = {}; - if (o[key] === Array.prototype) o[key] = []; - o = o[key]; - } +var resolveFrom_1 = (fromDirectory, moduleId) => resolveFrom(fromDirectory, moduleId); +var silent = (fromDirectory, moduleId) => resolveFrom(fromDirectory, moduleId, true); +resolveFrom_1.silent = silent; - var key = keys[keys.length - 1]; - if (key === '__proto__') return; - if (o === Object.prototype || o === Number.prototype - || o === String.prototype) o = {}; - if (o === Array.prototype) o = []; - if (o[key] === undefined || flags.bools[key] || typeof o[key] === 'boolean') { - o[key] = value; - } - else if (Array.isArray(o[key])) { - o[key].push(value); - } - else { - o[key] = [ o[key], value ]; +class FiggyPudding { + constructor (specs, opts, providers) { + this.__specs = specs || {}; + Object.keys(this.__specs).forEach(alias => { + if (typeof this.__specs[alias] === 'string') { + const key = this.__specs[alias]; + const realSpec = this.__specs[key]; + if (realSpec) { + const aliasArr = realSpec.aliases || []; + aliasArr.push(alias, key); + realSpec.aliases = [...(new Set(aliasArr))]; + this.__specs[alias] = realSpec; + } else { + throw new Error(`Alias refers to invalid key: ${key} -> ${alias}`) } + } + }); + this.__opts = opts || {}; + this.__providers = reverse((providers).filter( + x => x != null && typeof x === 'object' + )); + this.__isFiggyPudding = true; + } + get (key) { + return pudGet(this, key, true) + } + get [Symbol.toStringTag] () { return 'FiggyPudding' } + forEach (fn, thisArg = this) { + for (let [key, value] of this.entries()) { + fn.call(thisArg, value, key, this); } - - function aliasIsBoolean(key) { - return aliases[key].some(function (x) { - return flags.bools[x]; - }); - } - - for (var i = 0; i < args.length; i++) { - var arg = args[i]; - - if (/^--.+=/.test(arg)) { - // Using [\s\S] instead of . because js doesn't support the - // 'dotall' regex modifier. See: - // http://stackoverflow.com/a/1068308/13216 - var m = arg.match(/^--([^=]+)=([\s\S]*)$/); - var key = m[1]; - var value = m[2]; - if (flags.bools[key]) { - value = value !== 'false'; - } - setArg(key, value, arg); - } - else if (/^--no-.+/.test(arg)) { - var key = arg.match(/^--no-(.+)/)[1]; - setArg(key, false, arg); - } - else if (/^--.+/.test(arg)) { - var key = arg.match(/^--(.+)/)[1]; - var next = args[i + 1]; - if (next !== undefined && !/^-/.test(next) - && !flags.bools[key] - && !flags.allBools - && (aliases[key] ? !aliasIsBoolean(key) : true)) { - setArg(key, next, arg); - i++; - } - else if (/^(true|false)$/.test(next)) { - setArg(key, next === 'true', arg); - i++; - } - else { - setArg(key, flags.strings[key] ? '' : true, arg); - } - } - else if (/^-[^-]+/.test(arg)) { - var letters = arg.slice(1,-1).split(''); - - var broken = false; - for (var j = 0; j < letters.length; j++) { - var next = arg.slice(j+2); - - if (next === '-') { - setArg(letters[j], next, arg); - continue; - } - - if (/[A-Za-z]/.test(letters[j]) && /=/.test(next)) { - setArg(letters[j], next.split('=')[1], arg); - broken = true; - break; - } - - if (/[A-Za-z]/.test(letters[j]) - && /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) { - setArg(letters[j], next, arg); - broken = true; - break; - } - - if (letters[j+1] && letters[j+1].match(/\W/)) { - setArg(letters[j], arg.slice(j+2), arg); - broken = true; - break; - } - else { - setArg(letters[j], flags.strings[letters[j]] ? '' : true, arg); - } - } - - var key = arg.slice(-1)[0]; - if (!broken && key !== '-') { - if (args[i+1] && !/^(-|--)[^-]/.test(args[i+1]) - && !flags.bools[key] - && (aliases[key] ? !aliasIsBoolean(key) : true)) { - setArg(key, args[i+1], arg); - i++; - } - else if (args[i+1] && /^(true|false)$/.test(args[i+1])) { - setArg(key, args[i+1] === 'true', arg); - i++; - } - else { - setArg(key, flags.strings[key] ? '' : true, arg); - } - } - } - else { - if (!flags.unknownFn || flags.unknownFn(arg) !== false) { - argv._.push( - flags.strings['_'] || !isNumber(arg) ? arg : Number(arg) - ); - } - if (opts.stopEarly) { - argv._.push.apply(argv._, args.slice(i + 1)); - break; - } + } + toJSON () { + const obj = {}; + this.forEach((val, key) => { + obj[key] = val; + }); + return obj + } + * entries (_matcher) { + for (let key of Object.keys(this.__specs)) { + yield [key, this.get(key)]; + } + const matcher = _matcher || this.__opts.other; + if (matcher) { + const seen = new Set(); + for (let p of this.__providers) { + const iter = p.entries ? p.entries(matcher) : entries(p); + for (let [key, val] of iter) { + if (matcher(key) && !seen.has(key)) { + seen.add(key); + yield [key, val]; + } } + } } - - Object.keys(defaults).forEach(function (key) { - if (!hasKey(argv, key.split('.'))) { - setKey(argv, key.split('.'), defaults[key]); - - (aliases[key] || []).forEach(function (x) { - setKey(argv, x.split('.'), defaults[key]); - }); + } + * [Symbol.iterator] () { + for (let [key, value] of this.entries()) { + yield [key, value]; + } + } + * keys () { + for (let [key] of this.entries()) { + yield key; + } + } + * values () { + for (let [, value] of this.entries()) { + yield value; + } + } + concat (...moreConfig) { + return new Proxy(new FiggyPudding( + this.__specs, + this.__opts, + reverse(this.__providers).concat(moreConfig) + ), proxyHandler) + } +} +try { + const util = util$2; + FiggyPudding.prototype[util.inspect.custom] = function (depth, opts) { + return ( + this[Symbol.toStringTag] + ' ' + ) + util.inspect(this.toJSON(), opts) + }; +} catch (e) {} + +function BadKeyError (key) { + throw Object.assign(new Error( + `invalid config key requested: ${key}` + ), {code: 'EBADKEY'}) +} + +function pudGet (pud, key, validate) { + let spec = pud.__specs[key]; + if (validate && !spec && (!pud.__opts.other || !pud.__opts.other(key))) { + BadKeyError(key); + } else { + if (!spec) { spec = {}; } + let ret; + for (let p of pud.__providers) { + ret = tryGet(key, p); + if (ret === undefined && spec.aliases && spec.aliases.length) { + for (let alias of spec.aliases) { + if (alias === key) { continue } + ret = tryGet(alias, p); + if (ret !== undefined) { + break + } } - }); - - if (opts['--']) { - argv['--'] = new Array(); - notFlags.forEach(function(key) { - argv['--'].push(key); - }); + } + if (ret !== undefined) { + break + } } - else { - notFlags.forEach(function(key) { - argv._.push(key); - }); + if (ret === undefined && spec.default !== undefined) { + if (typeof spec.default === 'function') { + return spec.default(pud) + } else { + return spec.default + } + } else { + return ret } + } +} - return argv; -}; +function tryGet (key, p) { + let ret; + if (p.__isFiggyPudding) { + ret = pudGet(p, key, false); + } else if (typeof p.get === 'function') { + ret = p.get(key); + } else { + ret = p[key]; + } + return ret +} -function hasKey (obj, keys) { - var o = obj; - keys.slice(0,-1).forEach(function (key) { - o = (o[key] || {}); - }); +const proxyHandler = { + has (obj, prop) { + return prop in obj.__specs && pudGet(obj, prop, false) !== undefined + }, + ownKeys (obj) { + return Object.keys(obj.__specs) + }, + get (obj, prop) { + if ( + typeof prop === 'symbol' || + prop.slice(0, 2) === '__' || + prop in FiggyPudding.prototype + ) { + return obj[prop] + } + return obj.get(prop) + }, + set (obj, prop, value) { + if ( + typeof prop === 'symbol' || + prop.slice(0, 2) === '__' + ) { + obj[prop] = value; + return true + } else { + throw new Error('figgyPudding options cannot be modified. Use .concat() instead.') + } + }, + deleteProperty () { + throw new Error('figgyPudding options cannot be deleted. Use .concat() and shadow them instead.') + } +}; - var key = keys[keys.length - 1]; - return key in o; +var figgyPudding_1 = figgyPudding; +function figgyPudding (specs, opts) { + function factory (...providers) { + return new Proxy(new FiggyPudding( + specs, + opts, + providers + ), proxyHandler) + } + return factory } -function isNumber (x) { - if (typeof x === 'number') return true; - if (/^0x[0-9a-f]+$/i.test(x)) return true; - return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x); +function reverse (arr) { + const ret = []; + arr.forEach(x => ret.unshift(x)); + return ret } -var join = path$1.join; +function entries (obj) { + return Object.keys(obj).map(k => [k, obj[k]]) +} -var etc = '/etc'; -var win = process.platform === "win32"; -var home = win - ? process.env.USERPROFILE - : process.env.HOME; - -var rc = function (name, defaults, argv, parse) { - if('string' !== typeof name) - throw new Error('rc(name): name *must* be string') - if(!argv) - argv = minimist(process.argv.slice(2)); - defaults = ( - 'string' === typeof defaults - ? utils.json(defaults) : defaults - ) || {}; - - parse = parse || utils.parse; - - var env = utils.env(name + '_'); - - var configs = [defaults]; - var configFiles = []; - function addConfigFile (file) { - if (configFiles.indexOf(file) >= 0) return - var fileConfig = utils.file(file); - if (fileConfig) { - configs.push(parse(fileConfig)); - configFiles.push(file); - } - } - - // which files do we look at? - if (!win) - [join(etc, name, 'config'), - join(etc, name + 'rc')].forEach(addConfigFile); - if (home) - [join(home, '.config', name, 'config'), - join(home, '.config', name), - join(home, '.' + name, 'config'), - join(home, '.' + name + 'rc')].forEach(addConfigFile); - addConfigFile(utils.find('.'+name+'rc')); - if (env.config) addConfigFile(env.config); - if (argv.config) addConfigFile(argv.config); - - return deepExtend_1.apply(null, configs.concat([ - env, - argv, - configFiles.length ? {configs: configFiles, config: configFiles[configFiles.length - 1]} : undefined, - ])) -}; - -function homedir() { - var env = process.env; - var home = env.HOME; - var user = env.LOGNAME || env.USER || env.LNAME || env.USERNAME; +var pathExists = fp => new Promise(resolve => { + fs$1.access(fp, err => { + resolve(!err); + }); +}); - if (process.platform === 'win32') { - return env.USERPROFILE || env.HOMEDRIVE + env.HOMEPATH || home || null; +var sync = fp => { + try { + fs$1.accessSync(fp); + return true; + } catch (err) { + return false; } +}; +pathExists.sync = sync; - if (process.platform === 'darwin') { - return home || (user ? '/Users/' + user : null); - } +const pTry = (fn, ...arguments_) => new Promise(resolve => { + resolve(fn(...arguments_)); +}); + +var pTry_1 = pTry; +// TODO: remove this in the next major version +var default_1 = pTry; +pTry_1.default = default_1; - if (process.platform === 'linux') { - return home || (process.getuid() === 0 ? '/root' : (user ? '/home/' + user : null)); +const pLimit = concurrency => { + if (!((Number.isInteger(concurrency) || concurrency === Infinity) && concurrency > 0)) { + return Promise.reject(new TypeError('Expected `concurrency` to be a number from 1 and up')); } - return home || null; + const queue = []; + let activeCount = 0; + + const next = () => { + activeCount--; + + if (queue.length > 0) { + queue.shift()(); + } + }; + + const run = (fn, resolve, ...args) => { + activeCount++; + + const result = pTry_1(fn, ...args); + + resolve(result); + + result.then(next, next); + }; + + const enqueue = (fn, resolve, ...args) => { + if (activeCount < concurrency) { + run(fn, resolve, ...args); + } else { + queue.push(run.bind(null, fn, resolve, ...args)); + } + }; + + const generator = (fn, ...args) => new Promise(resolve => enqueue(fn, resolve, ...args)); + Object.defineProperties(generator, { + activeCount: { + get: () => activeCount + }, + pendingCount: { + get: () => queue.length + }, + clearQueue: { + value: () => { + queue.length = 0; + } + } + }); + + return generator; +}; + +var pLimit_1 = pLimit; +var default_1$1 = pLimit; +pLimit_1.default = default_1$1; + +class EndError extends Error { + constructor(value) { + super(); + this.value = value; + } } -var osHomedir = typeof os.homedir === 'function' ? os.homedir : homedir; +// The input can also be a promise, so we `Promise.resolve()` it +const testElement = (el, tester) => Promise.resolve(el).then(tester); -var home$1 = osHomedir(); +// The input can also be a promise, so we `Promise.all()` them both +const finder = el => Promise.all(el).then(val => val[1] === true && Promise.reject(new EndError(val[0]))); -var untildify = function (str) { - if (typeof str !== 'string') { - throw new TypeError('Expected a string'); +var pLocate = (iterable, tester, opts) => { + opts = Object.assign({ + concurrency: Infinity, + preserveOrder: true + }, opts); + + const limit = pLimit_1(opts.concurrency); + + // Start all the promises concurrently with optional limit + const items = [...iterable].map(el => [el, limit(testElement, el, tester)]); + + // Check the promises either serially or concurrently + const checkLimit = pLimit_1(opts.preserveOrder ? 1 : Infinity); + + return Promise.all(items.map(el => checkLimit(finder, el))) + .then(() => {}) + .catch(err => err instanceof EndError ? err.value : Promise.reject(err)); +}; + +var locatePath = (iterable, options) => { + options = Object.assign({ + cwd: process.cwd() + }, options); + + return pLocate(iterable, el => pathExists(path$1.resolve(options.cwd, el)), options); +}; + +var sync$1 = (iterable, options) => { + options = Object.assign({ + cwd: process.cwd() + }, options); + + for (const el of iterable) { + if (pathExists.sync(path$1.resolve(options.cwd, el))) { + return el; + } } +}; +locatePath.sync = sync$1; + +var findUp = (filename, opts = {}) => { + const startDir = path$1.resolve(opts.cwd || ''); + const {root} = path$1.parse(startDir); + + const filenames = [].concat(filename); + + return new Promise(resolve => { + (function find(dir) { + locatePath(filenames, {cwd: dir}).then(file => { + if (file) { + resolve(path$1.join(dir, file)); + } else if (dir === root) { + resolve(null); + } else { + find(path$1.dirname(dir)); + } + }); + })(startDir); + }); +}; + +var sync$2 = (filename, opts = {}) => { + let dir = path$1.resolve(opts.cwd || ''); + const {root} = path$1.parse(dir); + + const filenames = [].concat(filename); + + // eslint-disable-next-line no-constant-condition + while (true) { + const file = locatePath.sync(filenames, {cwd: dir}); - return home$1 ? str.replace(/^~($|\/|\\)/, home$1 + '$1') : str; + if (file) { + return path$1.join(dir, file); + } + + if (dir === root) { + return null; + } + + dir = path$1.dirname(dir); + } }; +findUp.sync = sync$2; + +var ini = createCommonjsModule(function (module, exports) { +exports.parse = exports.decode = decode; + +exports.stringify = exports.encode = encode; + +exports.safe = safe; +exports.unsafe = unsafe; + +var eol = typeof process !== 'undefined' && + process.platform === 'win32' ? '\r\n' : '\n'; + +function encode (obj, opt) { + var children = []; + var out = ''; + + if (typeof opt === 'string') { + opt = { + section: opt, + whitespace: false + }; + } else { + opt = opt || {}; + opt.whitespace = opt.whitespace === true; + } + + var separator = opt.whitespace ? ' = ' : '='; -var shellsubstitute = function (s, vars) { - return s.replace(/(\\*)(\$([_a-z0-9]+)|\${([_a-z0-9]+)})/ig, function (_, escape, varExpression, variable, bracedVariable) { - if (!(escape.length % 2)) { - return escape.substring(Math.ceil(escape.length / 2)) + (vars[variable || bracedVariable] || ''); + Object.keys(obj).forEach(function (k, _, __) { + var val = obj[k]; + if (val && Array.isArray(val)) { + val.forEach(function (item) { + out += safe(k + '[]') + separator + safe(item) + '\n'; + }); + } else if (val && typeof val === 'object') { + children.push(k); } else { - return escape.substring(1) + varExpression; + out += safe(k) + separator + safe(val) + eol; } }); -}; -var npmPrefix = function () { - var rcPrefix = rc('npm', null, []).prefix; + if (opt.section && out.length) { + out = '[' + safe(opt.section) + ']' + eol + out; + } + + children.forEach(function (k, _, __) { + var nk = dotSplit(k).join('\\.'); + var section = (opt.section ? opt.section + '.' : '') + nk; + var child = encode(obj[k], { + section: section, + whitespace: opt.whitespace + }); + if (out.length && child.length) { + out += eol; + } + out += child; + }); + + return out +} + +function dotSplit (str) { + return str.replace(/\1/g, '\u0002LITERAL\\1LITERAL\u0002') + .replace(/\\\./g, '\u0001') + .split(/\./).map(function (part) { + return part.replace(/\1/g, '\\.') + .replace(/\2LITERAL\\1LITERAL\2/g, '\u0001') + }) +} + +function decode (str) { + var out = {}; + var p = out; + var section = null; + // section |key = value + var re = /^\[([^\]]*)\]$|^([^=]+)(=(.*))?$/i; + var lines = str.split(/[\r\n]+/g); + + lines.forEach(function (line, _, __) { + if (!line || line.match(/^\s*[;#]/)) return + var match = line.match(re); + if (!match) return + if (match[1] !== undefined) { + section = unsafe(match[1]); + p = out[section] = out[section] || {}; + return + } + var key = unsafe(match[2]); + var value = match[3] ? unsafe(match[4]) : true; + switch (value) { + case 'true': + case 'false': + case 'null': value = JSON.parse(value); + } + + // Convert keys with '[]' suffix to an array + if (key.length > 2 && key.slice(-2) === '[]') { + key = key.substring(0, key.length - 2); + if (!p[key]) { + p[key] = []; + } else if (!Array.isArray(p[key])) { + p[key] = [p[key]]; + } + } + + // safeguard against resetting a previously defined + // array by accidentally forgetting the brackets + if (Array.isArray(p[key])) { + p[key].push(value); + } else { + p[key] = value; + } + }); + + // {a:{y:1},"a.b":{x:2}} --> {a:{y:1,b:{x:2}}} + // use a filter to return the keys that have to be deleted. + Object.keys(out).filter(function (k, _, __) { + if (!out[k] || + typeof out[k] !== 'object' || + Array.isArray(out[k])) { + return false + } + // see if the parent section is also an object. + // if so, add it to that, and mark this one for deletion + var parts = dotSplit(k); + var p = out; + var l = parts.pop(); + var nl = l.replace(/\\\./g, '.'); + parts.forEach(function (part, _, __) { + if (!p[part] || typeof p[part] !== 'object') p[part] = {}; + p = p[part]; + }); + if (p === out && nl === l) { + return false + } + p[nl] = out[k]; + return true + }).forEach(function (del, _, __) { + delete out[del]; + }); + + return out +} + +function isQuoted (val) { + return (val.charAt(0) === '"' && val.slice(-1) === '"') || + (val.charAt(0) === "'" && val.slice(-1) === "'") +} + +function safe (val) { + return (typeof val !== 'string' || + val.match(/[=\r\n]/) || + val.match(/^\[/) || + (val.length > 1 && + isQuoted(val)) || + val !== val.trim()) + ? JSON.stringify(val) + : val.replace(/;/g, '\\;').replace(/#/g, '\\#') +} + +function unsafe (val, doUnesc) { + val = (val || '').trim(); + if (isQuoted(val)) { + // remove the single quotes before calling JSON.parse + if (val.charAt(0) === "'") { + val = val.substr(1, val.length - 2); + } + try { val = JSON.parse(val); } catch (_) {} + } else { + // walk the val to find the first not-escaped ; character + var esc = false; + var unesc = ''; + for (var i = 0, l = val.length; i < l; i++) { + var c = val.charAt(i); + if (esc) { + if ('\\;#'.indexOf(c) !== -1) { + unesc += c; + } else { + unesc += '\\' + c; + } + esc = false; + } else if (';#'.indexOf(c) !== -1) { + break + } else if (c === '\\') { + esc = true; + } else { + unesc += c; + } + } + if (esc) { + unesc += '\\'; + } + return unesc.trim() + } + return val +} +}); +var ini_1 = ini.parse; +var ini_2 = ini.decode; +var ini_3 = ini.stringify; +var ini_4 = ini.encode; +var ini_5 = ini.safe; +var ini_6 = ini.unsafe; + +const NpmConfig = figgyPudding_1({}, { + // Open up the pudding object. + other () { return true } +}); + +const ConfigOpts = figgyPudding_1({ + cache: { default: path$1.join(os.homedir(), '.npm') }, + configNames: { default: ['npmrc', '.npmrc'] }, + envPrefix: { default: /^npm_config_/i }, + cwd: { default: () => process.cwd() }, + globalconfig: { + default: () => path$1.join(getGlobalPrefix(), 'etc', 'npmrc') + }, + userconfig: { default: path$1.join(os.homedir(), '.npmrc') } +}); - if (rcPrefix) { - return untildify(shellsubstitute(rcPrefix, process.env)); +var read = getNpmConfig; +function getNpmConfig (_opts, _builtin) { + const builtin = ConfigOpts(_builtin); + const env = {}; + for (let key of Object.keys(process.env)) { + if (!key.match(builtin.envPrefix)) continue + const newKey = key.toLowerCase() + .replace(builtin.envPrefix, '') + .replace(/(?!^)_/g, '-'); + env[newKey] = process.env[key]; + } + const cli = NpmConfig(_opts); + const userConfPath = ( + builtin.userconfig || + cli.userconfig || + env.userconfig + ); + const user = userConfPath && maybeReadIni(userConfPath); + const globalConfPath = ( + builtin.globalconfig || + cli.globalconfig || + env.globalconfig + ); + const global = globalConfPath && maybeReadIni(globalConfPath); + const projConfPath = findUp.sync(builtin.configNames, { cwd: builtin.cwd }); + let proj = {}; + if (projConfPath && projConfPath !== userConfPath) { + proj = maybeReadIni(projConfPath); + } + const newOpts = NpmConfig(builtin, global, user, proj, env, cli); + if (newOpts.cache) { + return newOpts.concat({ + cache: path$1.resolve( + ( + (cli.cache || env.cache) + ? builtin.cwd + : proj.cache + ? path$1.dirname(projConfPath) + : user.cache + ? path$1.dirname(userConfPath) + : global.cache + ? path$1.dirname(globalConfPath) + : path$1.dirname(userConfPath) + ), + newOpts.cache + ) + }) + } else { + return newOpts } - else if (process.platform == 'win32') { - return path$1.dirname(process.execPath); +} + +function maybeReadIni (f) { + let txt; + try { + txt = fs$1.readFileSync(f, 'utf8'); + } catch (err) { + if (err.code === 'ENOENT') { + return '' + } else { + throw err + } } - else { - return path$1.resolve(process.execPath, '../..'); + return ini.parse(txt) +} + +function getGlobalPrefix () { + if (process.env.PREFIX) { + return process.env.PREFIX + } else if (process.platform === 'win32') { + // c:\node\node.exe --> prefix=c:\node\ + return path$1.dirname(process.execPath) + } else { + // /usr/local/bin/node --> prefix=/usr/local + let pref = path$1.dirname(path$1.dirname(process.execPath)); + // destdir only is respected on Unix + if (process.env.DESTDIR) { + pref = path$1.join(process.env.DESTDIR, pref); + } + return pref } +} + +var libnpmconfig = { + read: read }; var resolve = resolveFrom_1.silent; -var npmPrefix$1 = npmPrefix(); +var readNpmConfig = libnpmconfig.read; var loadPlugin_1 = loadPlugin; loadPlugin.resolve = resolvePlugin; var electron = process.versions.electron !== undefined; +var windows = process.platform === 'win32'; + var argv = process.argv[1] || /* istanbul ignore next */ ''; var nvm = process.env.NVM_BIN; -var globally = electron || argv.indexOf(npmPrefix$1) === 0; -var windows = process.platform === 'win32'; -var prefix = windows ? /* istanbul ignore next */ '' : 'lib'; -var globals = path$1.resolve(npmPrefix$1, prefix, 'node_modules'); +var appData = process.env.APPDATA; + +/* istanbul ignore next */ +var globalsLibrary = windows ? '' : 'lib'; + +var builtinNpmConfig; + +// The prefix config defaults to the location where node is installed. +// On Windows, this is in a place called `%AppData%`, which we have to +// pass to `libnpmconfig` explicitly: +/* istanbul ignore next */ +if (windows && appData) { + builtinNpmConfig = {prefix: path$1.join(appData, 'npm')}; +} + +var npmPrefix = readNpmConfig(null, builtinNpmConfig).prefix; + +// If there is no prefix defined, use the defaults +// See: +/* istanbul ignore next */ +if (!npmPrefix) { + npmPrefix = windows + ? path$1.dirname(process.execPath) + : path$1.resolve(process.execPath, '../..'); +} + +var globally = electron || argv.indexOf(npmPrefix) === 0; +var globals = path$1.resolve(npmPrefix, globalsLibrary, 'node_modules'); // If we’re in Electron, we’re running in a modified Node that cannot really -// install global node modules. To find the actual modules, the user has to -// either set `prefix` in their `.npmrc` (which is picked up by `npm-prefix`). +// install global node modules. +// To find the actual modules, the user has to set `prefix` somewhere in an +// `.npmrc` (which is picked up by `libnpmconfig`). // Most people don’t do that, and some use NVM instead to manage different -// versions of Node. Luckily NVM leaks some environment variables that we can -// pick up on to try and detect the actual modules. +// versions of Node. +// Luckily NVM leaks some environment variables that we can pick up on to try +// and detect the actual modules. /* istanbul ignore next */ if (electron && nvm && !fs$1.existsSync(globals)) { - globals = path$1.resolve(nvm, '..', prefix, 'node_modules'); + globals = path$1.resolve(nvm, '..', globalsLibrary, 'node_modules'); } -// Load the plug-in found using `resolvePlugin`. +// Load the plugin found using `resolvePlugin`. function loadPlugin(name, options) { return commonjsRequire(resolvePlugin(name, options) || name) } @@ -6326,8 +8643,9 @@ function resolvePlugin(name, options) { if (name.charAt(0) === '@') { slash = name.indexOf('/'); - // Let’s keep the algorithm simple. No need to care if this is a - // “valid” scope (I think?). But we do check for the slash. + // Let’s keep the algorithm simple. + // No need to care if this is a “valid” scope (I think?). + // But we do check for the slash. if (slash !== -1) { scope = name.slice(0, slash + 1); name = name.slice(slash + 1); @@ -6357,6 +8675,15 @@ function resolvePlugin(name, options) { return null } +var isPlainObj = value => { + if (Object.prototype.toString.call(value) !== '[object Object]') { + return false; + } + + const prototype = Object.getPrototypeOf(value); + return prototype === null || prototype === Object.prototype; +}; + var format = createCommonjsModule(function (module) { (function() { @@ -6499,47 +8826,14 @@ function create(EConstructor) { } } -var immutable = extend$1; - -var hasOwnProperty = Object.prototype.hasOwnProperty; - -function extend$1() { - var target = {}; - - for (var i = 0; i < arguments.length; i++) { - var source = arguments[i]; - - for (var key in source) { - if (hasOwnProperty.call(source, key)) { - target[key] = source[key]; - } - } - } - - return target -} - -var isObject$1 = function isObject(x) { - return typeof x === "object" && x !== null; -}; - -var toString = Object.prototype.toString; - -var xIsString = isString; - -function isString(obj) { - return toString.call(obj) === "[object String]" -} - var debug = src('unified-engine:find-up'); +var findUp$1 = FindUp; -var findUp = FindUp; - -var read = fs$1.readFile; +var read$1 = fs$1.readFile; var resolve$1 = path$1.resolve; var relative = path$1.relative; -var join$1 = path$1.join; +var join = path$1.join; var dirname = path$1.dirname; FindUp.prototype.load = load$2; @@ -6576,7 +8870,7 @@ function load$2(filePath, callback) { givenFile = [callback]; self.givenFile = givenFile; debug('Checking given file `%s`', givenFilePath); - read(givenFilePath, loadGiven); + read$1(givenFilePath, loadGiven); } return @@ -6613,13 +8907,13 @@ function load$2(filePath, callback) { try { result = create(buf, givenFilePath); debug('Read given file `%s`', givenFilePath); - } catch (error2) { + } catch (error_) { result = fault_1( 'Cannot parse given file `%s`\n%s', relative(cwd, givenFilePath), - error2.stack + error_.stack ); - debug(error2.message); + debug(error_.message); } } @@ -6641,7 +8935,7 @@ function load$2(filePath, callback) { // We do not use `readdir` because on huge directories, that could be // *very* slow. if (++index < length) { - read(join$1(directory, names[index]), done); + read$1(join(directory, names[index]), done); } else { parent = dirname(directory); @@ -6659,7 +8953,7 @@ function load$2(filePath, callback) { function done(error, buf) { var name = names[index]; - var fp = join$1(directory, name); + var fp = join(directory, name); var contents; /* istanbul ignore if - Hard to test. */ @@ -6679,9 +8973,9 @@ function load$2(filePath, callback) { try { contents = create(buf, fp); - } catch (error2) { + } catch (error_) { return found( - fault_1('Cannot parse file `%s`\n%s', relative(cwd, fp), error2.message) + fault_1('Cannot parse file `%s`\n%s', relative(cwd, fp), error_.message) ) } @@ -6710,7 +9004,11 @@ function load$2(filePath, callback) { } function apply(cb, result) { - if (isObject$1(result) && typeof result[0] === 'function') { + if ( + result !== null && + typeof result === 'object' && + typeof result[0] === 'function' + ) { result.push(cb); } else if (result instanceof Error) { cb(result); @@ -6732,8 +9030,6 @@ var resolve = loadPlugin_1.resolve; - - module.exports = Config; var own = {}.hasOwnProperty; @@ -6743,13 +9039,13 @@ var dirname = path$1.dirname; var relative = path$1.relative; var loaders = { - '.json': loadJSON, + '.json': loadJson, '.js': loadScript, - '.yaml': loadYAML, - '.yml': loadYAML + '.yaml': loadYaml, + '.yml': loadYaml }; -var defaultLoader = loadJSON; +var defaultLoader = loadJson; Config.prototype.load = load; @@ -6777,7 +9073,7 @@ function Config(options) { this.given = {settings: options.settings, plugins: options.plugins}; this.create = create.bind(this); - this.findUp = new findUp({ + this.findUp = new findUp$1({ filePath: options.rcPath, cwd: options.cwd, detect: options.detectConfig, @@ -6787,14 +9083,14 @@ function Config(options) { } function load(filePath, callback) { - var searchPath = filePath || path$1.resolve(this.cwd, 'stdin.js'); var self = this; + var searchPath = filePath || path$1.resolve(this.cwd, 'stdin.js'); self.findUp.load(searchPath, done); - function done(error, res) { - if (error || res) { - return callback(error, res) + function done(error, file) { + if (error || file) { + return callback(error, file) } callback(null, self.create()); @@ -6821,13 +9117,17 @@ function create(buf, filePath) { if (contents === undefined) { if (defaults) { - merge(result, defaults, null, immutable(options, {root: self.cwd})); + merge(result, defaults, Object.assign({}, options, {root: self.cwd})); } } else { - merge(result, contents, null, immutable(options, {root: dirname(filePath)})); + merge( + result, + contents, + Object.assign({}, options, {root: dirname(filePath)}) + ); } - merge(result, self.given, null, immutable(options, {root: self.cwd})); + merge(result, self.given, Object.assign({}, options, {root: self.cwd})); return result } @@ -6848,11 +9148,11 @@ function loadScript(buf, filePath) { return submodule.exports } -function loadYAML(buf, filePath) { +function loadYaml(buf, filePath) { return jsYaml$1.safeLoad(buf, {filename: basename(filePath)}) } -function loadJSON(buf, filePath) { +function loadJson(buf, filePath) { var result = parseJson$1(buf, filePath); if (basename(filePath) === 'package.json') { @@ -6862,12 +9162,12 @@ function loadJSON(buf, filePath) { return result } -function merge(target, raw, val, options) { +function merge(target, raw, options) { var root = options.root; var cwd = options.cwd; var prefix = options.prefix; - if (isObject$1(raw)) { + if (typeof raw === 'object' && raw !== null) { addPreset(raw); } else { throw new Error('Expected preset, not `' + raw + '`') @@ -6878,7 +9178,7 @@ function merge(target, raw, val, options) { function addPreset(result) { var plugins = result.plugins; - if (plugins === null || plugins === undefined) ; else if (isObject$1(plugins)) { + if (plugins === null || plugins === undefined) ; else if (typeof plugins === 'object' && plugins !== null) { if ('length' in plugins) { addEach(plugins); } else { @@ -6890,7 +9190,7 @@ function merge(target, raw, val, options) { ) } - target.settings = immutable(target.settings, result.settings); + target.settings = Object.assign({}, target.settings, result.settings); } function addEach(result) { @@ -6901,7 +9201,7 @@ function merge(target, raw, val, options) { while (++index < length) { value = result[index]; - if (isObject$1(value) && 'length' in value) { + if (value !== null && typeof value === 'object' && 'length' in value) { use.apply(null, value); } else { use(value); @@ -6918,22 +9218,22 @@ function merge(target, raw, val, options) { } function use(usable, value) { - if (xIsString(usable)) { + if (typeof usable === 'string') { addModule(usable, value); } else if (typeof usable === 'function') { addPlugin(usable, value); } else { - merge(target, usable, value, options); + merge(target, usable, options); } } function addModule(id, value) { var fp = resolve(id, {cwd: root, prefix: prefix}); - var res; + var result; if (fp) { try { - res = commonjsRequire(fp); + result = commonjsRequire(fp); } catch (error) { throw fault_1( 'Cannot parse script `%s`\n%s', @@ -6943,15 +9243,15 @@ function merge(target, raw, val, options) { } try { - if (typeof res === 'function') { - addPlugin(res, value); + if (typeof result === 'function') { + addPlugin(result, value); } else { - merge(target, res, value, immutable(options, {root: dirname(fp)})); + merge(target, result, Object.assign({}, options, {root: dirname(fp)})); } - } catch (error) { + } catch (_) { throw fault_1( 'Error: Expected preset or plugin, not %s, at `%s`', - res, + result, relative(root, fp) ) } @@ -6976,8 +9276,8 @@ function merge(target, raw, val, options) { } function reconfigure(entry, value) { - if (value !== false && entry[1] !== false && isObject$1(value)) { - value = immutable(entry[1], value); + if (isPlainObj(entry[1]) && isPlainObj(value)) { + value = Object.assign({}, entry[1], value); } entry[1] = value; @@ -7294,11 +9594,11 @@ const makeRegex = (pattern, negative, ignorecase) => { : new RegExp(source) }; -const isString$1 = subject => typeof subject === 'string'; +const isString = subject => typeof subject === 'string'; // > A blank line matches no files, so it can serve as a separator for readability. const checkPattern = pattern => pattern - && isString$1(pattern) + && isString(pattern) && !REGEX_TEST_BLANK_LINE.test(pattern) // > A line starting with # serves as a comment. @@ -7353,7 +9653,7 @@ const throwError$1 = (message, Ctor) => { }; const checkPath = (path, originalPath, doThrow) => { - if (!isString$1(path)) { + if (!isString(path)) { return doThrow( `path must be a string, but got \`${originalPath}\``, TypeError @@ -7417,7 +9717,7 @@ class Ignore { this._added = false; makeArray( - isString$1(pattern) + isString(pattern) ? splitPattern(pattern) : pattern ).forEach(this._addPattern, this); @@ -7586,14 +9886,16 @@ var ignore$1 = Ignore$1; Ignore$1.prototype.check = check; +var sep = path$1.sep; var dirname$1 = path$1.dirname; var relative$1 = path$1.relative; var resolve$2 = path$1.resolve; function Ignore$1(options) { this.cwd = options.cwd; + this.ignorePathResolveFrom = options.ignorePathResolveFrom; - this.findUp = new findUp({ + this.findUp = new findUp$1({ filePath: options.ignorePath, cwd: options.cwd, detect: options.detectIgnore, @@ -7613,8 +9915,24 @@ function check(filePath, callback) { if (error) { callback(error); } else if (ignore) { - normal = relative$1(ignore.filePath, resolve$2(self.cwd, filePath)); - callback(null, normal ? ignore.ignores(normal) : false); + normal = relative$1( + resolve$2( + self.cwd, + self.ignorePathResolveFrom === 'cwd' ? '.' : ignore.filePath + ), + resolve$2(self.cwd, filePath) + ); + + if ( + normal === '' || + normal === '..' || + normal.charAt(0) === sep || + normal.slice(0, 3) === '..' + sep + ) { + callback(null, false); + } else { + callback(null, ignore.ignores(normal)); + } } else { callback(null, false); } @@ -9226,7 +11544,7 @@ if (typeof Object.create === 'function') { var inherits = createCommonjsModule(function (module) { try { - var util = util$1; + var util = util$2; /* istanbul ignore next */ if (typeof util.inherits !== 'function') throw ''; module.exports = util.inherits; @@ -9510,7 +11828,7 @@ var common$2 = { childrenIgnored: childrenIgnored_1 }; -var sync = globSync; +var sync$3 = globSync; globSync.GlobSync = GlobSync; var setopts$1 = common$2.setopts; var ownProp$1 = common$2.ownProp; @@ -10170,19 +12488,19 @@ function glob (pattern, options, cb) { if (options.sync) { if (cb) throw new TypeError('callback provided to sync glob') - return sync(pattern, options) + return sync$3(pattern, options) } return new Glob(pattern, options, cb) } -glob.sync = sync; -var GlobSync$1 = glob.GlobSync = sync.GlobSync; +glob.sync = sync$3; +var GlobSync$1 = glob.GlobSync = sync$3.GlobSync; // old api surface glob.glob = glob; -function extend$2 (origin, add) { +function extend$1 (origin, add) { if (add === null || typeof add !== 'object') { return origin } @@ -10196,7 +12514,7 @@ function extend$2 (origin, add) { } glob.hasMagic = function (pattern, options_) { - var options = extend$2({}, options_); + var options = extend$1({}, options_); options.noprocess = true; var g = new Glob(pattern, options); @@ -11062,7 +13380,7 @@ var proto$1 = VFile.prototype; // stem can be set. var order = ['history', 'path', 'basename', 'stem', 'extname', 'dirname']; -proto$1.toString = toString$1; +proto$1.toString = toString; // Access full path (`~/index.min.js`). Object.defineProperty(proto$1, 'path', {get: getPath, set: setPath}); @@ -11189,7 +13507,7 @@ function setStem(stem) { } // Get the value of the file. -function toString$1(encoding) { +function toString(encoding) { var value = this.contents || ''; return isBuffer(value) ? value.toString(encoding) : String(value) } @@ -11275,7 +13593,7 @@ function toVFile(options) { return vfile(options) } -var read$1 = readSync; +var read$2 = readSync; var write = writeSync; // Create a virtual file and read it in, synchronously. @@ -11296,16 +13614,16 @@ function writeSync(description, options) { return file } -var sync$1 = { - read: read$1, +var sync$4 = { + read: read$2, write: write }; -var read_1 = read$2; +var read_1 = read$3; var write_1 = write$1; // Create a virtual file and read it in, asynchronously. -function read$2(description, options, callback) { +function read$3(description, options, callback) { var file = core$2(description); if (!callback && typeof options === 'function') { @@ -11394,32 +13712,23 @@ var async = { var fs = core$2; core$2.read = async.read; -core$2.readSync = sync$1.read; +core$2.readSync = sync$4.read; core$2.write = async.write; -core$2.writeSync = sync$1.write; +core$2.writeSync = sync$4.write; var toVfile = fs; -var isHidden = hidden; - -function hidden(filename) { - if (typeof filename !== 'string') { - throw new Error('Expected string') - } - - return filename.charAt(0) === '.' -} - var readdir = fs$1.readdir; var stat = fs$1.stat; -var join$2 = path$1.join; +var sep$1 = path$1.sep; +var join$1 = path$1.join; var relative$2 = path$1.relative; var resolve$3 = path$1.resolve; var basename = path$1.basename; var extname = path$1.extname; var magic = glob_1.hasMagic; -var finder = find; +var finder$1 = find; // Search `patterns`, a mix of globs, paths, and files. function find(input, options, callback) { @@ -11452,7 +13761,7 @@ function expand$1(input, options, next) { } function each(file) { - if (xIsString(file)) { + if (typeof file === 'string') { if (magic(file)) { expected++; glob_1(file, {cwd: cwd}, one); @@ -11519,23 +13828,27 @@ function search(input, options, next) { return each function each(file) { - var ext = xIsString(file) ? extname(file) : file.extname; + var ext = typeof file === 'string' ? extname(file) : file.extname; var part; // Normalise globs. - if (xIsString(file)) { + if (typeof file === 'string') { file = file.split('/').join(path$1.sep); } part = base(file); - if (nested && (isHidden(part) || part === 'node_modules')) { + if (nested && (part.charAt(0) === '.' || part === 'node_modules')) { return } expected++; - statAndIgnore(file, immutable(options, {extraIgnore: extraIgnore}), handle); + statAndIgnore( + file, + Object.assign({}, options, {extraIgnore: extraIgnore}), + handle + ); function handle(error, result) { var ignored = result && result.ignored; @@ -11564,7 +13877,7 @@ function search(input, options, next) { if (ignored) { try { file.fail('Cannot process specified file: it’s ignored'); - } catch (error2) {} + } catch (_) {} } if (error && error.code === 'ENOENT') { @@ -11572,7 +13885,7 @@ function search(input, options, next) { file.fail( error.syscall === 'stat' ? 'No such file or directory' : error ); - } catch (error2) {} + } catch (_) {} } one(null, [file]); @@ -11589,11 +13902,15 @@ function search(input, options, next) { try { file.fail('Cannot read directory'); - } catch (error2) {} + } catch (_) {} one(null, [file]); } else { - search(basenames.map(concat), immutable(options, {nested: true}), one); + search( + basenames.map(concat), + Object.assign({}, options, {nested: true}), + one + ); } } @@ -11612,7 +13929,7 @@ function search(input, options, next) { } function concat(value) { - return join$2(filePath(file), value) + return join$1(filePath(file), value) } } } @@ -11620,8 +13937,9 @@ function search(input, options, next) { function statAndIgnore(file, options, callback) { var ignore = options.ignore; var extraIgnore = options.extraIgnore; - var fp = resolve$3(options.cwd, filePath(file)); - var normal = relative$2(options.cwd, fp); + var cwd = options.cwd; + var fp = resolve$3(cwd, filePath(file)); + var normal = relative$2(cwd, fp); var expected = 1; var actual = 0; var stats; @@ -11653,18 +13971,25 @@ function statAndIgnore(file, options, callback) { } else if (actual === expected) { callback(null, { stats: stats, - ignored: ignored || (normal ? extraIgnore.ignores(normal) : false) + ignored: + ignored || + (normal === '' || + normal === '..' || + normal.charAt(0) === sep$1 || + normal.slice(0, 3) === '..' + sep$1 + ? false + : extraIgnore.ignores(normal)) }); } } } function base(file) { - return xIsString(file) ? basename(file) : file.basename + return typeof file === 'string' ? basename(file) : file.basename } function filePath(file) { - return xIsString(file) ? file : file.path + return typeof file === 'string' ? file : file.path } function oneFileMode(result) { @@ -11684,7 +14009,7 @@ function fileSystem(context, settings, next) { if (input.length === 0) { next(); } else { - finder( + finder$1( input, { cwd: settings.cwd, @@ -11695,7 +14020,8 @@ function fileSystem(context, settings, next) { cwd: settings.cwd, detectIgnore: settings.detectIgnore, ignoreName: settings.ignoreName, - ignorePath: settings.ignorePath + ignorePath: settings.ignorePath, + ignorePathResolveFrom: settings.ignorePathResolveFrom }) }, onfound @@ -11734,7 +14060,7 @@ function fileSystem(context, settings, next) { } } -var toString$2 = Object.prototype.toString; +var toString$1 = Object.prototype.toString; var isModern = ( typeof Buffer.alloc === 'function' && @@ -11743,7 +14069,7 @@ var isModern = ( ); function isArrayBuffer (input) { - return toString$2.call(input).slice(8, -1) === 'ArrayBuffer' + return toString$1.call(input).slice(8, -1) === 'ArrayBuffer' } function fromArrayBuffer (obj, byteOffset, length) { @@ -12642,8 +14968,7 @@ function stdin(context, settings, next) { } } -var inherits$1 = util$1.inherits; - +var inherits$1 = util$2.inherits; @@ -12713,7 +15038,7 @@ function add(file) { var self = this; var origin; - if (xIsString(file)) { + if (typeof file === 'string') { file = toVfile(file); } @@ -12757,13 +15082,13 @@ function one() { var debug$2 = src('unified-engine:file-pipeline:read'); -var read_1$1 = read$3; +var read_1$1 = read$4; var resolve$4 = path$1.resolve; var readFile = fs$1.readFile; // Fill a file with its contents when not already filled. -function read$3(context, file, fileSet, next) { +function read$4(context, file, fileSet, next) { var filePath = file.path; if (file.contents || file.data.unifiedEngineStreamIn) { @@ -12788,14 +15113,6 @@ function read$3(context, file, fileSet, next) { } } -var fnName = function (fn) { - if (typeof fn !== 'function') { - throw new TypeError('Expected a function'); - } - - return fn.displayName || fn.name || (/function ([^\(]+)?\(/.exec(fn.toString()) || [])[1] || null; -}; - /** * Has own property. * @@ -12810,7 +15127,7 @@ var has = Object.prototype.hasOwnProperty; * @type {Function} */ -var toString$3 = Object.prototype.toString; +var toString$2 = Object.prototype.toString; /** * Test whether a value is "empty". @@ -12842,7 +15159,7 @@ function isEmpty(val) { if (val instanceof Error) return val.message === '' // Objects... - if (val.toString == toString$3) { + if (val.toString == toString$2) { switch (val.toString()) { // Maps, Sets, Files and Errors... @@ -12873,14 +15190,12 @@ function isEmpty(val) { * @type {Function} */ -var lib = isEmpty; +var lib$3 = isEmpty; var debug$3 = src('unified-engine:file-pipeline:configure'); - - var configure_1$1 = configure$1; // Collect configuration for a file based on the context. @@ -12925,18 +15240,18 @@ function configure$1(context, file, fileSet, next) { } // Allow for default arguments in es2020. - if (options === null || (isObject$1(options) && lib(options))) { + if (options === null || (typeof options === 'object' && lib$3(options))) { options = undefined; } - name = fnName(plugin) || 'function'; + name = plugin.displayName || plugin.name || 'function'; debug$3('Using plugin `%s`, with options `%j`', name, options); try { processor.use(plugin, options, fileSet); - } catch (error2) { + } catch (error_) { /* istanbul ignore next - Should not happen anymore! */ - return next(error2) + return next(error_) } } @@ -12970,8 +15285,8 @@ function parse$3(context, file) { message.fatal = true; } - // Add the preferred extension to ensure the file, when compiled, is correctly - // recognised. + // Add the preferred extension to ensure the file, when serialized, is + // correctly recognised. // Only add it if there is a path — not if the file is for example stdin. if (file.path) { file.extname = context.extensions[0]; @@ -13071,8 +15386,8 @@ function queue(context, file, fileSet, next) { var color = true; try { - color = 'inspect' in util$1; -} catch (error) { + color = 'inspect' in util$2; +} catch (_) { /* istanbul ignore next - browser */ color = false; } @@ -13240,7 +15555,7 @@ function formatNode(node) { ignore$2.indexOf(key) !== -1 || value === null || value === undefined || - (typeof value === 'object' && lib(value)) + (typeof value === 'object' && lib$3(value)) ) { continue } @@ -13273,6 +15588,7 @@ var debug$7 = src('unified-engine:file-pipeline:stringify'); + var stringify_1 = stringify$2; // Stringify a tree. @@ -13313,14 +15629,17 @@ function stringify$2(context, file) { value = processor.stringify(tree, file); } - file.contents = value; + if (value === undefined || value === null) ; else if (typeof value === 'string' || isBuffer(value)) { + file.contents = value; + } else { + file.result = value; + } - debug$7('Compiled document'); + debug$7('Serialized document'); } var debug$8 = src('unified-engine:file-pipeline:copy'); - var copy_1 = copy; var stat$1 = fs$1.stat; @@ -13335,7 +15654,7 @@ function copy(context, file, fileSet, next) { var outpath = output; var currentPath = file.path; - if (!xIsString(outpath)) { + if (typeof outpath !== 'string') { debug$8('Not copying'); return next() } @@ -13455,25 +15774,9 @@ function fileSystem$1(context, file, fileSet, next) { // This pipeline ensures each of the pipes always runs: even if the read pipe // fails, queue and write run. var filePipeline = trough_1() - .use( - chunk( - trough_1() - .use(read_1$1) - .use(configure_1$1) - .use(parse_1) - .use(transform_1) - ) - ) + .use(chunk(trough_1().use(read_1$1).use(configure_1$1).use(parse_1).use(transform_1))) .use(chunk(trough_1().use(queue_1))) - .use( - chunk( - trough_1() - .use(stringify_1) - .use(copy_1) - .use(stdout_1) - .use(fileSystem_1$1) - ) - ); + .use(chunk(trough_1().use(stringify_1).use(copy_1).use(stdout_1).use(fileSystem_1$1))); // Factory to run a pipe. // Wraps a pipe to trigger an error on the `file` in `context`, but still call @@ -13558,31 +15861,39 @@ function transform$1(context, settings, next) { } } -const {env: env$1} = process; +var hasFlag$2 = (flag, argv) => { + argv = argv || process.argv; + const prefix = flag.startsWith('-') ? '' : (flag.length === 1 ? '-' : '--'); + const pos = argv.indexOf(prefix + flag); + const terminatorPos = argv.indexOf('--'); + return pos !== -1 && (terminatorPos === -1 ? true : pos < terminatorPos); +}; -let forceColor$1; -if (hasFlag('no-color') || - hasFlag('no-colors') || - hasFlag('color=false') || - hasFlag('color=never')) { - forceColor$1 = 0; -} else if (hasFlag('color') || - hasFlag('colors') || - hasFlag('color=true') || - hasFlag('color=always')) { - forceColor$1 = 1; -} -if ('FORCE_COLOR' in env$1) { - if (env$1.FORCE_COLOR === true || env$1.FORCE_COLOR === 'true') { - forceColor$1 = 1; - } else if (env$1.FORCE_COLOR === false || env$1.FORCE_COLOR === 'false') { - forceColor$1 = 0; +const {env: env$2} = process; + +let forceColor$2; +if (hasFlag$2('no-color') || + hasFlag$2('no-colors') || + hasFlag$2('color=false') || + hasFlag$2('color=never')) { + forceColor$2 = 0; +} else if (hasFlag$2('color') || + hasFlag$2('colors') || + hasFlag$2('color=true') || + hasFlag$2('color=always')) { + forceColor$2 = 1; +} +if ('FORCE_COLOR' in env$2) { + if (env$2.FORCE_COLOR === true || env$2.FORCE_COLOR === 'true') { + forceColor$2 = 1; + } else if (env$2.FORCE_COLOR === false || env$2.FORCE_COLOR === 'false') { + forceColor$2 = 0; } else { - forceColor$1 = env$1.FORCE_COLOR.length === 0 ? 1 : Math.min(parseInt(env$1.FORCE_COLOR, 10), 3); + forceColor$2 = env$2.FORCE_COLOR.length === 0 ? 1 : Math.min(parseInt(env$2.FORCE_COLOR, 10), 3); } } -function translateLevel$1(level) { +function translateLevel$2(level) { if (level === 0) { return false; } @@ -13595,28 +15906,28 @@ function translateLevel$1(level) { }; } -function supportsColor$1(stream) { - if (forceColor$1 === 0) { +function supportsColor$2(stream) { + if (forceColor$2 === 0) { return 0; } - if (hasFlag('color=16m') || - hasFlag('color=full') || - hasFlag('color=truecolor')) { + if (hasFlag$2('color=16m') || + hasFlag$2('color=full') || + hasFlag$2('color=truecolor')) { return 3; } - if (hasFlag('color=256')) { + if (hasFlag$2('color=256')) { return 2; } - if (stream && !stream.isTTY && forceColor$1 === undefined) { + if (stream && !stream.isTTY && forceColor$2 === undefined) { return 0; } - const min = forceColor$1 || 0; + const min = forceColor$2 || 0; - if (env$1.TERM === 'dumb') { + if (env$2.TERM === 'dumb') { return min; } @@ -13639,26 +15950,26 @@ function supportsColor$1(stream) { return 1; } - if ('CI' in env$1) { - if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI'].some(sign => sign in env$1) || env$1.CI_NAME === 'codeship') { + if ('CI' in env$2) { + if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI'].some(sign => sign in env$2) || env$2.CI_NAME === 'codeship') { return 1; } return min; } - if ('TEAMCITY_VERSION' in env$1) { - return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env$1.TEAMCITY_VERSION) ? 1 : 0; + if ('TEAMCITY_VERSION' in env$2) { + return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env$2.TEAMCITY_VERSION) ? 1 : 0; } - if (env$1.COLORTERM === 'truecolor') { + if (env$2.COLORTERM === 'truecolor') { return 3; } - if ('TERM_PROGRAM' in env$1) { - const version = parseInt((env$1.TERM_PROGRAM_VERSION || '').split('.')[0], 10); + if ('TERM_PROGRAM' in env$2) { + const version = parseInt((env$2.TERM_PROGRAM_VERSION || '').split('.')[0], 10); - switch (env$1.TERM_PROGRAM) { + switch (env$2.TERM_PROGRAM) { case 'iTerm.app': return version >= 3 ? 3 : 2; case 'Apple_Terminal': @@ -13667,30 +15978,30 @@ function supportsColor$1(stream) { } } - if (/-256(color)?$/i.test(env$1.TERM)) { + if (/-256(color)?$/i.test(env$2.TERM)) { return 2; } - if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env$1.TERM)) { + if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env$2.TERM)) { return 1; } - if ('COLORTERM' in env$1) { + if ('COLORTERM' in env$2) { return 1; } return min; } -function getSupportLevel$1(stream) { - const level = supportsColor$1(stream); - return translateLevel$1(level); +function getSupportLevel$2(stream) { + const level = supportsColor$2(stream); + return translateLevel$2(level); } -var supportsColor_1$1 = { - supportsColor: getSupportLevel$1, - stdout: getSupportLevel$1(process.stdout), - stderr: getSupportLevel$1(process.stderr) +var supportsColor_1$2 = { + supportsColor: getSupportLevel$2, + stdout: getSupportLevel$2(process.stdout), + stderr: getSupportLevel$2(process.stderr) }; var ansiRegex = ({onlyFirst = false} = {}) => { @@ -13752,8 +16063,8 @@ const isFullwidthCodePoint = codePoint => { }; var isFullwidthCodePoint_1 = isFullwidthCodePoint; -var default_1 = isFullwidthCodePoint; -isFullwidthCodePoint_1.default = default_1; +var default_1$2 = isFullwidthCodePoint; +isFullwidthCodePoint_1.default = default_1$2; var emojiRegex = function () { // https://mths.be/emoji @@ -13797,8 +16108,8 @@ const stringWidth = string => { var stringWidth_1 = stringWidth; // TODO: remove this in the next major version -var default_1$1 = stringWidth; -stringWidth_1.default = default_1$1; +var default_1$3 = stringWidth; +stringWidth_1.default = default_1$3; /*! * repeat-string @@ -13903,7 +16214,7 @@ function compare(a, b, property) { return (a[property] || '').localeCompare(b[property] || '') } -var supported = supportsColor_1$1.stderr.hasBasic; +var supported = supportsColor_1$2.stderr.hasBasic; @@ -14233,16 +16544,16 @@ function plural$1(value, count) { var log_1 = log; -var prefix$1 = 'vfile-reporter'; +var prefix = 'vfile-reporter'; function log(context, settings, next) { var reporter = settings.reporter || vfileReporter; var diagnostics; - if (xIsString(reporter)) { + if (typeof reporter === 'string') { try { - reporter = loadPlugin_1(reporter, {cwd: settings.cwd, prefix: prefix$1}); - } catch (error) { + reporter = loadPlugin_1(reporter, {cwd: settings.cwd, prefix: prefix}); + } catch (_) { next(new Error('Could not find reporter `' + reporter + '`')); return } @@ -14250,7 +16561,7 @@ function log(context, settings, next) { diagnostics = reporter( context.files.filter(given), - immutable(settings.reporterOptions, { + Object.assign({}, settings.reporterOptions, { quiet: settings.quiet, silent: settings.silent, color: settings.color @@ -14283,7 +16594,7 @@ var PassThrough = stream.PassThrough; -var lib$1 = run; +var lib$4 = run; // Run the file set pipeline once. // `callback` is invoked with a fatal error, or with a status code (`0` on @@ -14299,7 +16610,7 @@ function run(options, callback) { try { stdin = process.stdin; - } catch (error) { + } catch (_) { // Obscure bug in Node (seen on Windows). // See: , // . @@ -14388,6 +16699,7 @@ function run(options, callback) { : detectIgnore; settings.ignoreName = options.ignoreName || null; settings.ignorePath = options.ignorePath || null; + settings.ignorePathResolveFrom = options.ignorePathResolveFrom || 'dir'; settings.ignorePatterns = options.ignorePatterns || []; settings.silentlyIgnore = Boolean(options.silentlyIgnore); @@ -14428,20 +16740,10 @@ function extension(ext) { return ext.charAt(0) === '.' ? ext : '.' + ext } -var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g; - -var escapeStringRegexp = function (str) { - if (typeof str !== 'string') { - throw new TypeError('Expected a string'); - } - - return str.replace(matchOperatorsRe, '\\$&'); -}; - -var colorName = { - "aliceblue": [240, 248, 255], - "antiquewhite": [250, 235, 215], - "aqua": [0, 255, 255], +var colorName$1 = { + "aliceblue": [240, 248, 255], + "antiquewhite": [250, 235, 215], + "aqua": [0, 255, 255], "aquamarine": [127, 255, 212], "azure": [240, 255, 255], "beige": [245, 245, 220], @@ -14586,25 +16888,23 @@ var colorName = { "white": [255, 255, 255], "whitesmoke": [245, 245, 245], "yellow": [255, 255, 0], - "yellowgreen": [154, 205, 50] + "yellowgreen": [154, 205, 50] }; -var conversions = createCommonjsModule(function (module) { /* MIT license */ +/* eslint-disable no-mixed-operators */ // NOTE: conversions should only return primitive values (i.e. arrays, or // values that give correct `typeof` results). // do not use box values types (i.e. Number(), String(), etc.) -var reverseKeywords = {}; -for (var key in colorName) { - if (colorName.hasOwnProperty(key)) { - reverseKeywords[colorName[key]] = key; - } +const reverseKeywords = {}; +for (const key of Object.keys(colorName$1)) { + reverseKeywords[colorName$1[key]] = key; } -var convert = module.exports = { +const convert$1 = { rgb: {channels: 3, labels: 'rgb'}, hsl: {channels: 3, labels: 'hsl'}, hsv: {channels: 3, labels: 'hsv'}, @@ -14622,40 +16922,38 @@ var convert = module.exports = { gray: {channels: 1, labels: ['gray']} }; -// hide .channels and .labels properties -for (var model in convert) { - if (convert.hasOwnProperty(model)) { - if (!('channels' in convert[model])) { - throw new Error('missing channels property: ' + model); - } +var conversions$1 = convert$1; - if (!('labels' in convert[model])) { - throw new Error('missing channel labels property: ' + model); - } +// Hide .channels and .labels properties +for (const model of Object.keys(convert$1)) { + if (!('channels' in convert$1[model])) { + throw new Error('missing channels property: ' + model); + } - if (convert[model].labels.length !== convert[model].channels) { - throw new Error('channel and label counts mismatch: ' + model); - } + if (!('labels' in convert$1[model])) { + throw new Error('missing channel labels property: ' + model); + } - var channels = convert[model].channels; - var labels = convert[model].labels; - delete convert[model].channels; - delete convert[model].labels; - Object.defineProperty(convert[model], 'channels', {value: channels}); - Object.defineProperty(convert[model], 'labels', {value: labels}); + if (convert$1[model].labels.length !== convert$1[model].channels) { + throw new Error('channel and label counts mismatch: ' + model); } + + const {channels, labels} = convert$1[model]; + delete convert$1[model].channels; + delete convert$1[model].labels; + Object.defineProperty(convert$1[model], 'channels', {value: channels}); + Object.defineProperty(convert$1[model], 'labels', {value: labels}); } -convert.rgb.hsl = function (rgb) { - var r = rgb[0] / 255; - var g = rgb[1] / 255; - var b = rgb[2] / 255; - var min = Math.min(r, g, b); - var max = Math.max(r, g, b); - var delta = max - min; - var h; - var s; - var l; +convert$1.rgb.hsl = function (rgb) { + const r = rgb[0] / 255; + const g = rgb[1] / 255; + const b = rgb[2] / 255; + const min = Math.min(r, g, b); + const max = Math.max(r, g, b); + const delta = max - min; + let h; + let s; if (max === min) { h = 0; @@ -14673,7 +16971,7 @@ convert.rgb.hsl = function (rgb) { h += 360; } - l = (min + max) / 2; + const l = (min + max) / 2; if (max === min) { s = 0; @@ -14686,24 +16984,25 @@ convert.rgb.hsl = function (rgb) { return [h, s * 100, l * 100]; }; -convert.rgb.hsv = function (rgb) { - var rdif; - var gdif; - var bdif; - var h; - var s; +convert$1.rgb.hsv = function (rgb) { + let rdif; + let gdif; + let bdif; + let h; + let s; - var r = rgb[0] / 255; - var g = rgb[1] / 255; - var b = rgb[2] / 255; - var v = Math.max(r, g, b); - var diff = v - Math.min(r, g, b); - var diffc = function (c) { + const r = rgb[0] / 255; + const g = rgb[1] / 255; + const b = rgb[2] / 255; + const v = Math.max(r, g, b); + const diff = v - Math.min(r, g, b); + const diffc = function (c) { return (v - c) / 6 / diff + 1 / 2; }; if (diff === 0) { - h = s = 0; + h = 0; + s = 0; } else { s = diff / v; rdif = diffc(r); @@ -14717,6 +17016,7 @@ convert.rgb.hsv = function (rgb) { } else if (b === v) { h = (2 / 3) + gdif - rdif; } + if (h < 0) { h += 1; } else if (h > 1) { @@ -14731,127 +17031,116 @@ convert.rgb.hsv = function (rgb) { ]; }; -convert.rgb.hwb = function (rgb) { - var r = rgb[0]; - var g = rgb[1]; - var b = rgb[2]; - var h = convert.rgb.hsl(rgb)[0]; - var w = 1 / 255 * Math.min(r, Math.min(g, b)); +convert$1.rgb.hwb = function (rgb) { + const r = rgb[0]; + const g = rgb[1]; + let b = rgb[2]; + const h = convert$1.rgb.hsl(rgb)[0]; + const w = 1 / 255 * Math.min(r, Math.min(g, b)); b = 1 - 1 / 255 * Math.max(r, Math.max(g, b)); return [h, w * 100, b * 100]; }; -convert.rgb.cmyk = function (rgb) { - var r = rgb[0] / 255; - var g = rgb[1] / 255; - var b = rgb[2] / 255; - var c; - var m; - var y; - var k; +convert$1.rgb.cmyk = function (rgb) { + const r = rgb[0] / 255; + const g = rgb[1] / 255; + const b = rgb[2] / 255; - k = Math.min(1 - r, 1 - g, 1 - b); - c = (1 - r - k) / (1 - k) || 0; - m = (1 - g - k) / (1 - k) || 0; - y = (1 - b - k) / (1 - k) || 0; + const k = Math.min(1 - r, 1 - g, 1 - b); + const c = (1 - r - k) / (1 - k) || 0; + const m = (1 - g - k) / (1 - k) || 0; + const y = (1 - b - k) / (1 - k) || 0; return [c * 100, m * 100, y * 100, k * 100]; }; -/** - * See https://en.m.wikipedia.org/wiki/Euclidean_distance#Squared_Euclidean_distance - * */ function comparativeDistance(x, y) { + /* + See https://en.m.wikipedia.org/wiki/Euclidean_distance#Squared_Euclidean_distance + */ return ( - Math.pow(x[0] - y[0], 2) + - Math.pow(x[1] - y[1], 2) + - Math.pow(x[2] - y[2], 2) + ((x[0] - y[0]) ** 2) + + ((x[1] - y[1]) ** 2) + + ((x[2] - y[2]) ** 2) ); } -convert.rgb.keyword = function (rgb) { - var reversed = reverseKeywords[rgb]; +convert$1.rgb.keyword = function (rgb) { + const reversed = reverseKeywords[rgb]; if (reversed) { return reversed; } - var currentClosestDistance = Infinity; - var currentClosestKeyword; + let currentClosestDistance = Infinity; + let currentClosestKeyword; - for (var keyword in colorName) { - if (colorName.hasOwnProperty(keyword)) { - var value = colorName[keyword]; + for (const keyword of Object.keys(colorName$1)) { + const value = colorName$1[keyword]; - // Compute comparative distance - var distance = comparativeDistance(rgb, value); + // Compute comparative distance + const distance = comparativeDistance(rgb, value); - // Check if its less, if so set as closest - if (distance < currentClosestDistance) { - currentClosestDistance = distance; - currentClosestKeyword = keyword; - } + // Check if its less, if so set as closest + if (distance < currentClosestDistance) { + currentClosestDistance = distance; + currentClosestKeyword = keyword; } } return currentClosestKeyword; }; -convert.keyword.rgb = function (keyword) { - return colorName[keyword]; +convert$1.keyword.rgb = function (keyword) { + return colorName$1[keyword]; }; -convert.rgb.xyz = function (rgb) { - var r = rgb[0] / 255; - var g = rgb[1] / 255; - var b = rgb[2] / 255; +convert$1.rgb.xyz = function (rgb) { + let r = rgb[0] / 255; + let g = rgb[1] / 255; + let b = rgb[2] / 255; - // assume sRGB - r = r > 0.04045 ? Math.pow(((r + 0.055) / 1.055), 2.4) : (r / 12.92); - g = g > 0.04045 ? Math.pow(((g + 0.055) / 1.055), 2.4) : (g / 12.92); - b = b > 0.04045 ? Math.pow(((b + 0.055) / 1.055), 2.4) : (b / 12.92); + // Assume sRGB + r = r > 0.04045 ? (((r + 0.055) / 1.055) ** 2.4) : (r / 12.92); + g = g > 0.04045 ? (((g + 0.055) / 1.055) ** 2.4) : (g / 12.92); + b = b > 0.04045 ? (((b + 0.055) / 1.055) ** 2.4) : (b / 12.92); - var x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805); - var y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722); - var z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505); + const x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805); + const y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722); + const z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505); return [x * 100, y * 100, z * 100]; }; -convert.rgb.lab = function (rgb) { - var xyz = convert.rgb.xyz(rgb); - var x = xyz[0]; - var y = xyz[1]; - var z = xyz[2]; - var l; - var a; - var b; +convert$1.rgb.lab = function (rgb) { + const xyz = convert$1.rgb.xyz(rgb); + let x = xyz[0]; + let y = xyz[1]; + let z = xyz[2]; x /= 95.047; y /= 100; z /= 108.883; - x = x > 0.008856 ? Math.pow(x, 1 / 3) : (7.787 * x) + (16 / 116); - y = y > 0.008856 ? Math.pow(y, 1 / 3) : (7.787 * y) + (16 / 116); - z = z > 0.008856 ? Math.pow(z, 1 / 3) : (7.787 * z) + (16 / 116); + x = x > 0.008856 ? (x ** (1 / 3)) : (7.787 * x) + (16 / 116); + y = y > 0.008856 ? (y ** (1 / 3)) : (7.787 * y) + (16 / 116); + z = z > 0.008856 ? (z ** (1 / 3)) : (7.787 * z) + (16 / 116); - l = (116 * y) - 16; - a = 500 * (x - y); - b = 200 * (y - z); + const l = (116 * y) - 16; + const a = 500 * (x - y); + const b = 200 * (y - z); return [l, a, b]; }; -convert.hsl.rgb = function (hsl) { - var h = hsl[0] / 360; - var s = hsl[1] / 100; - var l = hsl[2] / 100; - var t1; - var t2; - var t3; - var rgb; - var val; +convert$1.hsl.rgb = function (hsl) { + const h = hsl[0] / 360; + const s = hsl[1] / 100; + const l = hsl[2] / 100; + let t2; + let t3; + let val; if (s === 0) { val = l * 255; @@ -14864,14 +17153,15 @@ convert.hsl.rgb = function (hsl) { t2 = l + s - l * s; } - t1 = 2 * l - t2; + const t1 = 2 * l - t2; - rgb = [0, 0, 0]; - for (var i = 0; i < 3; i++) { + const rgb = [0, 0, 0]; + for (let i = 0; i < 3; i++) { t3 = h + 1 / 3 * -(i - 1); if (t3 < 0) { t3++; } + if (t3 > 1) { t3--; } @@ -14892,34 +17182,32 @@ convert.hsl.rgb = function (hsl) { return rgb; }; -convert.hsl.hsv = function (hsl) { - var h = hsl[0]; - var s = hsl[1] / 100; - var l = hsl[2] / 100; - var smin = s; - var lmin = Math.max(l, 0.01); - var sv; - var v; +convert$1.hsl.hsv = function (hsl) { + const h = hsl[0]; + let s = hsl[1] / 100; + let l = hsl[2] / 100; + let smin = s; + const lmin = Math.max(l, 0.01); l *= 2; s *= (l <= 1) ? l : 2 - l; smin *= lmin <= 1 ? lmin : 2 - lmin; - v = (l + s) / 2; - sv = l === 0 ? (2 * smin) / (lmin + smin) : (2 * s) / (l + s); + const v = (l + s) / 2; + const sv = l === 0 ? (2 * smin) / (lmin + smin) : (2 * s) / (l + s); return [h, sv * 100, v * 100]; }; -convert.hsv.rgb = function (hsv) { - var h = hsv[0] / 60; - var s = hsv[1] / 100; - var v = hsv[2] / 100; - var hi = Math.floor(h) % 6; +convert$1.hsv.rgb = function (hsv) { + const h = hsv[0] / 60; + const s = hsv[1] / 100; + let v = hsv[2] / 100; + const hi = Math.floor(h) % 6; - var f = h - Math.floor(h); - var p = 255 * v * (1 - s); - var q = 255 * v * (1 - (s * f)); - var t = 255 * v * (1 - (s * (1 - f))); + const f = h - Math.floor(h); + const p = 255 * v * (1 - s); + const q = 255 * v * (1 - (s * f)); + const t = 255 * v * (1 - (s * (1 - f))); v *= 255; switch (hi) { @@ -14938,17 +17226,16 @@ convert.hsv.rgb = function (hsv) { } }; -convert.hsv.hsl = function (hsv) { - var h = hsv[0]; - var s = hsv[1] / 100; - var v = hsv[2] / 100; - var vmin = Math.max(v, 0.01); - var lmin; - var sl; - var l; +convert$1.hsv.hsl = function (hsv) { + const h = hsv[0]; + const s = hsv[1] / 100; + const v = hsv[2] / 100; + const vmin = Math.max(v, 0.01); + let sl; + let l; l = (2 - s) * v; - lmin = (2 - s) * vmin; + const lmin = (2 - s) * vmin; sl = s * vmin; sl /= (lmin <= 1) ? lmin : 2 - lmin; sl = sl || 0; @@ -14958,88 +17245,84 @@ convert.hsv.hsl = function (hsv) { }; // http://dev.w3.org/csswg/css-color/#hwb-to-rgb -convert.hwb.rgb = function (hwb) { - var h = hwb[0] / 360; - var wh = hwb[1] / 100; - var bl = hwb[2] / 100; - var ratio = wh + bl; - var i; - var v; - var f; - var n; - - // wh + bl cant be > 1 +convert$1.hwb.rgb = function (hwb) { + const h = hwb[0] / 360; + let wh = hwb[1] / 100; + let bl = hwb[2] / 100; + const ratio = wh + bl; + let f; + + // Wh + bl cant be > 1 if (ratio > 1) { wh /= ratio; bl /= ratio; } - i = Math.floor(6 * h); - v = 1 - bl; + const i = Math.floor(6 * h); + const v = 1 - bl; f = 6 * h - i; if ((i & 0x01) !== 0) { f = 1 - f; } - n = wh + f * (v - wh); // linear interpolation + const n = wh + f * (v - wh); // Linear interpolation - var r; - var g; - var b; + let r; + let g; + let b; + /* eslint-disable max-statements-per-line,no-multi-spaces */ switch (i) { default: case 6: - case 0: r = v; g = n; b = wh; break; - case 1: r = n; g = v; b = wh; break; - case 2: r = wh; g = v; b = n; break; - case 3: r = wh; g = n; b = v; break; - case 4: r = n; g = wh; b = v; break; - case 5: r = v; g = wh; b = n; break; + case 0: r = v; g = n; b = wh; break; + case 1: r = n; g = v; b = wh; break; + case 2: r = wh; g = v; b = n; break; + case 3: r = wh; g = n; b = v; break; + case 4: r = n; g = wh; b = v; break; + case 5: r = v; g = wh; b = n; break; } + /* eslint-enable max-statements-per-line,no-multi-spaces */ return [r * 255, g * 255, b * 255]; }; -convert.cmyk.rgb = function (cmyk) { - var c = cmyk[0] / 100; - var m = cmyk[1] / 100; - var y = cmyk[2] / 100; - var k = cmyk[3] / 100; - var r; - var g; - var b; +convert$1.cmyk.rgb = function (cmyk) { + const c = cmyk[0] / 100; + const m = cmyk[1] / 100; + const y = cmyk[2] / 100; + const k = cmyk[3] / 100; - r = 1 - Math.min(1, c * (1 - k) + k); - g = 1 - Math.min(1, m * (1 - k) + k); - b = 1 - Math.min(1, y * (1 - k) + k); + const r = 1 - Math.min(1, c * (1 - k) + k); + const g = 1 - Math.min(1, m * (1 - k) + k); + const b = 1 - Math.min(1, y * (1 - k) + k); return [r * 255, g * 255, b * 255]; }; -convert.xyz.rgb = function (xyz) { - var x = xyz[0] / 100; - var y = xyz[1] / 100; - var z = xyz[2] / 100; - var r; - var g; - var b; +convert$1.xyz.rgb = function (xyz) { + const x = xyz[0] / 100; + const y = xyz[1] / 100; + const z = xyz[2] / 100; + let r; + let g; + let b; r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986); g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415); b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570); - // assume sRGB + // Assume sRGB r = r > 0.0031308 - ? ((1.055 * Math.pow(r, 1.0 / 2.4)) - 0.055) + ? ((1.055 * (r ** (1.0 / 2.4))) - 0.055) : r * 12.92; g = g > 0.0031308 - ? ((1.055 * Math.pow(g, 1.0 / 2.4)) - 0.055) + ? ((1.055 * (g ** (1.0 / 2.4))) - 0.055) : g * 12.92; b = b > 0.0031308 - ? ((1.055 * Math.pow(b, 1.0 / 2.4)) - 0.055) + ? ((1.055 * (b ** (1.0 / 2.4))) - 0.055) : b * 12.92; r = Math.min(Math.max(0, r), 1); @@ -15049,44 +17332,41 @@ convert.xyz.rgb = function (xyz) { return [r * 255, g * 255, b * 255]; }; -convert.xyz.lab = function (xyz) { - var x = xyz[0]; - var y = xyz[1]; - var z = xyz[2]; - var l; - var a; - var b; +convert$1.xyz.lab = function (xyz) { + let x = xyz[0]; + let y = xyz[1]; + let z = xyz[2]; x /= 95.047; y /= 100; z /= 108.883; - x = x > 0.008856 ? Math.pow(x, 1 / 3) : (7.787 * x) + (16 / 116); - y = y > 0.008856 ? Math.pow(y, 1 / 3) : (7.787 * y) + (16 / 116); - z = z > 0.008856 ? Math.pow(z, 1 / 3) : (7.787 * z) + (16 / 116); + x = x > 0.008856 ? (x ** (1 / 3)) : (7.787 * x) + (16 / 116); + y = y > 0.008856 ? (y ** (1 / 3)) : (7.787 * y) + (16 / 116); + z = z > 0.008856 ? (z ** (1 / 3)) : (7.787 * z) + (16 / 116); - l = (116 * y) - 16; - a = 500 * (x - y); - b = 200 * (y - z); + const l = (116 * y) - 16; + const a = 500 * (x - y); + const b = 200 * (y - z); return [l, a, b]; }; -convert.lab.xyz = function (lab) { - var l = lab[0]; - var a = lab[1]; - var b = lab[2]; - var x; - var y; - var z; +convert$1.lab.xyz = function (lab) { + const l = lab[0]; + const a = lab[1]; + const b = lab[2]; + let x; + let y; + let z; y = (l + 16) / 116; x = a / 500 + y; z = y - b / 200; - var y2 = Math.pow(y, 3); - var x2 = Math.pow(x, 3); - var z2 = Math.pow(z, 3); + const y2 = y ** 3; + const x2 = x ** 3; + const z2 = z ** 3; y = y2 > 0.008856 ? y2 : (y - 16 / 116) / 7.787; x = x2 > 0.008856 ? x2 : (x - 16 / 116) / 7.787; z = z2 > 0.008856 ? z2 : (z - 16 / 116) / 7.787; @@ -15098,46 +17378,39 @@ convert.lab.xyz = function (lab) { return [x, y, z]; }; -convert.lab.lch = function (lab) { - var l = lab[0]; - var a = lab[1]; - var b = lab[2]; - var hr; - var h; - var c; +convert$1.lab.lch = function (lab) { + const l = lab[0]; + const a = lab[1]; + const b = lab[2]; + let h; - hr = Math.atan2(b, a); + const hr = Math.atan2(b, a); h = hr * 360 / 2 / Math.PI; if (h < 0) { h += 360; } - c = Math.sqrt(a * a + b * b); + const c = Math.sqrt(a * a + b * b); return [l, c, h]; }; -convert.lch.lab = function (lch) { - var l = lch[0]; - var c = lch[1]; - var h = lch[2]; - var a; - var b; - var hr; +convert$1.lch.lab = function (lch) { + const l = lch[0]; + const c = lch[1]; + const h = lch[2]; - hr = h / 360 * 2 * Math.PI; - a = c * Math.cos(hr); - b = c * Math.sin(hr); + const hr = h / 360 * 2 * Math.PI; + const a = c * Math.cos(hr); + const b = c * Math.sin(hr); return [l, a, b]; }; -convert.rgb.ansi16 = function (args) { - var r = args[0]; - var g = args[1]; - var b = args[2]; - var value = 1 in arguments ? arguments[1] : convert.rgb.hsv(args)[2]; // hsv -> ansi16 optimization +convert$1.rgb.ansi16 = function (args, saturation = null) { + const [r, g, b] = args; + let value = saturation === null ? convert$1.rgb.hsv(args)[2] : saturation; // Hsv -> ansi16 optimization value = Math.round(value / 50); @@ -15145,7 +17418,7 @@ convert.rgb.ansi16 = function (args) { return 30; } - var ansi = 30 + let ansi = 30 + ((Math.round(b / 255) << 2) | (Math.round(g / 255) << 1) | Math.round(r / 255)); @@ -15157,18 +17430,18 @@ convert.rgb.ansi16 = function (args) { return ansi; }; -convert.hsv.ansi16 = function (args) { - // optimization here; we already know the value and don't need to get +convert$1.hsv.ansi16 = function (args) { + // Optimization here; we already know the value and don't need to get // it converted for us. - return convert.rgb.ansi16(convert.hsv.rgb(args), args[2]); + return convert$1.rgb.ansi16(convert$1.hsv.rgb(args), args[2]); }; -convert.rgb.ansi256 = function (args) { - var r = args[0]; - var g = args[1]; - var b = args[2]; +convert$1.rgb.ansi256 = function (args) { + const r = args[0]; + const g = args[1]; + const b = args[2]; - // we use the extended greyscale palette here, with the exception of + // We use the extended greyscale palette here, with the exception of // black and white. normal palette only has 4 greyscale shades. if (r === g && g === b) { if (r < 8) { @@ -15182,7 +17455,7 @@ convert.rgb.ansi256 = function (args) { return Math.round(((r - 8) / 247) * 24) + 232; } - var ansi = 16 + const ansi = 16 + (36 * Math.round(r / 255 * 5)) + (6 * Math.round(g / 255 * 5)) + Math.round(b / 255 * 5); @@ -15190,10 +17463,10 @@ convert.rgb.ansi256 = function (args) { return ansi; }; -convert.ansi16.rgb = function (args) { - var color = args % 10; +convert$1.ansi16.rgb = function (args) { + let color = args % 10; - // handle greyscale + // Handle greyscale if (color === 0 || color === 7) { if (args > 50) { color += 3.5; @@ -15204,71 +17477,71 @@ convert.ansi16.rgb = function (args) { return [color, color, color]; } - var mult = (~~(args > 50) + 1) * 0.5; - var r = ((color & 1) * mult) * 255; - var g = (((color >> 1) & 1) * mult) * 255; - var b = (((color >> 2) & 1) * mult) * 255; + const mult = (~~(args > 50) + 1) * 0.5; + const r = ((color & 1) * mult) * 255; + const g = (((color >> 1) & 1) * mult) * 255; + const b = (((color >> 2) & 1) * mult) * 255; return [r, g, b]; }; -convert.ansi256.rgb = function (args) { - // handle greyscale +convert$1.ansi256.rgb = function (args) { + // Handle greyscale if (args >= 232) { - var c = (args - 232) * 10 + 8; + const c = (args - 232) * 10 + 8; return [c, c, c]; } args -= 16; - var rem; - var r = Math.floor(args / 36) / 5 * 255; - var g = Math.floor((rem = args % 36) / 6) / 5 * 255; - var b = (rem % 6) / 5 * 255; + let rem; + const r = Math.floor(args / 36) / 5 * 255; + const g = Math.floor((rem = args % 36) / 6) / 5 * 255; + const b = (rem % 6) / 5 * 255; return [r, g, b]; }; -convert.rgb.hex = function (args) { - var integer = ((Math.round(args[0]) & 0xFF) << 16) +convert$1.rgb.hex = function (args) { + const integer = ((Math.round(args[0]) & 0xFF) << 16) + ((Math.round(args[1]) & 0xFF) << 8) + (Math.round(args[2]) & 0xFF); - var string = integer.toString(16).toUpperCase(); + const string = integer.toString(16).toUpperCase(); return '000000'.substring(string.length) + string; }; -convert.hex.rgb = function (args) { - var match = args.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i); +convert$1.hex.rgb = function (args) { + const match = args.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i); if (!match) { return [0, 0, 0]; } - var colorString = match[0]; + let colorString = match[0]; if (match[0].length === 3) { - colorString = colorString.split('').map(function (char) { + colorString = colorString.split('').map(char => { return char + char; }).join(''); } - var integer = parseInt(colorString, 16); - var r = (integer >> 16) & 0xFF; - var g = (integer >> 8) & 0xFF; - var b = integer & 0xFF; + const integer = parseInt(colorString, 16); + const r = (integer >> 16) & 0xFF; + const g = (integer >> 8) & 0xFF; + const b = integer & 0xFF; return [r, g, b]; }; -convert.rgb.hcg = function (rgb) { - var r = rgb[0] / 255; - var g = rgb[1] / 255; - var b = rgb[2] / 255; - var max = Math.max(Math.max(r, g), b); - var min = Math.min(Math.min(r, g), b); - var chroma = (max - min); - var grayscale; - var hue; +convert$1.rgb.hcg = function (rgb) { + const r = rgb[0] / 255; + const g = rgb[1] / 255; + const b = rgb[2] / 255; + const max = Math.max(Math.max(r, g), b); + const min = Math.min(Math.min(r, g), b); + const chroma = (max - min); + let grayscale; + let hue; if (chroma < 1) { grayscale = min / (1 - chroma); @@ -15285,7 +17558,7 @@ convert.rgb.hcg = function (rgb) { if (max === g) { hue = 2 + (b - r) / chroma; } else { - hue = 4 + (r - g) / chroma + 4; + hue = 4 + (r - g) / chroma; } hue /= 6; @@ -15294,18 +17567,13 @@ convert.rgb.hcg = function (rgb) { return [hue * 360, chroma * 100, grayscale * 100]; }; -convert.hsl.hcg = function (hsl) { - var s = hsl[1] / 100; - var l = hsl[2] / 100; - var c = 1; - var f = 0; +convert$1.hsl.hcg = function (hsl) { + const s = hsl[1] / 100; + const l = hsl[2] / 100; - if (l < 0.5) { - c = 2.0 * s * l; - } else { - c = 2.0 * s * (1.0 - l); - } + const c = l < 0.5 ? (2.0 * s * l) : (2.0 * s * (1.0 - l)); + let f = 0; if (c < 1.0) { f = (l - 0.5 * c) / (1.0 - c); } @@ -15313,12 +17581,12 @@ convert.hsl.hcg = function (hsl) { return [hsl[0], c * 100, f * 100]; }; -convert.hsv.hcg = function (hsv) { - var s = hsv[1] / 100; - var v = hsv[2] / 100; +convert$1.hsv.hcg = function (hsv) { + const s = hsv[1] / 100; + const v = hsv[2] / 100; - var c = s * v; - var f = 0; + const c = s * v; + let f = 0; if (c < 1.0) { f = (v - c) / (1 - c); @@ -15327,21 +17595,22 @@ convert.hsv.hcg = function (hsv) { return [hsv[0], c * 100, f * 100]; }; -convert.hcg.rgb = function (hcg) { - var h = hcg[0] / 360; - var c = hcg[1] / 100; - var g = hcg[2] / 100; +convert$1.hcg.rgb = function (hcg) { + const h = hcg[0] / 360; + const c = hcg[1] / 100; + const g = hcg[2] / 100; if (c === 0.0) { return [g * 255, g * 255, g * 255]; } - var pure = [0, 0, 0]; - var hi = (h % 1) * 6; - var v = hi % 1; - var w = 1 - v; - var mg = 0; + const pure = [0, 0, 0]; + const hi = (h % 1) * 6; + const v = hi % 1; + const w = 1 - v; + let mg = 0; + /* eslint-disable max-statements-per-line */ switch (Math.floor(hi)) { case 0: pure[0] = 1; pure[1] = v; pure[2] = 0; break; @@ -15356,6 +17625,7 @@ convert.hcg.rgb = function (hcg) { default: pure[0] = 1; pure[1] = 0; pure[2] = w; } + /* eslint-enable max-statements-per-line */ mg = (1.0 - c) * g; @@ -15366,12 +17636,12 @@ convert.hcg.rgb = function (hcg) { ]; }; -convert.hcg.hsv = function (hcg) { - var c = hcg[1] / 100; - var g = hcg[2] / 100; +convert$1.hcg.hsv = function (hcg) { + const c = hcg[1] / 100; + const g = hcg[2] / 100; - var v = c + g * (1.0 - c); - var f = 0; + const v = c + g * (1.0 - c); + let f = 0; if (v > 0.0) { f = c / v; @@ -15380,12 +17650,12 @@ convert.hcg.hsv = function (hcg) { return [hcg[0], f * 100, v * 100]; }; -convert.hcg.hsl = function (hcg) { - var c = hcg[1] / 100; - var g = hcg[2] / 100; +convert$1.hcg.hsl = function (hcg) { + const c = hcg[1] / 100; + const g = hcg[2] / 100; - var l = g * (1.0 - c) + 0.5 * c; - var s = 0; + const l = g * (1.0 - c) + 0.5 * c; + let s = 0; if (l > 0.0 && l < 0.5) { s = c / (2 * l); @@ -15397,19 +17667,19 @@ convert.hcg.hsl = function (hcg) { return [hcg[0], s * 100, l * 100]; }; -convert.hcg.hwb = function (hcg) { - var c = hcg[1] / 100; - var g = hcg[2] / 100; - var v = c + g * (1.0 - c); +convert$1.hcg.hwb = function (hcg) { + const c = hcg[1] / 100; + const g = hcg[2] / 100; + const v = c + g * (1.0 - c); return [hcg[0], (v - c) * 100, (1 - v) * 100]; }; -convert.hwb.hcg = function (hwb) { - var w = hwb[1] / 100; - var b = hwb[2] / 100; - var v = 1 - b; - var c = v - w; - var g = 0; +convert$1.hwb.hcg = function (hwb) { + const w = hwb[1] / 100; + const b = hwb[2] / 100; + const v = 1 - b; + const c = v - w; + let g = 0; if (c < 1) { g = (v - c) / (1 - c); @@ -15418,65 +17688,51 @@ convert.hwb.hcg = function (hwb) { return [hwb[0], c * 100, g * 100]; }; -convert.apple.rgb = function (apple) { +convert$1.apple.rgb = function (apple) { return [(apple[0] / 65535) * 255, (apple[1] / 65535) * 255, (apple[2] / 65535) * 255]; }; -convert.rgb.apple = function (rgb) { +convert$1.rgb.apple = function (rgb) { return [(rgb[0] / 255) * 65535, (rgb[1] / 255) * 65535, (rgb[2] / 255) * 65535]; }; -convert.gray.rgb = function (args) { +convert$1.gray.rgb = function (args) { return [args[0] / 100 * 255, args[0] / 100 * 255, args[0] / 100 * 255]; }; -convert.gray.hsl = convert.gray.hsv = function (args) { +convert$1.gray.hsl = function (args) { return [0, 0, args[0]]; }; -convert.gray.hwb = function (gray) { +convert$1.gray.hsv = convert$1.gray.hsl; + +convert$1.gray.hwb = function (gray) { return [0, 100, gray[0]]; }; -convert.gray.cmyk = function (gray) { +convert$1.gray.cmyk = function (gray) { return [0, 0, 0, gray[0]]; }; -convert.gray.lab = function (gray) { +convert$1.gray.lab = function (gray) { return [gray[0], 0, 0]; }; -convert.gray.hex = function (gray) { - var val = Math.round(gray[0] / 100 * 255) & 0xFF; - var integer = (val << 16) + (val << 8) + val; +convert$1.gray.hex = function (gray) { + const val = Math.round(gray[0] / 100 * 255) & 0xFF; + const integer = (val << 16) + (val << 8) + val; - var string = integer.toString(16).toUpperCase(); + const string = integer.toString(16).toUpperCase(); return '000000'.substring(string.length) + string; }; -convert.rgb.gray = function (rgb) { - var val = (rgb[0] + rgb[1] + rgb[2]) / 3; +convert$1.rgb.gray = function (rgb) { + const val = (rgb[0] + rgb[1] + rgb[2]) / 3; return [val / 255 * 100]; }; -}); -var conversions_1 = conversions.rgb; -var conversions_2 = conversions.hsl; -var conversions_3 = conversions.hsv; -var conversions_4 = conversions.hwb; -var conversions_5 = conversions.cmyk; -var conversions_6 = conversions.xyz; -var conversions_7 = conversions.lab; -var conversions_8 = conversions.lch; -var conversions_9 = conversions.hex; -var conversions_10 = conversions.keyword; -var conversions_11 = conversions.ansi16; -var conversions_12 = conversions.ansi256; -var conversions_13 = conversions.hcg; -var conversions_14 = conversions.apple; -var conversions_15 = conversions.gray; /* - this function routes a model to all other models. + This function routes a model to all other models. all functions that are routed have a property `.conversion` attached to the returned synthetic function. This property is an array @@ -15486,12 +17742,12 @@ var conversions_15 = conversions.gray; conversions that are not possible simply are not included. */ -function buildGraph() { - var graph = {}; +function buildGraph$1() { + const graph = {}; // https://jsperf.com/object-keys-vs-for-in-with-closure/3 - var models = Object.keys(conversions); + const models = Object.keys(conversions$1); - for (var len = models.length, i = 0; i < len; i++) { + for (let len = models.length, i = 0; i < len; i++) { graph[models[i]] = { // http://jsperf.com/1-vs-infinity // micro-opt, but this is simple. @@ -15504,19 +17760,19 @@ function buildGraph() { } // https://en.wikipedia.org/wiki/Breadth-first_search -function deriveBFS(fromModel) { - var graph = buildGraph(); - var queue = [fromModel]; // unshift -> queue -> pop +function deriveBFS$1(fromModel) { + const graph = buildGraph$1(); + const queue = [fromModel]; // Unshift -> queue -> pop graph[fromModel].distance = 0; while (queue.length) { - var current = queue.pop(); - var adjacents = Object.keys(conversions[current]); + const current = queue.pop(); + const adjacents = Object.keys(conversions$1[current]); - for (var len = adjacents.length, i = 0; i < len; i++) { - var adjacent = adjacents[i]; - var node = graph[adjacent]; + for (let len = adjacents.length, i = 0; i < len; i++) { + const adjacent = adjacents[i]; + const node = graph[adjacent]; if (node.distance === -1) { node.distance = graph[current].distance + 1; @@ -15529,20 +17785,20 @@ function deriveBFS(fromModel) { return graph; } -function link(from, to) { +function link$1(from, to) { return function (args) { return to(from(args)); }; } -function wrapConversion(toModel, graph) { - var path = [graph[toModel].parent, toModel]; - var fn = conversions[graph[toModel].parent][toModel]; +function wrapConversion$1(toModel, graph) { + const path = [graph[toModel].parent, toModel]; + let fn = conversions$1[graph[toModel].parent][toModel]; - var cur = graph[toModel].parent; + let cur = graph[toModel].parent; while (graph[cur].parent) { path.unshift(graph[cur].parent); - fn = link(conversions[graph[cur].parent][cur], fn); + fn = link$1(conversions$1[graph[cur].parent][cur], fn); cur = graph[cur].parent; } @@ -15550,44 +17806,45 @@ function wrapConversion(toModel, graph) { return fn; } -var route = function (fromModel) { - var graph = deriveBFS(fromModel); - var conversion = {}; +var route$1 = function (fromModel) { + const graph = deriveBFS$1(fromModel); + const conversion = {}; - var models = Object.keys(graph); - for (var len = models.length, i = 0; i < len; i++) { - var toModel = models[i]; - var node = graph[toModel]; + const models = Object.keys(graph); + for (let len = models.length, i = 0; i < len; i++) { + const toModel = models[i]; + const node = graph[toModel]; if (node.parent === null) { - // no possible conversion, or this node is the source model. + // No possible conversion, or this node is the source model. continue; } - conversion[toModel] = wrapConversion(toModel, graph); + conversion[toModel] = wrapConversion$1(toModel, graph); } return conversion; }; -var convert = {}; +const convert$2 = {}; -var models = Object.keys(conversions); +const models$1 = Object.keys(conversions$1); -function wrapRaw(fn) { - var wrappedFn = function (args) { - if (args === undefined || args === null) { - return args; +function wrapRaw$1(fn) { + const wrappedFn = function (...args) { + const arg0 = args[0]; + if (arg0 === undefined || arg0 === null) { + return arg0; } - if (arguments.length > 1) { - args = Array.prototype.slice.call(arguments); + if (arg0.length > 1) { + args = arg0; } return fn(args); }; - // preserve .conversion property if there is one + // Preserve .conversion property if there is one if ('conversion' in fn) { wrappedFn.conversion = fn.conversion; } @@ -15595,23 +17852,25 @@ function wrapRaw(fn) { return wrappedFn; } -function wrapRounded(fn) { - var wrappedFn = function (args) { - if (args === undefined || args === null) { - return args; +function wrapRounded$1(fn) { + const wrappedFn = function (...args) { + const arg0 = args[0]; + + if (arg0 === undefined || arg0 === null) { + return arg0; } - if (arguments.length > 1) { - args = Array.prototype.slice.call(arguments); + if (arg0.length > 1) { + args = arg0; } - var result = fn(args); + const result = fn(args); - // we're assuming the result is an array here. + // We're assuming the result is an array here. // see notice in conversions.js; don't use box types // in conversion functions. if (typeof result === 'object') { - for (var len = result.length, i = 0; i < len; i++) { + for (let len = result.length, i = 0; i < len; i++) { result[i] = Math.round(result[i]); } } @@ -15619,7 +17878,7 @@ function wrapRounded(fn) { return result; }; - // preserve .conversion property if there is one + // Preserve .conversion property if there is one if ('conversion' in fn) { wrappedFn.conversion = fn.conversion; } @@ -15627,43 +17886,85 @@ function wrapRounded(fn) { return wrappedFn; } -models.forEach(function (fromModel) { - convert[fromModel] = {}; +models$1.forEach(fromModel => { + convert$2[fromModel] = {}; - Object.defineProperty(convert[fromModel], 'channels', {value: conversions[fromModel].channels}); - Object.defineProperty(convert[fromModel], 'labels', {value: conversions[fromModel].labels}); + Object.defineProperty(convert$2[fromModel], 'channels', {value: conversions$1[fromModel].channels}); + Object.defineProperty(convert$2[fromModel], 'labels', {value: conversions$1[fromModel].labels}); - var routes = route(fromModel); - var routeModels = Object.keys(routes); + const routes = route$1(fromModel); + const routeModels = Object.keys(routes); - routeModels.forEach(function (toModel) { - var fn = routes[toModel]; + routeModels.forEach(toModel => { + const fn = routes[toModel]; - convert[fromModel][toModel] = wrapRounded(fn); - convert[fromModel][toModel].raw = wrapRaw(fn); + convert$2[fromModel][toModel] = wrapRounded$1(fn); + convert$2[fromModel][toModel].raw = wrapRaw$1(fn); }); }); -var colorConvert = convert; - -var ansiStyles = createCommonjsModule(function (module) { +var colorConvert$1 = convert$2; +var ansiStyles$1 = createCommonjsModule(function (module) { -const wrapAnsi16 = (fn, offset) => function () { - const code = fn.apply(colorConvert, arguments); +const wrapAnsi16 = (fn, offset) => (...args) => { + const code = fn(...args); return `\u001B[${code + offset}m`; }; -const wrapAnsi256 = (fn, offset) => function () { - const code = fn.apply(colorConvert, arguments); +const wrapAnsi256 = (fn, offset) => (...args) => { + const code = fn(...args); return `\u001B[${38 + offset};5;${code}m`; }; -const wrapAnsi16m = (fn, offset) => function () { - const rgb = fn.apply(colorConvert, arguments); +const wrapAnsi16m = (fn, offset) => (...args) => { + const rgb = fn(...args); return `\u001B[${38 + offset};2;${rgb[0]};${rgb[1]};${rgb[2]}m`; }; +const ansi2ansi = n => n; +const rgb2rgb = (r, g, b) => [r, g, b]; + +const setLazyProperty = (object, property, get) => { + Object.defineProperty(object, property, { + get: () => { + const value = get(); + + Object.defineProperty(object, property, { + value, + enumerable: true, + configurable: true + }); + + return value; + }, + enumerable: true, + configurable: true + }); +}; + +/** @type {typeof import('color-convert')} */ +let colorConvert; +const makeDynamicStyles = (wrap, targetSpace, identity, isBackground) => { + if (colorConvert === undefined) { + colorConvert = colorConvert$1; + } + + const offset = isBackground ? 10 : 0; + const styles = {}; + + for (const [sourceSpace, suite] of Object.entries(colorConvert)) { + const name = sourceSpace === 'ansi16' ? 'ansi' : sourceSpace; + if (sourceSpace === targetSpace) { + styles[name] = wrap(identity, offset); + } else if (typeof suite === 'object') { + styles[name] = wrap(suite[targetSpace], offset); + } + } + + return styles; +}; + function assembleStyles() { const codes = new Map(); const styles = { @@ -15687,9 +17988,9 @@ function assembleStyles() { magenta: [35, 39], cyan: [36, 39], white: [37, 39], - gray: [90, 39], // Bright color + blackBright: [90, 39], redBright: [91, 39], greenBright: [92, 39], yellowBright: [93, 39], @@ -15720,15 +18021,14 @@ function assembleStyles() { } }; - // Fix humans - styles.color.grey = styles.color.gray; - - for (const groupName of Object.keys(styles)) { - const group = styles[groupName]; - - for (const styleName of Object.keys(group)) { - const style = group[styleName]; + // Alias bright black as gray (and grey) + styles.color.gray = styles.color.blackBright; + styles.bgColor.bgGray = styles.bgColor.bgBlackBright; + styles.color.grey = styles.color.blackBright; + styles.bgColor.bgGrey = styles.bgColor.bgBlackBright; + for (const [groupName, group] of Object.entries(styles)) { + for (const [styleName, style] of Object.entries(group)) { styles[styleName] = { open: `\u001B[${style[0]}m`, close: `\u001B[${style[1]}m` @@ -15743,65 +18043,22 @@ function assembleStyles() { value: group, enumerable: false }); - - Object.defineProperty(styles, 'codes', { - value: codes, - enumerable: false - }); } - const ansi2ansi = n => n; - const rgb2rgb = (r, g, b) => [r, g, b]; + Object.defineProperty(styles, 'codes', { + value: codes, + enumerable: false + }); styles.color.close = '\u001B[39m'; styles.bgColor.close = '\u001B[49m'; - styles.color.ansi = { - ansi: wrapAnsi16(ansi2ansi, 0) - }; - styles.color.ansi256 = { - ansi256: wrapAnsi256(ansi2ansi, 0) - }; - styles.color.ansi16m = { - rgb: wrapAnsi16m(rgb2rgb, 0) - }; - - styles.bgColor.ansi = { - ansi: wrapAnsi16(ansi2ansi, 10) - }; - styles.bgColor.ansi256 = { - ansi256: wrapAnsi256(ansi2ansi, 10) - }; - styles.bgColor.ansi16m = { - rgb: wrapAnsi16m(rgb2rgb, 10) - }; - - for (let key of Object.keys(colorConvert)) { - if (typeof colorConvert[key] !== 'object') { - continue; - } - - const suite = colorConvert[key]; - - if (key === 'ansi16') { - key = 'ansi'; - } - - if ('ansi16' in suite) { - styles.color.ansi[key] = wrapAnsi16(suite.ansi16, 0); - styles.bgColor.ansi[key] = wrapAnsi16(suite.ansi16, 10); - } - - if ('ansi256' in suite) { - styles.color.ansi256[key] = wrapAnsi256(suite.ansi256, 0); - styles.bgColor.ansi256[key] = wrapAnsi256(suite.ansi256, 10); - } - - if ('rgb' in suite) { - styles.color.ansi16m[key] = wrapAnsi16m(suite.rgb, 0); - styles.bgColor.ansi16m[key] = wrapAnsi16m(suite.rgb, 10); - } - } + setLazyProperty(styles.color, 'ansi', () => makeDynamicStyles(wrapAnsi16, 'ansi16', ansi2ansi, false)); + setLazyProperty(styles.color, 'ansi256', () => makeDynamicStyles(wrapAnsi256, 'ansi256', ansi2ansi, false)); + setLazyProperty(styles.color, 'ansi16m', () => makeDynamicStyles(wrapAnsi16m, 'rgb', rgb2rgb, false)); + setLazyProperty(styles.bgColor, 'ansi', () => makeDynamicStyles(wrapAnsi16, 'ansi16', ansi2ansi, true)); + setLazyProperty(styles.bgColor, 'ansi256', () => makeDynamicStyles(wrapAnsi256, 'ansi256', ansi2ansi, true)); + setLazyProperty(styles.bgColor, 'ansi16m', () => makeDynamicStyles(wrapAnsi16m, 'rgb', rgb2rgb, true)); return styles; } @@ -15813,12 +18070,50 @@ Object.defineProperty(module, 'exports', { }); }); -const TEMPLATE_REGEX = /(?:\\(u[a-f\d]{4}|x[a-f\d]{2}|.))|(?:\{(~)?(\w+(?:\([^)]*\))?(?:\.\w+(?:\([^)]*\))?)*)(?:[ \t]|(?=\r?\n)))|(\})|((?:.|[\r\n\f])+?)/gi; -const STYLE_REGEX = /(?:^|\.)(\w+)(?:\(([^)]*)\))?/g; -const STRING_REGEX = /^(['"])((?:\\.|(?!\1)[^\\])*)\1$/; -const ESCAPE_REGEX = /\\(u[a-f\d]{4}|x[a-f\d]{2}|.)|([^\\])/gi; +const stringReplaceAll = (string, substring, replacer) => { + let index = string.indexOf(substring); + if (index === -1) { + return string; + } -const ESCAPES = new Map([ + const substringLength = substring.length; + let endIndex = 0; + let returnValue = ''; + do { + returnValue += string.substr(endIndex, index - endIndex) + substring + replacer; + endIndex = index + substringLength; + index = string.indexOf(substring, endIndex); + } while (index !== -1); + + returnValue += string.substr(endIndex); + return returnValue; +}; + +const stringEncaseCRLFWithFirstIndex = (string, prefix, postfix, index) => { + let endIndex = 0; + let returnValue = ''; + do { + const gotCR = string[index - 1] === '\r'; + returnValue += string.substr(endIndex, (gotCR ? index - 1 : index) - endIndex) + prefix + (gotCR ? '\r\n' : '\n') + postfix; + endIndex = index + 1; + index = string.indexOf('\n', endIndex); + } while (index !== -1); + + returnValue += string.substr(endIndex); + return returnValue; +}; + +var util = { + stringReplaceAll, + stringEncaseCRLFWithFirstIndex +}; + +const TEMPLATE_REGEX$1 = /(?:\\(u(?:[a-f\d]{4}|\{[a-f\d]{1,6}\})|x[a-f\d]{2}|.))|(?:\{(~)?(\w+(?:\([^)]*\))?(?:\.\w+(?:\([^)]*\))?)*)(?:[ \t]|(?=\r?\n)))|(\})|((?:.|[\r\n\f])+?)/gi; +const STYLE_REGEX$1 = /(?:^|\.)(\w+)(?:\(([^)]*)\))?/g; +const STRING_REGEX$1 = /^(['"])((?:\\.|(?!\1)[^\\])*)\1$/; +const ESCAPE_REGEX$1 = /\\(u(?:[a-f\d]{4}|\{[a-f\d]{1,6}\})|x[a-f\d]{2}|.)|([^\\])/gi; + +const ESCAPES$1 = new Map([ ['n', '\n'], ['r', '\r'], ['t', '\t'], @@ -15831,24 +18126,32 @@ const ESCAPES = new Map([ ['a', '\u0007'] ]); -function unescape(c) { - if ((c[0] === 'u' && c.length === 5) || (c[0] === 'x' && c.length === 3)) { +function unescape$1(c) { + const u = c[0] === 'u'; + const bracket = c[1] === '{'; + + if ((u && !bracket && c.length === 5) || (c[0] === 'x' && c.length === 3)) { return String.fromCharCode(parseInt(c.slice(1), 16)); } - return ESCAPES.get(c) || c; + if (u && bracket) { + return String.fromCodePoint(parseInt(c.slice(2, -1), 16)); + } + + return ESCAPES$1.get(c) || c; } -function parseArguments(name, args) { +function parseArguments$1(name, arguments_) { const results = []; - const chunks = args.trim().split(/\s*,\s*/g); + const chunks = arguments_.trim().split(/\s*,\s*/g); let matches; for (const chunk of chunks) { - if (!isNaN(chunk)) { - results.push(Number(chunk)); - } else if ((matches = chunk.match(STRING_REGEX))) { - results.push(matches[2].replace(ESCAPE_REGEX, (m, escape, chr) => escape ? unescape(escape) : chr)); + const number = Number(chunk); + if (!Number.isNaN(number)) { + results.push(number); + } else if ((matches = chunk.match(STRING_REGEX$1))) { + results.push(matches[2].replace(ESCAPE_REGEX$1, (m, escape, character) => escape ? unescape$1(escape) : character)); } else { throw new Error(`Invalid Chalk template style argument: ${chunk} (in style '${name}')`); } @@ -15857,17 +18160,17 @@ function parseArguments(name, args) { return results; } -function parseStyle(style) { - STYLE_REGEX.lastIndex = 0; +function parseStyle$1(style) { + STYLE_REGEX$1.lastIndex = 0; const results = []; let matches; - while ((matches = STYLE_REGEX.exec(style)) !== null) { + while ((matches = STYLE_REGEX$1.exec(style)) !== null) { const name = matches[1]; if (matches[2]) { - const args = parseArguments(name, matches[2]); + const args = parseArguments$1(name, matches[2]); results.push([name].concat(args)); } else { results.push([name]); @@ -15877,7 +18180,7 @@ function parseStyle(style) { return results; } -function buildStyle(chalk, styles) { +function buildStyle$1(chalk, styles) { const enabled = {}; for (const layer of styles) { @@ -15887,47 +18190,45 @@ function buildStyle(chalk, styles) { } let current = chalk; - for (const styleName of Object.keys(enabled)) { - if (Array.isArray(enabled[styleName])) { - if (!(styleName in current)) { - throw new Error(`Unknown Chalk style: ${styleName}`); - } + for (const [styleName, styles] of Object.entries(enabled)) { + if (!Array.isArray(styles)) { + continue; + } - if (enabled[styleName].length > 0) { - current = current[styleName].apply(current, enabled[styleName]); - } else { - current = current[styleName]; - } + if (!(styleName in current)) { + throw new Error(`Unknown Chalk style: ${styleName}`); } + + current = styles.length > 0 ? current[styleName](...styles) : current[styleName]; } return current; } -var templates = (chalk, tmp) => { +var templates$1 = (chalk, temporary) => { const styles = []; const chunks = []; let chunk = []; // eslint-disable-next-line max-params - tmp.replace(TEMPLATE_REGEX, (m, escapeChar, inverse, style, close, chr) => { - if (escapeChar) { - chunk.push(unescape(escapeChar)); + temporary.replace(TEMPLATE_REGEX$1, (m, escapeCharacter, inverse, style, close, character) => { + if (escapeCharacter) { + chunk.push(unescape$1(escapeCharacter)); } else if (style) { - const str = chunk.join(''); + const string = chunk.join(''); chunk = []; - chunks.push(styles.length === 0 ? str : buildStyle(chalk, styles)(str)); - styles.push({inverse, styles: parseStyle(style)}); + chunks.push(styles.length === 0 ? string : buildStyle$1(chalk, styles)(string)); + styles.push({inverse, styles: parseStyle$1(style)}); } else if (close) { if (styles.length === 0) { throw new Error('Found extraneous } in Chalk template literal'); } - chunks.push(buildStyle(chalk, styles)(chunk.join(''))); + chunks.push(buildStyle$1(chalk, styles)(chunk.join(''))); chunk = []; styles.pop(); } else { - chunk.push(chr); + chunk.push(character); } }); @@ -15941,236 +18242,237 @@ var templates = (chalk, tmp) => { return chunks.join(''); }; -var chalk = createCommonjsModule(function (module) { - - -const stdoutColor = supportsColor_1.stdout; - - - -const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm'); +const {stdout: stdoutColor, stderr: stderrColor} = supportsColor_1$1; +const { + stringReplaceAll: stringReplaceAll$1, + stringEncaseCRLFWithFirstIndex: stringEncaseCRLFWithFirstIndex$1 +} = util; // `supportsColor.level` → `ansiStyles.color[name]` mapping -const levelMapping = ['ansi', 'ansi', 'ansi256', 'ansi16m']; - -// `color-convert` models to exclude from the Chalk API due to conflicts and such -const skipModels = new Set(['gray']); +const levelMapping = [ + 'ansi', + 'ansi', + 'ansi256', + 'ansi16m' +]; const styles = Object.create(null); -function applyOptions(obj, options) { - options = options || {}; +const applyOptions = (object, options = {}) => { + if (options.level > 3 || options.level < 0) { + throw new Error('The `level` option should be an integer from 0 to 3'); + } // Detect level if not set manually - const scLevel = stdoutColor ? stdoutColor.level : 0; - obj.level = options.level === undefined ? scLevel : options.level; - obj.enabled = 'enabled' in options ? options.enabled : obj.level > 0; + const colorLevel = stdoutColor ? stdoutColor.level : 0; + object.level = options.level === undefined ? colorLevel : options.level; +}; + +class ChalkClass { + constructor(options) { + return chalkFactory(options); + } } -function Chalk(options) { - // We check for this.template here since calling `chalk.constructor()` - // by itself will have a `this` of a previously constructed chalk object - if (!this || !(this instanceof Chalk) || this.template) { - const chalk = {}; - applyOptions(chalk, options); +const chalkFactory = options => { + const chalk = {}; + applyOptions(chalk, options); - chalk.template = function () { - const args = [].slice.call(arguments); - return chalkTag.apply(null, [chalk.template].concat(args)); - }; + chalk.template = (...arguments_) => chalkTag(chalk.template, ...arguments_); - Object.setPrototypeOf(chalk, Chalk.prototype); - Object.setPrototypeOf(chalk.template, chalk); + Object.setPrototypeOf(chalk, Chalk.prototype); + Object.setPrototypeOf(chalk.template, chalk); - chalk.template.constructor = Chalk; + chalk.template.constructor = () => { + throw new Error('`chalk.constructor()` is deprecated. Use `new chalk.Instance()` instead.'); + }; - return chalk.template; - } + chalk.template.Instance = ChalkClass; - applyOptions(this, options); -} + return chalk.template; +}; -// Use bright blue on Windows as the normal blue color is illegible -if (isSimpleWindowsTerm) { - ansiStyles.blue.open = '\u001B[94m'; +function Chalk(options) { + return chalkFactory(options); } -for (const key of Object.keys(ansiStyles)) { - ansiStyles[key].closeRe = new RegExp(escapeStringRegexp(ansiStyles[key].close), 'g'); - - styles[key] = { +for (const [styleName, style] of Object.entries(ansiStyles$1)) { + styles[styleName] = { get() { - const codes = ansiStyles[key]; - return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, key); + const builder = createBuilder(this, createStyler(style.open, style.close, this._styler), this._isEmpty); + Object.defineProperty(this, styleName, {value: builder}); + return builder; } }; } styles.visible = { get() { - return build.call(this, this._styles || [], true, 'visible'); + const builder = createBuilder(this, this._styler, true); + Object.defineProperty(this, 'visible', {value: builder}); + return builder; } }; -ansiStyles.color.closeRe = new RegExp(escapeStringRegexp(ansiStyles.color.close), 'g'); -for (const model of Object.keys(ansiStyles.color.ansi)) { - if (skipModels.has(model)) { - continue; - } +const usedModels = ['rgb', 'hex', 'keyword', 'hsl', 'hsv', 'hwb', 'ansi', 'ansi256']; +for (const model of usedModels) { styles[model] = { get() { - const level = this.level; - return function () { - const open = ansiStyles.color[levelMapping[level]][model].apply(null, arguments); - const codes = { - open, - close: ansiStyles.color.close, - closeRe: ansiStyles.color.closeRe - }; - return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, model); + const {level} = this; + return function (...arguments_) { + const styler = createStyler(ansiStyles$1.color[levelMapping[level]][model](...arguments_), ansiStyles$1.color.close, this._styler); + return createBuilder(this, styler, this._isEmpty); }; } }; } -ansiStyles.bgColor.closeRe = new RegExp(escapeStringRegexp(ansiStyles.bgColor.close), 'g'); -for (const model of Object.keys(ansiStyles.bgColor.ansi)) { - if (skipModels.has(model)) { - continue; - } - +for (const model of usedModels) { const bgModel = 'bg' + model[0].toUpperCase() + model.slice(1); styles[bgModel] = { get() { - const level = this.level; - return function () { - const open = ansiStyles.bgColor[levelMapping[level]][model].apply(null, arguments); - const codes = { - open, - close: ansiStyles.bgColor.close, - closeRe: ansiStyles.bgColor.closeRe - }; - return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, model); + const {level} = this; + return function (...arguments_) { + const styler = createStyler(ansiStyles$1.bgColor[levelMapping[level]][model](...arguments_), ansiStyles$1.bgColor.close, this._styler); + return createBuilder(this, styler, this._isEmpty); }; } }; } -const proto = Object.defineProperties(() => {}, styles); - -function build(_styles, _empty, key) { - const builder = function () { - return applyStyle.apply(builder, arguments); - }; - - builder._styles = _styles; - builder._empty = _empty; - - const self = this; - - Object.defineProperty(builder, 'level', { +const proto$3 = Object.defineProperties(() => {}, { + ...styles, + level: { enumerable: true, get() { - return self.level; + return this._generator.level; }, set(level) { - self.level = level; + this._generator.level = level; } - }); + } +}); - Object.defineProperty(builder, 'enabled', { - enumerable: true, - get() { - return self.enabled; - }, - set(enabled) { - self.enabled = enabled; - } - }); +const createStyler = (open, close, parent) => { + let openAll; + let closeAll; + if (parent === undefined) { + openAll = open; + closeAll = close; + } else { + openAll = parent.openAll + open; + closeAll = close + parent.closeAll; + } - // See below for fix regarding invisible grey/dim combination on Windows - builder.hasGrey = this.hasGrey || key === 'gray' || key === 'grey'; + return { + open, + close, + openAll, + closeAll, + parent + }; +}; + +const createBuilder = (self, _styler, _isEmpty) => { + const builder = (...arguments_) => { + // Single argument is hot path, implicit coercion is faster than anything + // eslint-disable-next-line no-implicit-coercion + return applyStyle(builder, (arguments_.length === 1) ? ('' + arguments_[0]) : arguments_.join(' ')); + }; // `__proto__` is used because we must return a function, but there is // no way to create a function with a different prototype - builder.__proto__ = proto; // eslint-disable-line no-proto + builder.__proto__ = proto$3; // eslint-disable-line no-proto - return builder; -} + builder._generator = self; + builder._styler = _styler; + builder._isEmpty = _isEmpty; -function applyStyle() { - // Support varags, but simply cast to string in case there's only one arg - const args = arguments; - const argsLen = args.length; - let str = String(arguments[0]); + return builder; +}; - if (argsLen === 0) { - return ''; +const applyStyle = (self, string) => { + if (self.level <= 0 || !string) { + return self._isEmpty ? '' : string; } - if (argsLen > 1) { - // Don't slice `arguments`, it prevents V8 optimizations - for (let a = 1; a < argsLen; a++) { - str += ' ' + args[a]; - } - } + let styler = self._styler; - if (!this.enabled || this.level <= 0 || !str) { - return this._empty ? '' : str; + if (styler === undefined) { + return string; } - // Turns out that on Windows dimmed gray text becomes invisible in cmd.exe, - // see https://github.com/chalk/chalk/issues/58 - // If we're on Windows and we're dealing with a gray color, temporarily make 'dim' a noop. - const originalDim = ansiStyles.dim.open; - if (isSimpleWindowsTerm && this.hasGrey) { - ansiStyles.dim.open = ''; - } + const {openAll, closeAll} = styler; + if (string.indexOf('\u001B') !== -1) { + while (styler !== undefined) { + // Replace any instances already present with a re-opening code + // otherwise only the part of the string until said closing code + // will be colored, and the rest will simply be 'plain'. + string = stringReplaceAll$1(string, styler.close, styler.open); - for (const code of this._styles.slice().reverse()) { - // Replace any instances already present with a re-opening code - // otherwise only the part of the string until said closing code - // will be colored, and the rest will simply be 'plain'. - str = code.open + str.replace(code.closeRe, code.open) + code.close; + styler = styler.parent; + } + } - // Close the styling before a linebreak and reopen - // after next line to fix a bleed issue on macOS - // https://github.com/chalk/chalk/pull/92 - str = str.replace(/\r?\n/g, `${code.close}$&${code.open}`); + // We can move both next actions out of loop, because remaining actions in loop won't have + // any/visible effect on parts we add here. Close the styling before a linebreak and reopen + // after next line to fix a bleed issue on macOS: https://github.com/chalk/chalk/pull/92 + const lfIndex = string.indexOf('\n'); + if (lfIndex !== -1) { + string = stringEncaseCRLFWithFirstIndex$1(string, closeAll, openAll, lfIndex); } - // Reset the original `dim` if we changed it to work around the Windows dimmed gray issue - ansiStyles.dim.open = originalDim; + return openAll + string + closeAll; +}; - return str; -} +let template; +const chalkTag = (chalk, ...strings) => { + const [firstString] = strings; -function chalkTag(chalk, strings) { - if (!Array.isArray(strings)) { + if (!Array.isArray(firstString)) { // If chalk() was called by itself or with a string, // return the string itself as a string. - return [].slice.call(arguments, 1).join(' '); + return strings.join(' '); } - const args = [].slice.call(arguments, 2); - const parts = [strings.raw[0]]; + const arguments_ = strings.slice(1); + const parts = [firstString.raw[0]]; - for (let i = 1; i < strings.length; i++) { - parts.push(String(args[i - 1]).replace(/[{}\\]/g, '\\$&')); - parts.push(String(strings.raw[i])); + for (let i = 1; i < firstString.length; i++) { + parts.push( + String(arguments_[i - 1]).replace(/[{}\\]/g, '\\$&'), + String(firstString.raw[i]) + ); } - return templates(chalk, parts.join('')); -} + if (template === undefined) { + template = templates$1; + } + + return template(chalk, parts.join('')); +}; Object.defineProperties(Chalk.prototype, styles); -module.exports = Chalk(); // eslint-disable-line new-cap -module.exports.supportsColor = stdoutColor; -module.exports.default = module.exports; // For TypeScript -}); -var chalk_1 = chalk.supportsColor; +const chalk$1 = Chalk(); // eslint-disable-line new-cap +chalk$1.supportsColor = stdoutColor; +chalk$1.stderr = Chalk({level: stderrColor ? stderrColor.level : 0}); // eslint-disable-line new-cap +chalk$1.stderr.supportsColor = stderrColor; + +// For TypeScript +chalk$1.Level = { + None: 0, + Basic: 1, + Ansi256: 2, + TrueColor: 3, + 0: 'None', + 1: 'Basic', + 2: 'Ansi256', + 3: 'TrueColor' +}; + +var source = chalk$1; const WIN_SLASH = '\\\\/'; const WIN_NO_SLASH = `[^${WIN_SLASH}]`; @@ -16349,7 +18651,7 @@ var constants = { } }; -var utils$1 = createCommonjsModule(function (module, exports) { +var utils = createCommonjsModule(function (module, exports) { const win32 = process.platform === 'win32'; @@ -16414,17 +18716,17 @@ exports.wrapOutput = (input, state = {}, options = {}) => { return output; }; }); -var utils_1$1 = utils$1.isObject; -var utils_2$1 = utils$1.hasRegexChars; -var utils_3$1 = utils$1.isRegexChar; -var utils_4$1 = utils$1.escapeRegex; -var utils_5$1 = utils$1.toPosixSlashes; -var utils_6 = utils$1.removeBackslashes; -var utils_7 = utils$1.supportsLookbehinds; -var utils_8 = utils$1.isWindows; -var utils_9 = utils$1.escapeLast; -var utils_10 = utils$1.removePrefix; -var utils_11 = utils$1.wrapOutput; +var utils_1 = utils.isObject; +var utils_2 = utils.hasRegexChars; +var utils_3 = utils.isRegexChar; +var utils_4 = utils.escapeRegex; +var utils_5 = utils.toPosixSlashes; +var utils_6 = utils.removeBackslashes; +var utils_7 = utils.supportsLookbehinds; +var utils_8 = utils.isWindows; +var utils_9 = utils.escapeLast; +var utils_10 = utils.removePrefix; +var utils_11 = utils.wrapOutput; const { CHAR_ASTERISK: CHAR_ASTERISK$1, /* * */ @@ -16672,23 +18974,24 @@ const scan$1 = (input, options) => { } if (opts.noparen !== true && code === CHAR_LEFT_PARENTHESES) { - while (eos() !== true && (code = advance())) { - if (code === CHAR_BACKWARD_SLASH) { - backslashes = token.backslashes = true; - code = advance(); - continue; - } - - if (code === CHAR_RIGHT_PARENTHESES) { - isGlob = token.isGlob = true; - finished = true; + isGlob = token.isGlob = true; - if (scanToEnd === true) { + if (scanToEnd === true) { + while (eos() !== true && (code = advance())) { + if (code === CHAR_LEFT_PARENTHESES) { + backslashes = token.backslashes = true; + code = advance(); continue; } - break; + + if (code === CHAR_RIGHT_PARENTHESES) { + finished = true; + break; + } } + continue; } + break; } if (isGlob === true) { @@ -16734,10 +19037,10 @@ const scan$1 = (input, options) => { } if (opts.unescape === true) { - if (glob) glob = utils$1.removeBackslashes(glob); + if (glob) glob = utils.removeBackslashes(glob); if (base && backslashes === true) { - base = utils$1.removeBackslashes(base); + base = utils.removeBackslashes(base); } } @@ -16834,7 +19137,7 @@ const expandRange = (args, options) => { /* eslint-disable-next-line no-new */ new RegExp(value); } catch (ex) { - return args.map(v => utils$1.escapeRegex(v)).join('..'); + return args.map(v => utils.escapeRegex(v)).join('..'); } return value; @@ -16874,7 +19177,7 @@ const parse$5 = (input, options) => { const tokens = [bos]; const capture = opts.capture ? '' : '?:'; - const win32 = utils$1.isWindows(options); + const win32 = utils.isWindows(options); // create constants based on platform, for windows or posix const PLATFORM_CHARS = constants.globChars(win32); @@ -16930,7 +19233,7 @@ const parse$5 = (input, options) => { tokens }; - input = utils$1.removePrefix(input, state); + input = utils.removePrefix(input, state); len = input.length; const extglobs = []; @@ -17031,8 +19334,6 @@ const parse$5 = (input, options) => { const output = (opts.capture ? '(' : '') + token.open; increment('parens'); - - push({ type, value, output: state.output ? '' : ONE_CHAR }); push({ type: 'paren', extglob: true, value: advance(), output }); extglobs.push(token); @@ -17112,7 +19413,7 @@ const parse$5 = (input, options) => { return state; } - state.output = utils$1.wrapOutput(output, state, options); + state.output = utils.wrapOutput(output, state, options); return state; } @@ -17225,7 +19526,7 @@ const parse$5 = (input, options) => { */ if (state.quotes === 1 && value !== '"') { - value = utils$1.escapeRegex(value); + value = utils.escapeRegex(value); prev.value += value; append({ value }); continue; @@ -17315,11 +19616,11 @@ const parse$5 = (input, options) => { // when literal brackets are explicitly disabled // assume we should match with a regex character class - if (opts.literalBrackets === false || utils$1.hasRegexChars(prevValue)) { + if (opts.literalBrackets === false || utils.hasRegexChars(prevValue)) { continue; } - const escaped = utils$1.escapeRegex(prev.value); + const escaped = utils.escapeRegex(prev.value); state.output = state.output.slice(0, -prev.value.length); // when literal brackets are explicitly enabled @@ -17388,7 +19689,7 @@ const parse$5 = (input, options) => { const out = state.output.slice(0, brace.outputIndex); const toks = state.tokens.slice(brace.tokensIndex); brace.value = brace.output = '\\{'; - value = output = `\\}`; + value = output = '\\}'; state.output = out; for (const t of toks) { state.output += (t.output || t.value); @@ -17491,7 +19792,7 @@ const parse$5 = (input, options) => { const next = peek(); let output = value; - if (next === '<' && !utils$1.supportsLookbehinds()) { + if (next === '<' && !utils.supportsLookbehinds()) { throw new Error('Node.js v10 or higher is required for regex lookbehinds'); } @@ -17751,19 +20052,19 @@ const parse$5 = (input, options) => { while (state.brackets > 0) { if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', ']')); - state.output = utils$1.escapeLast(state.output, '['); + state.output = utils.escapeLast(state.output, '['); decrement('brackets'); } while (state.parens > 0) { if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', ')')); - state.output = utils$1.escapeLast(state.output, '('); + state.output = utils.escapeLast(state.output, '('); decrement('parens'); } while (state.braces > 0) { if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', '}')); - state.output = utils$1.escapeLast(state.output, '{'); + state.output = utils.escapeLast(state.output, '{'); decrement('braces'); } @@ -17802,7 +20103,7 @@ parse$5.fastpaths = (input, options) => { } input = REPLACEMENTS[input] || input; - const win32 = utils$1.isWindows(options); + const win32 = utils.isWindows(options); // create constants based on platform, for windows or posix const { @@ -17870,7 +20171,7 @@ parse$5.fastpaths = (input, options) => { } }; - const output = utils$1.removePrefix(input, state); + const output = utils.removePrefix(input, state); let source = create(output); if (source && opts.strictSlashes !== true) { @@ -17882,7 +20183,7 @@ parse$5.fastpaths = (input, options) => { var parse_1$1 = parse$5; -const isObject$2 = val => val && typeof val === 'object' && !Array.isArray(val); +const isObject$1 = val => val && typeof val === 'object' && !Array.isArray(val); /** * Creates a matcher function from one or more glob patterns. The @@ -17919,14 +20220,14 @@ const picomatch = (glob, options, returnState = false) => { return arrayMatcher; } - const isState = isObject$2(glob) && glob.tokens && glob.input; + const isState = isObject$1(glob) && glob.tokens && glob.input; if (glob === '' || (typeof glob !== 'string' && !isState)) { throw new TypeError('Expected pattern to be a non-empty string'); } const opts = options || {}; - const posix = utils$1.isWindows(options); + const posix = utils.isWindows(options); const regex = isState ? picomatch.compileRe(glob, options) : picomatch.makeRe(glob, options, false, true); @@ -18001,7 +20302,7 @@ picomatch.test = (input, regex, options, { glob, posix } = {}) => { } const opts = options || {}; - const format = opts.format || (posix ? utils$1.toPosixSlashes : null); + const format = opts.format || (posix ? utils.toPosixSlashes : null); let match = input === glob; let output = (match && format) ? format(input) : input; @@ -18035,7 +20336,7 @@ picomatch.test = (input, regex, options, { glob, posix } = {}) => { * @api public */ -picomatch.matchBase = (input, glob, options, posix = utils$1.isWindows(options)) => { +picomatch.matchBase = (input, glob, options, posix = utils.isWindows(options)) => { const regex = glob instanceof RegExp ? glob : picomatch.makeRe(glob, options); return regex.test(path$1.basename(input)); }; @@ -18108,16 +20409,17 @@ picomatch.parse = (pattern, options) => { picomatch.scan = (input, options) => scan_1(input, options); /** - * Create a regular expression from a glob pattern. + * Create a regular expression from a parsed glob pattern. * * ```js * const picomatch = require('picomatch'); - * // picomatch.makeRe(input[, options]); + * const state = picomatch.parse('*.js'); + * // picomatch.compileRe(state[, options]); * - * console.log(picomatch.makeRe('*.js')); + * console.log(picomatch.compileRe(state)); * //=> /^(?:(?!\.)(?=.)[^/]*?\.js)$/ * ``` - * @param {String} `input` A glob pattern to convert to regex. + * @param {String} `state` The object returned from the `.parse` method. * @param {Object} `options` * @return {RegExp} Returns a regex created from the given pattern. * @api public @@ -18218,12 +20520,13 @@ var picomatch$1 = picomatch_1; const { Readable } = stream; -const { promisify } = util$1; +const { promisify } = util$2; const readdir$1 = promisify(fs$1.readdir); const stat$2 = promisify(fs$1.stat); const lstat = promisify(fs$1.lstat); +const realpath$2 = promisify(fs$1.realpath); /** * @typedef {Object} EntryInfo @@ -18321,11 +20624,7 @@ class ReaddirpStream extends Readable { this._rdOptions = { encoding: 'utf8', withFileTypes: this._isDirent }; // Launch stream with one parent, the root dir. - try { - this.parents = [this._exploreDir(root, 1)]; - } catch (error) { - this.destroy(error); - } + this.parents = [this._exploreDir(root, 1)]; this.reading = false; this.parent = undefined; } @@ -18341,7 +20640,10 @@ class ReaddirpStream extends Readable { if (files.length > 0) { const slice = files.splice(0, batch).map(dirent => this._formatEntry(dirent, path)); for (const entry of await Promise.all(slice)) { - if (this._isDirAndMatchesFilter(entry)) { + if (this.destroyed) return; + + const entryType = await this._getEntryType(entry); + if (entryType === 'directory' && this._directoryFilter(entry)) { if (depth <= this._maxDepth) { this.parents.push(this._exploreDir(entry.fullPath, depth + 1)); } @@ -18350,7 +20652,7 @@ class ReaddirpStream extends Readable { this.push(entry); batch--; } - } else if (this._isFileAndMatchesFilter(entry)) { + } else if ((entryType === 'file' || this._includeAsFile(entry)) && this._fileFilter(entry)) { if (this._wantsFile) { this.push(entry); batch--; @@ -18364,6 +20666,7 @@ class ReaddirpStream extends Readable { break; } this.parent = await parent; + if (this.destroyed) return; } } } catch (error) { @@ -18384,10 +20687,11 @@ class ReaddirpStream extends Readable { } async _formatEntry(dirent, path) { - const basename = this._isDirent ? dirent.name : dirent; - const fullPath = path$1.resolve(path$1.join(path, basename)); - const entry = {path: path$1.relative(this._root, fullPath), fullPath, basename}; + let entry; try { + const basename = this._isDirent ? dirent.name : dirent; + const fullPath = path$1.resolve(path$1.join(path, basename)); + entry = {path: path$1.relative(this._root, fullPath), fullPath, basename}; entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath); } catch (err) { this._onError(err); @@ -18399,24 +20703,43 @@ class ReaddirpStream extends Readable { if (isNormalFlowError(err) && !this.destroyed) { this.emit('warn', err); } else { - throw err; + this.destroy(err); } } - _isDirAndMatchesFilter(entry) { + async _getEntryType(entry) { // entry may be undefined, because a warning or an error were emitted // and the statsProp is undefined const stats = entry && entry[this._statsProp]; - return stats && stats.isDirectory() && this._directoryFilter(entry); + if (!stats) { + return; + } + if (stats.isFile()) { + return 'file'; + } + if (stats.isDirectory()) { + return 'directory'; + } + if (stats && stats.isSymbolicLink()) { + try { + const entryRealPath = await realpath$2(entry.fullPath); + const entryRealPathStats = await lstat(entryRealPath); + if (entryRealPathStats.isFile()) { + return 'file'; + } + if (entryRealPathStats.isDirectory()) { + return 'directory'; + } + } catch (error) { + this._onError(error); + } + } } - _isFileAndMatchesFilter(entry) { + _includeAsFile(entry) { const stats = entry && entry[this._statsProp]; - const isFileType = stats && ( - (this._wantsEverything && !stats.isDirectory()) || - (stats.isFile() || stats.isSymbolicLink()) - ); - return isFileType && this._fileFilter(entry); + + return stats && this._wantsEverything && !stats.isDirectory(); } } @@ -18687,7 +21010,7 @@ var slash = '/'; var backslash = /\\/g; var enclosure = /[\{\[].*[\/]*.*[\}\]]$/; var globby = /(^|[^\\])([\{\[]|\([^\)]+$)/; -var escaped = /\\([\*\?\|\[\]\(\)\{\}])/g; +var escaped = /\\([\!\*\?\|\[\]\(\)\{\}])/g; /** * @param {string} str @@ -18719,7 +21042,7 @@ var globParent = function globParent(str, opts) { return str.replace(escaped, '$1'); }; -var utils$2 = createCommonjsModule(function (module, exports) { +var utils$1 = createCommonjsModule(function (module, exports) { exports.isInteger = num => { if (typeof num === 'number') { @@ -18832,24 +21155,24 @@ exports.flatten = (...args) => { return result; }; }); -var utils_1$2 = utils$2.isInteger; -var utils_2$2 = utils$2.find; -var utils_3$2 = utils$2.exceedsLimit; -var utils_4$2 = utils$2.escapeNode; -var utils_5$2 = utils$2.encloseBrace; -var utils_6$1 = utils$2.isInvalidBrace; -var utils_7$1 = utils$2.isOpenOrClose; -var utils_8$1 = utils$2.reduce; -var utils_9$1 = utils$2.flatten; +var utils_1$1 = utils$1.isInteger; +var utils_2$1 = utils$1.find; +var utils_3$1 = utils$1.exceedsLimit; +var utils_4$1 = utils$1.escapeNode; +var utils_5$1 = utils$1.encloseBrace; +var utils_6$1 = utils$1.isInvalidBrace; +var utils_7$1 = utils$1.isOpenOrClose; +var utils_8$1 = utils$1.reduce; +var utils_9$1 = utils$1.flatten; var stringify$3 = (ast, options = {}) => { let stringify = (node, parent = {}) => { - let invalidBlock = options.escapeInvalid && utils$2.isInvalidBrace(parent); + let invalidBlock = options.escapeInvalid && utils$1.isInvalidBrace(parent); let invalidNode = node.invalid === true && options.escapeInvalid === true; let output = ''; if (node.value) { - if ((invalidBlock || invalidNode) && utils$2.isOpenOrClose(node)) { + if ((invalidBlock || invalidNode) && utils$1.isOpenOrClose(node)) { return '\\' + node.value; } return node.value; @@ -18877,7 +21200,7 @@ var stringify$3 = (ast, options = {}) => { * Released under the MIT License. */ -var isNumber$1 = function(num) { +var isNumber = function(num) { if (typeof num === 'number') { return num - num === 0; } @@ -18888,7 +21211,7 @@ var isNumber$1 = function(num) { }; const toRegexRange = (min, max, options) => { - if (isNumber$1(min) === false) { + if (isNumber(min) === false) { throw new TypeError('toRegexRange: expected the first argument to be a number'); } @@ -18896,7 +21219,7 @@ const toRegexRange = (min, max, options) => { return String(min); } - if (isNumber$1(max) === false) { + if (isNumber(max) === false) { throw new TypeError('toRegexRange: expected the second argument to be a number.'); } @@ -19165,7 +21488,7 @@ toRegexRange.clearCache = () => (toRegexRange.cache = {}); var toRegexRange_1 = toRegexRange; -const isObject$3 = val => val !== null && typeof val === 'object' && !Array.isArray(val); +const isObject$2 = val => val !== null && typeof val === 'object' && !Array.isArray(val); const transform$2 = toNumber => { return value => toNumber === true ? Number(value) : String(value); @@ -19175,7 +21498,7 @@ const isValidValue = value => { return typeof value === 'number' || (typeof value === 'string' && value !== ''); }; -const isNumber$2 = num => Number.isInteger(+num); +const isNumber$1 = num => Number.isInteger(+num); const zeros = input => { let value = `${input}`; @@ -19267,7 +21590,7 @@ const toRegex = (start, end, options) => { }; const rangeError = (...args) => { - return new RangeError('Invalid range arguments: ' + util$1.inspect(...args)); + return new RangeError('Invalid range arguments: ' + util$2.inspect(...args)); }; const invalidRange = (start, end, options) => { @@ -19335,7 +21658,7 @@ const fillNumbers = (start, end, step = 1, options = {}) => { }; const fillLetters = (start, end, step = 1, options = {}) => { - if ((!isNumber$2(start) && start.length > 1) || (!isNumber$2(end) && end.length > 1)) { + if ((!isNumber$1(start) && start.length > 1) || (!isNumber$1(end) && end.length > 1)) { return invalidRange(start, end, options); } @@ -19381,7 +21704,7 @@ const fill = (start, end, step, options = {}) => { return fill(start, end, 1, { transform: step }); } - if (isObject$3(step)) { + if (isObject$2(step)) { return fill(start, end, 0, step); } @@ -19389,12 +21712,12 @@ const fill = (start, end, step, options = {}) => { if (opts.capture === true) opts.wrap = true; step = step || opts.step || 1; - if (!isNumber$2(step)) { - if (step != null && !isObject$3(step)) return invalidStep(step, opts); + if (!isNumber$1(step)) { + if (step != null && !isObject$2(step)) return invalidStep(step, opts); return fill(start, end, 1, step); } - if (isNumber$2(start) && isNumber$2(end)) { + if (isNumber$1(start) && isNumber$1(end)) { return fillNumbers(start, end, step, opts); } @@ -19405,7 +21728,7 @@ var fillRange = fill; const compile$2 = (ast, options = {}) => { let walk = (node, parent = {}) => { - let invalidBlock = utils$2.isInvalidBrace(parent); + let invalidBlock = utils$1.isInvalidBrace(parent); let invalidNode = node.invalid === true && options.escapeInvalid === true; let invalid = invalidBlock === true || invalidNode === true; let prefix = options.escapeInvalid === true ? '\\' : ''; @@ -19435,7 +21758,7 @@ const compile$2 = (ast, options = {}) => { } if (node.nodes && node.ranges > 0) { - let args = utils$2.reduce(node.nodes); + let args = utils$1.reduce(node.nodes); let range = fillRange(...args, { ...options, wrap: false, toRegex: true }); if (range.length !== 0) { @@ -19464,7 +21787,7 @@ const append = (queue = '', stash = '', enclose = false) => { if (!stash.length) return queue; if (!queue.length) { - return enclose ? utils$2.flatten(stash).map(ele => `{${ele}}`) : stash; + return enclose ? utils$1.flatten(stash).map(ele => `{${ele}}`) : stash; } for (let item of queue) { @@ -19479,7 +21802,7 @@ const append = (queue = '', stash = '', enclose = false) => { } } } - return utils$2.flatten(result); + return utils$1.flatten(result); }; const expand$2 = (ast, options = {}) => { @@ -19507,9 +21830,9 @@ const expand$2 = (ast, options = {}) => { } if (node.nodes && node.ranges > 0) { - let args = utils$2.reduce(node.nodes); + let args = utils$1.reduce(node.nodes); - if (utils$2.exceedsLimit(...args, options.step, rangeLimit)) { + if (utils$1.exceedsLimit(...args, options.step, rangeLimit)) { throw new RangeError('expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.'); } @@ -19523,7 +21846,7 @@ const expand$2 = (ast, options = {}) => { return; } - let enclose = utils$2.encloseBrace(node); + let enclose = utils$1.encloseBrace(node); let queue = node.queue; let block = node; @@ -19559,7 +21882,7 @@ const expand$2 = (ast, options = {}) => { return queue; }; - return utils$2.flatten(walk(ast)); + return utils$1.flatten(walk(ast)); }; var expand_1 = expand$2; @@ -20369,9 +22692,9 @@ var binaryExtensions$1 = /*#__PURE__*/Object.freeze({ 'default': binaryExtensions }); -var require$$0 = getCjsExportFromNamespace(binaryExtensions$1); +var require$$0$1 = getCjsExportFromNamespace(binaryExtensions$1); -var binaryExtensions$2 = require$$0; +var binaryExtensions$2 = require$$0$1; const extensions = new Set(binaryExtensions$2); @@ -20402,6 +22725,7 @@ exports.FSEVENT_DELETED = 'deleted'; exports.FSEVENT_MOVED = 'moved'; exports.FSEVENT_CLONED = 'cloned'; exports.FSEVENT_UNKNOWN = 'unknown'; +exports.FSEVENT_TYPE_FILE = 'file'; exports.FSEVENT_TYPE_DIRECTORY = 'directory'; exports.FSEVENT_TYPE_SYMLINK = 'symlink'; @@ -20456,38 +22780,39 @@ var constants_15 = constants$2.FSEVENT_DELETED; var constants_16 = constants$2.FSEVENT_MOVED; var constants_17 = constants$2.FSEVENT_CLONED; var constants_18 = constants$2.FSEVENT_UNKNOWN; -var constants_19 = constants$2.FSEVENT_TYPE_DIRECTORY; -var constants_20 = constants$2.FSEVENT_TYPE_SYMLINK; -var constants_21 = constants$2.KEY_LISTENERS; -var constants_22 = constants$2.KEY_ERR; -var constants_23 = constants$2.KEY_RAW; -var constants_24 = constants$2.HANDLER_KEYS; -var constants_25 = constants$2.DOT_SLASH; -var constants_26 = constants$2.BACK_SLASH_RE; -var constants_27 = constants$2.DOUBLE_SLASH_RE; -var constants_28 = constants$2.SLASH_OR_BACK_SLASH_RE; -var constants_29 = constants$2.DOT_RE; -var constants_30 = constants$2.REPLACER_RE; -var constants_31 = constants$2.SLASH; -var constants_32 = constants$2.BRACE_START; -var constants_33 = constants$2.BANG; -var constants_34 = constants$2.ONE_DOT; -var constants_35 = constants$2.TWO_DOTS; -var constants_36 = constants$2.STAR; -var constants_37 = constants$2.GLOBSTAR; -var constants_38 = constants$2.ROOT_GLOBSTAR; -var constants_39 = constants$2.SLASH_GLOBSTAR; -var constants_40 = constants$2.DIR_SUFFIX; -var constants_41 = constants$2.ANYMATCH_OPTS; -var constants_42 = constants$2.STRING_TYPE; -var constants_43 = constants$2.FUNCTION_TYPE; -var constants_44 = constants$2.EMPTY_STR; -var constants_45 = constants$2.EMPTY_FN; -var constants_46 = constants$2.IDENTITY_FN; -var constants_47 = constants$2.isWindows; -var constants_48 = constants$2.isMacos; - -const { promisify: promisify$1 } = util$1; +var constants_19 = constants$2.FSEVENT_TYPE_FILE; +var constants_20 = constants$2.FSEVENT_TYPE_DIRECTORY; +var constants_21 = constants$2.FSEVENT_TYPE_SYMLINK; +var constants_22 = constants$2.KEY_LISTENERS; +var constants_23 = constants$2.KEY_ERR; +var constants_24 = constants$2.KEY_RAW; +var constants_25 = constants$2.HANDLER_KEYS; +var constants_26 = constants$2.DOT_SLASH; +var constants_27 = constants$2.BACK_SLASH_RE; +var constants_28 = constants$2.DOUBLE_SLASH_RE; +var constants_29 = constants$2.SLASH_OR_BACK_SLASH_RE; +var constants_30 = constants$2.DOT_RE; +var constants_31 = constants$2.REPLACER_RE; +var constants_32 = constants$2.SLASH; +var constants_33 = constants$2.BRACE_START; +var constants_34 = constants$2.BANG; +var constants_35 = constants$2.ONE_DOT; +var constants_36 = constants$2.TWO_DOTS; +var constants_37 = constants$2.STAR; +var constants_38 = constants$2.GLOBSTAR; +var constants_39 = constants$2.ROOT_GLOBSTAR; +var constants_40 = constants$2.SLASH_GLOBSTAR; +var constants_41 = constants$2.DIR_SUFFIX; +var constants_42 = constants$2.ANYMATCH_OPTS; +var constants_43 = constants$2.STRING_TYPE; +var constants_44 = constants$2.FUNCTION_TYPE; +var constants_45 = constants$2.EMPTY_STR; +var constants_46 = constants$2.EMPTY_FN; +var constants_47 = constants$2.IDENTITY_FN; +var constants_48 = constants$2.isWindows; +var constants_49 = constants$2.isMacos; + +const { promisify: promisify$1 } = util$2; const { isWindows: isWindows$1, @@ -21121,7 +23446,7 @@ async _addToNodeFs(path, initialAdd, priorWh, depth, target) { var nodefsHandler = NodeFsHandler; -const { promisify: promisify$2 } = util$1; +const { promisify: promisify$2 } = util$2; let fsevents; try { @@ -21156,6 +23481,7 @@ const { FSEVENT_MOVED, // FSEVENT_CLONED, FSEVENT_UNKNOWN, + FSEVENT_TYPE_FILE, FSEVENT_TYPE_DIRECTORY, FSEVENT_TYPE_SYMLINK, @@ -21166,15 +23492,12 @@ const { EMPTY_FN: EMPTY_FN$1, IDENTITY_FN } = constants$2; -const FS_MODE_READ = 'r'; const Depth = (value) => isNaN(value) ? {} : {depth: value}; const stat$4 = promisify$2(fs$1.stat); -const open$1 = promisify$2(fs$1.open); -const close$1 = promisify$2(fs$1.close); const lstat$2 = promisify$2(fs$1.lstat); -const realpath$2 = promisify$2(fs$1.realpath); +const realpath$3 = promisify$2(fs$1.realpath); const statMethods$1 = { stat: stat$4, lstat: lstat$2 }; @@ -21321,6 +23644,14 @@ const calcDepth = (path, root) => { return i; }; +// returns boolean indicating whether the fsevents' event info has the same type +// as the one returned by fs.stat +const sameTypes = (info, stats) => ( + info.type === FSEVENT_TYPE_DIRECTORY && stats.isDirectory() || + info.type === FSEVENT_TYPE_SYMLINK && stats.isSymbolicLink() || + info.type === FSEVENT_TYPE_FILE && stats.isFile() +); + /** * @mixin */ @@ -21351,13 +23682,16 @@ addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts) { this.handleEvent(event, path, fullPath, realPath, parent, watchedDir, item, info, opts); } -async checkFd(path, fullPath, realPath, parent, watchedDir, item, info, opts) { +async checkExists(path, fullPath, realPath, parent, watchedDir, item, info, opts) { try { - const fd = await open$1(path, FS_MODE_READ); + const stats = await stat$4(path); if (this.fsw.closed) return; - await close$1(fd); if (this.fsw.closed) return; - this.addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts); + if (sameTypes(info, stats)) { + this.addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts); + } else { + this.handleEvent(EV_UNLINK, path, fullPath, realPath, parent, watchedDir, item, info, opts); + } } catch (error) { if (error.code === 'EACCES') { this.addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts); @@ -21371,9 +23705,10 @@ handleEvent(event, path, fullPath, realPath, parent, watchedDir, item, info, opt if (this.fsw.closed || this.checkIgnored(path)) return; if (event === EV_UNLINK) { + const isDirectory = info.type === FSEVENT_TYPE_DIRECTORY; // suppress unlink events on never before seen files - if (info.type === FSEVENT_TYPE_DIRECTORY || watchedDir.has(item)) { - this.fsw._remove(parent, item); + if (isDirectory || watchedDir.has(item)) { + this.fsw._remove(parent, item, isDirectory); } } else { if (event === EV_ADD$1) { @@ -21438,13 +23773,13 @@ _watchWithFsEvents(watchPath, realPath, transform, globFilter) { } catch (error) {} if (this.fsw.closed) return; if (this.checkIgnored(path, stats)) return; - if (stats) { + if (sameTypes(info, stats)) { this.addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts); } else { this.handleEvent(EV_UNLINK, path, fullPath, realPath, parent, watchedDir, item, info, opts); } } else { - this.checkFd(path, fullPath, realPath, parent, watchedDir, item, info, opts); + this.checkExists(path, fullPath, realPath, parent, watchedDir, item, info, opts); } } else { switch (info.event) { @@ -21453,7 +23788,7 @@ _watchWithFsEvents(watchPath, realPath, transform, globFilter) { return this.addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts); case FSEVENT_DELETED: case FSEVENT_MOVED: - return this.checkFd(path, fullPath, realPath, parent, watchedDir, item, info, opts); + return this.checkExists(path, fullPath, realPath, parent, watchedDir, item, info, opts); } } }; @@ -21486,7 +23821,7 @@ async _handleFsEventsSymlink(linkPath, fullPath, transform, curDepth) { this.fsw._incrReadyCount(); try { - const linkTarget = await realpath$2(linkPath); + const linkTarget = await realpath$3(linkPath); if (this.fsw.closed) return; if (this.fsw._isIgnored(linkTarget)) { return this.fsw._emitReady(); @@ -21622,7 +23957,7 @@ async _addToFsEvents(path, transform, forceAdd, priorDepth) { } else { let realPath; try { - realPath = await realpath$2(wh.watchPath); + realPath = await realpath$3(wh.watchPath); } catch (e) {} this.initWatch(realPath, path, wh, processPath); } @@ -21638,7 +23973,7 @@ fseventsHandler.canUse = canUse_1; const { EventEmitter } = events; -const { promisify: promisify$3 } = util$1; +const { promisify: promisify$3 } = util$2; const anymatch = anymatch_1.default; @@ -21787,12 +24122,13 @@ class DirEntry { const {items} = this; if (!items) return; items.delete(item); + if (items.size > 0) return; - if (!items.size) { - const dir = this.path; - try { - await readdir$2(dir); - } catch (err) { + const dir = this.path; + try { + await readdir$2(dir); + } catch (err) { + if (this._removeWatcher) { this._removeWatcher(path$1.dirname(dir), path$1.basename(dir)); } } @@ -22118,7 +24454,7 @@ unwatch(paths_) { * @returns {Promise}. */ close() { - if (this.closed) return this; + if (this.closed) return this._closePromise; this.closed = true; // Memory management. @@ -22136,7 +24472,9 @@ close() { ['closers', 'watched', 'streams', 'symlinkPaths', 'throttled'].forEach(key => { this[`_${key}`].clear(); }); - return closers.length ? Promise.all(closers).then(() => undefined) : Promise.resolve(); + + this._closePromise = closers.length ? Promise.all(closers).then(() => undefined) : Promise.resolve(); + return this._closePromise; } /** @@ -22237,16 +24575,15 @@ async _emit(event, path, val1, val2, val3) { (event === EV_ADD$2 || event === EV_ADD_DIR$2 || event === EV_CHANGE$2) ) { const fullPath = opts.cwd ? path$1.join(opts.cwd, path) : path; + let stats; try { - const stats = await stat$5(fullPath); - // Suppress event when fs_stat fails, to avoid sending undefined 'stat' - if (!stats) return; - args.push(stats); - this.emitWithAll(event, args); + stats = await stat$5(fullPath); } catch (err) {} - } else { - this.emitWithAll(event, args); + // Suppress event when fs_stat fails, to avoid sending undefined 'stat' + if (!stats || this.closed) return; + args.push(stats); } + this.emitWithAll(event, args); return this; } @@ -22455,13 +24792,15 @@ _hasReadPermissions(stats) { * @param {String} item base path of item/directory * @returns {void} */ -_remove(directory, item) { +_remove(directory, item, isDirectory) { // if what is being deleted is a directory, get that directory's paths // for recursive deleting and cleaning of watched object // if it is not a directory, nestedDirectoryChildren will be empty array const path = path$1.join(directory, item); const fullPath = path$1.resolve(path); - const isDirectory = this._watched.has(path) || this._watched.has(fullPath); + isDirectory = isDirectory != null + ? isDirectory + : this._watched.has(path) || this._watched.has(fullPath); // prevent duplicate handling in case of arriving here nearly simultaneously // via multiple paths (such as _handleFile and _handleDir) @@ -22735,8 +25074,253 @@ const camelCase = (input, options) => { var camelcase = camelCase; // TODO: Remove this for the next major release -var default_1$2 = camelCase; -camelcase.default = default_1$2; +var default_1$4 = camelCase; +camelcase.default = default_1$4; + +var minimist = function (args, opts) { + if (!opts) opts = {}; + + var flags = { bools : {}, strings : {}, unknownFn: null }; + + if (typeof opts['unknown'] === 'function') { + flags.unknownFn = opts['unknown']; + } + + if (typeof opts['boolean'] === 'boolean' && opts['boolean']) { + flags.allBools = true; + } else { + [].concat(opts['boolean']).filter(Boolean).forEach(function (key) { + flags.bools[key] = true; + }); + } + + var aliases = {}; + Object.keys(opts.alias || {}).forEach(function (key) { + aliases[key] = [].concat(opts.alias[key]); + aliases[key].forEach(function (x) { + aliases[x] = [key].concat(aliases[key].filter(function (y) { + return x !== y; + })); + }); + }); + + [].concat(opts.string).filter(Boolean).forEach(function (key) { + flags.strings[key] = true; + if (aliases[key]) { + flags.strings[aliases[key]] = true; + } + }); + + var defaults = opts['default'] || {}; + + var argv = { _ : [] }; + Object.keys(flags.bools).forEach(function (key) { + setArg(key, defaults[key] === undefined ? false : defaults[key]); + }); + + var notFlags = []; + + if (args.indexOf('--') !== -1) { + notFlags = args.slice(args.indexOf('--')+1); + args = args.slice(0, args.indexOf('--')); + } + + function argDefined(key, arg) { + return (flags.allBools && /^--[^=]+$/.test(arg)) || + flags.strings[key] || flags.bools[key] || aliases[key]; + } + + function setArg (key, val, arg) { + if (arg && flags.unknownFn && !argDefined(key, arg)) { + if (flags.unknownFn(arg) === false) return; + } + + var value = !flags.strings[key] && isNumber$2(val) + ? Number(val) : val + ; + setKey(argv, key.split('.'), value); + + (aliases[key] || []).forEach(function (x) { + setKey(argv, x.split('.'), value); + }); + } + + function setKey (obj, keys, value) { + var o = obj; + for (var i = 0; i < keys.length-1; i++) { + var key = keys[i]; + if (key === '__proto__') return; + if (o[key] === undefined) o[key] = {}; + if (o[key] === Object.prototype || o[key] === Number.prototype + || o[key] === String.prototype) o[key] = {}; + if (o[key] === Array.prototype) o[key] = []; + o = o[key]; + } + + var key = keys[keys.length - 1]; + if (key === '__proto__') return; + if (o === Object.prototype || o === Number.prototype + || o === String.prototype) o = {}; + if (o === Array.prototype) o = []; + if (o[key] === undefined || flags.bools[key] || typeof o[key] === 'boolean') { + o[key] = value; + } + else if (Array.isArray(o[key])) { + o[key].push(value); + } + else { + o[key] = [ o[key], value ]; + } + } + + function aliasIsBoolean(key) { + return aliases[key].some(function (x) { + return flags.bools[x]; + }); + } + + for (var i = 0; i < args.length; i++) { + var arg = args[i]; + + if (/^--.+=/.test(arg)) { + // Using [\s\S] instead of . because js doesn't support the + // 'dotall' regex modifier. See: + // http://stackoverflow.com/a/1068308/13216 + var m = arg.match(/^--([^=]+)=([\s\S]*)$/); + var key = m[1]; + var value = m[2]; + if (flags.bools[key]) { + value = value !== 'false'; + } + setArg(key, value, arg); + } + else if (/^--no-.+/.test(arg)) { + var key = arg.match(/^--no-(.+)/)[1]; + setArg(key, false, arg); + } + else if (/^--.+/.test(arg)) { + var key = arg.match(/^--(.+)/)[1]; + var next = args[i + 1]; + if (next !== undefined && !/^-/.test(next) + && !flags.bools[key] + && !flags.allBools + && (aliases[key] ? !aliasIsBoolean(key) : true)) { + setArg(key, next, arg); + i++; + } + else if (/^(true|false)$/.test(next)) { + setArg(key, next === 'true', arg); + i++; + } + else { + setArg(key, flags.strings[key] ? '' : true, arg); + } + } + else if (/^-[^-]+/.test(arg)) { + var letters = arg.slice(1,-1).split(''); + + var broken = false; + for (var j = 0; j < letters.length; j++) { + var next = arg.slice(j+2); + + if (next === '-') { + setArg(letters[j], next, arg); + continue; + } + + if (/[A-Za-z]/.test(letters[j]) && /=/.test(next)) { + setArg(letters[j], next.split('=')[1], arg); + broken = true; + break; + } + + if (/[A-Za-z]/.test(letters[j]) + && /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) { + setArg(letters[j], next, arg); + broken = true; + break; + } + + if (letters[j+1] && letters[j+1].match(/\W/)) { + setArg(letters[j], arg.slice(j+2), arg); + broken = true; + break; + } + else { + setArg(letters[j], flags.strings[letters[j]] ? '' : true, arg); + } + } + + var key = arg.slice(-1)[0]; + if (!broken && key !== '-') { + if (args[i+1] && !/^(-|--)[^-]/.test(args[i+1]) + && !flags.bools[key] + && (aliases[key] ? !aliasIsBoolean(key) : true)) { + setArg(key, args[i+1], arg); + i++; + } + else if (args[i+1] && /^(true|false)$/.test(args[i+1])) { + setArg(key, args[i+1] === 'true', arg); + i++; + } + else { + setArg(key, flags.strings[key] ? '' : true, arg); + } + } + } + else { + if (!flags.unknownFn || flags.unknownFn(arg) !== false) { + argv._.push( + flags.strings['_'] || !isNumber$2(arg) ? arg : Number(arg) + ); + } + if (opts.stopEarly) { + argv._.push.apply(argv._, args.slice(i + 1)); + break; + } + } + } + + Object.keys(defaults).forEach(function (key) { + if (!hasKey(argv, key.split('.'))) { + setKey(argv, key.split('.'), defaults[key]); + + (aliases[key] || []).forEach(function (x) { + setKey(argv, x.split('.'), defaults[key]); + }); + } + }); + + if (opts['--']) { + argv['--'] = new Array(); + notFlags.forEach(function(key) { + argv['--'].push(key); + }); + } + else { + notFlags.forEach(function(key) { + argv._.push(key); + }); + } + + return argv; +}; + +function hasKey (obj, keys) { + var o = obj; + keys.slice(0,-1).forEach(function (key) { + o = (o[key] || {}); + }); + + var key = keys[keys.length - 1]; + return key in o; +} + +function isNumber$2 (x) { + if (typeof x === 'number') return true; + if (/^0x[0-9a-f]+$/i.test(x)) return true; + return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x); +} // This is a generated file. Do not edit. var Space_Separator = /[\u1680\u2000-\u200A\u202F\u205F\u3000]/; @@ -22749,13 +25333,13 @@ var unicode = { ID_Continue: ID_Continue }; -var util = { +var util$1 = { isSpaceSeparator (c) { - return unicode.Space_Separator.test(c) + return typeof c === 'string' && unicode.Space_Separator.test(c) }, isIdStartChar (c) { - return ( + return typeof c === 'string' && ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c === '$') || (c === '_') || @@ -22764,7 +25348,7 @@ var util = { }, isIdContinueChar (c) { - return ( + return typeof c === 'string' && ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || @@ -22775,15 +25359,15 @@ var util = { }, isDigit (c) { - return /[0-9]/.test(c) + return typeof c === 'string' && /[0-9]/.test(c) }, isHexDigit (c) { - return /[0-9A-Fa-f]/.test(c) + return typeof c === 'string' && /[0-9A-Fa-f]/.test(c) }, }; -let source; +let source$1; let parseState; let stack; let pos; @@ -22794,7 +25378,7 @@ let key; let root; var parse$7 = function parse (text, reviver) { - source = String(text); + source$1 = String(text); parseState = 'start'; stack = []; pos = 0; @@ -22866,12 +25450,12 @@ function lex () { } function peek () { - if (source[pos]) { - return String.fromCodePoint(source.codePointAt(pos)) + if (source$1[pos]) { + return String.fromCodePoint(source$1.codePointAt(pos)) } } -function read$4 () { +function read$5 () { const c = peek(); if (c === '\n') { @@ -22903,21 +25487,21 @@ const lexStates = { case '\r': case '\u2028': case '\u2029': - read$4(); + read$5(); return case '/': - read$4(); + read$5(); lexState = 'comment'; return case undefined: - read$4(); + read$5(); return newToken('eof') } - if (util.isSpaceSeparator(c)) { - read$4(); + if (util$1.isSpaceSeparator(c)) { + read$5(); return } @@ -22932,49 +25516,49 @@ const lexStates = { comment () { switch (c) { case '*': - read$4(); + read$5(); lexState = 'multiLineComment'; return case '/': - read$4(); + read$5(); lexState = 'singleLineComment'; return } - throw invalidChar(read$4()) + throw invalidChar(read$5()) }, multiLineComment () { switch (c) { case '*': - read$4(); + read$5(); lexState = 'multiLineCommentAsterisk'; return case undefined: - throw invalidChar(read$4()) + throw invalidChar(read$5()) } - read$4(); + read$5(); }, multiLineCommentAsterisk () { switch (c) { case '*': - read$4(); + read$5(); return case '/': - read$4(); + read$5(); lexState = 'default'; return case undefined: - throw invalidChar(read$4()) + throw invalidChar(read$5()) } - read$4(); + read$5(); lexState = 'multiLineComment'; }, @@ -22984,42 +25568,42 @@ const lexStates = { case '\r': case '\u2028': case '\u2029': - read$4(); + read$5(); lexState = 'default'; return case undefined: - read$4(); + read$5(); return newToken('eof') } - read$4(); + read$5(); }, value () { switch (c) { case '{': case '[': - return newToken('punctuator', read$4()) + return newToken('punctuator', read$5()) case 'n': - read$4(); + read$5(); literal('ull'); return newToken('null', null) case 't': - read$4(); + read$5(); literal('rue'); return newToken('boolean', true) case 'f': - read$4(); + read$5(); literal('alse'); return newToken('boolean', false) case '-': case '+': - if (read$4() === '-') { + if (read$5() === '-') { sign = -1; } @@ -23027,12 +25611,12 @@ const lexStates = { return case '.': - buffer = read$4(); + buffer = read$5(); lexState = 'decimalPointLeading'; return case '0': - buffer = read$4(); + buffer = read$5(); lexState = 'zero'; return @@ -23045,37 +25629,37 @@ const lexStates = { case '7': case '8': case '9': - buffer = read$4(); + buffer = read$5(); lexState = 'decimalInteger'; return case 'I': - read$4(); + read$5(); literal('nfinity'); return newToken('numeric', Infinity) case 'N': - read$4(); + read$5(); literal('aN'); return newToken('numeric', NaN) case '"': case "'": - doubleQuote = (read$4() === '"'); + doubleQuote = (read$5() === '"'); buffer = ''; lexState = 'string'; return } - throw invalidChar(read$4()) + throw invalidChar(read$5()) }, identifierNameStartEscape () { if (c !== 'u') { - throw invalidChar(read$4()) + throw invalidChar(read$5()) } - read$4(); + read$5(); const u = unicodeEscape(); switch (u) { case '$': @@ -23083,7 +25667,7 @@ const lexStates = { break default: - if (!util.isIdStartChar(u)) { + if (!util$1.isIdStartChar(u)) { throw invalidIdentifier() } @@ -23100,17 +25684,17 @@ const lexStates = { case '_': case '\u200C': case '\u200D': - buffer += read$4(); + buffer += read$5(); return case '\\': - read$4(); + read$5(); lexState = 'identifierNameEscape'; return } - if (util.isIdContinueChar(c)) { - buffer += read$4(); + if (util$1.isIdContinueChar(c)) { + buffer += read$5(); return } @@ -23119,10 +25703,10 @@ const lexStates = { identifierNameEscape () { if (c !== 'u') { - throw invalidChar(read$4()) + throw invalidChar(read$5()) } - read$4(); + read$5(); const u = unicodeEscape(); switch (u) { case '$': @@ -23132,7 +25716,7 @@ const lexStates = { break default: - if (!util.isIdContinueChar(u)) { + if (!util$1.isIdContinueChar(u)) { throw invalidIdentifier() } @@ -23146,12 +25730,12 @@ const lexStates = { sign () { switch (c) { case '.': - buffer = read$4(); + buffer = read$5(); lexState = 'decimalPointLeading'; return case '0': - buffer = read$4(); + buffer = read$5(); lexState = 'zero'; return @@ -23164,40 +25748,40 @@ const lexStates = { case '7': case '8': case '9': - buffer = read$4(); + buffer = read$5(); lexState = 'decimalInteger'; return case 'I': - read$4(); + read$5(); literal('nfinity'); return newToken('numeric', sign * Infinity) case 'N': - read$4(); + read$5(); literal('aN'); return newToken('numeric', NaN) } - throw invalidChar(read$4()) + throw invalidChar(read$5()) }, zero () { switch (c) { case '.': - buffer += read$4(); + buffer += read$5(); lexState = 'decimalPoint'; return case 'e': case 'E': - buffer += read$4(); + buffer += read$5(); lexState = 'decimalExponent'; return case 'x': case 'X': - buffer += read$4(); + buffer += read$5(); lexState = 'hexadecimal'; return } @@ -23208,19 +25792,19 @@ const lexStates = { decimalInteger () { switch (c) { case '.': - buffer += read$4(); + buffer += read$5(); lexState = 'decimalPoint'; return case 'e': case 'E': - buffer += read$4(); + buffer += read$5(); lexState = 'decimalExponent'; return } - if (util.isDigit(c)) { - buffer += read$4(); + if (util$1.isDigit(c)) { + buffer += read$5(); return } @@ -23228,26 +25812,26 @@ const lexStates = { }, decimalPointLeading () { - if (util.isDigit(c)) { - buffer += read$4(); + if (util$1.isDigit(c)) { + buffer += read$5(); lexState = 'decimalFraction'; return } - throw invalidChar(read$4()) + throw invalidChar(read$5()) }, decimalPoint () { switch (c) { case 'e': case 'E': - buffer += read$4(); + buffer += read$5(); lexState = 'decimalExponent'; return } - if (util.isDigit(c)) { - buffer += read$4(); + if (util$1.isDigit(c)) { + buffer += read$5(); lexState = 'decimalFraction'; return } @@ -23259,13 +25843,13 @@ const lexStates = { switch (c) { case 'e': case 'E': - buffer += read$4(); + buffer += read$5(); lexState = 'decimalExponent'; return } - if (util.isDigit(c)) { - buffer += read$4(); + if (util$1.isDigit(c)) { + buffer += read$5(); return } @@ -23276,33 +25860,33 @@ const lexStates = { switch (c) { case '+': case '-': - buffer += read$4(); + buffer += read$5(); lexState = 'decimalExponentSign'; return } - if (util.isDigit(c)) { - buffer += read$4(); + if (util$1.isDigit(c)) { + buffer += read$5(); lexState = 'decimalExponentInteger'; return } - throw invalidChar(read$4()) + throw invalidChar(read$5()) }, decimalExponentSign () { - if (util.isDigit(c)) { - buffer += read$4(); + if (util$1.isDigit(c)) { + buffer += read$5(); lexState = 'decimalExponentInteger'; return } - throw invalidChar(read$4()) + throw invalidChar(read$5()) }, decimalExponentInteger () { - if (util.isDigit(c)) { - buffer += read$4(); + if (util$1.isDigit(c)) { + buffer += read$5(); return } @@ -23310,18 +25894,18 @@ const lexStates = { }, hexadecimal () { - if (util.isHexDigit(c)) { - buffer += read$4(); + if (util$1.isHexDigit(c)) { + buffer += read$5(); lexState = 'hexadecimalInteger'; return } - throw invalidChar(read$4()) + throw invalidChar(read$5()) }, hexadecimalInteger () { - if (util.isHexDigit(c)) { - buffer += read$4(); + if (util$1.isHexDigit(c)) { + buffer += read$5(); return } @@ -23331,31 +25915,31 @@ const lexStates = { string () { switch (c) { case '\\': - read$4(); + read$5(); buffer += escape(); return case '"': if (doubleQuote) { - read$4(); + read$5(); return newToken('string', buffer) } - buffer += read$4(); + buffer += read$5(); return case "'": if (!doubleQuote) { - read$4(); + read$5(); return newToken('string', buffer) } - buffer += read$4(); + buffer += read$5(); return case '\n': case '\r': - throw invalidChar(read$4()) + throw invalidChar(read$5()) case '\u2028': case '\u2029': @@ -23363,17 +25947,17 @@ const lexStates = { break case undefined: - throw invalidChar(read$4()) + throw invalidChar(read$5()) } - buffer += read$4(); + buffer += read$5(); }, start () { switch (c) { case '{': case '[': - return newToken('punctuator', read$4()) + return newToken('punctuator', read$5()) // This code is unreachable since the default lexState handles eof. // case undefined: @@ -23387,40 +25971,40 @@ const lexStates = { switch (c) { case '$': case '_': - buffer = read$4(); + buffer = read$5(); lexState = 'identifierName'; return case '\\': - read$4(); + read$5(); lexState = 'identifierNameStartEscape'; return case '}': - return newToken('punctuator', read$4()) + return newToken('punctuator', read$5()) case '"': case "'": - doubleQuote = (read$4() === '"'); + doubleQuote = (read$5() === '"'); lexState = 'string'; return } - if (util.isIdStartChar(c)) { - buffer += read$4(); + if (util$1.isIdStartChar(c)) { + buffer += read$5(); lexState = 'identifierName'; return } - throw invalidChar(read$4()) + throw invalidChar(read$5()) }, afterPropertyName () { if (c === ':') { - return newToken('punctuator', read$4()) + return newToken('punctuator', read$5()) } - throw invalidChar(read$4()) + throw invalidChar(read$5()) }, beforePropertyValue () { @@ -23431,15 +26015,15 @@ const lexStates = { switch (c) { case ',': case '}': - return newToken('punctuator', read$4()) + return newToken('punctuator', read$5()) } - throw invalidChar(read$4()) + throw invalidChar(read$5()) }, beforeArrayValue () { if (c === ']') { - return newToken('punctuator', read$4()) + return newToken('punctuator', read$5()) } lexState = 'value'; @@ -23449,10 +26033,10 @@ const lexStates = { switch (c) { case ',': case ']': - return newToken('punctuator', read$4()) + return newToken('punctuator', read$5()) } - throw invalidChar(read$4()) + throw invalidChar(read$5()) }, end () { @@ -23462,7 +26046,7 @@ const lexStates = { // return newToken('eof') // } - throw invalidChar(read$4()) + throw invalidChar(read$5()) }, }; @@ -23480,10 +26064,10 @@ function literal (s) { const p = peek(); if (p !== c) { - throw invalidChar(read$4()) + throw invalidChar(read$5()) } - read$4(); + read$5(); } } @@ -23491,55 +26075,55 @@ function escape () { const c = peek(); switch (c) { case 'b': - read$4(); + read$5(); return '\b' case 'f': - read$4(); + read$5(); return '\f' case 'n': - read$4(); + read$5(); return '\n' case 'r': - read$4(); + read$5(); return '\r' case 't': - read$4(); + read$5(); return '\t' case 'v': - read$4(); + read$5(); return '\v' case '0': - read$4(); - if (util.isDigit(peek())) { - throw invalidChar(read$4()) + read$5(); + if (util$1.isDigit(peek())) { + throw invalidChar(read$5()) } return '\0' case 'x': - read$4(); + read$5(); return hexEscape() case 'u': - read$4(); + read$5(); return unicodeEscape() case '\n': case '\u2028': case '\u2029': - read$4(); + read$5(); return '' case '\r': - read$4(); + read$5(); if (peek() === '\n') { - read$4(); + read$5(); } return '' @@ -23553,31 +26137,31 @@ function escape () { case '7': case '8': case '9': - throw invalidChar(read$4()) + throw invalidChar(read$5()) case undefined: - throw invalidChar(read$4()) + throw invalidChar(read$5()) } - return read$4() + return read$5() } function hexEscape () { let buffer = ''; let c = peek(); - if (!util.isHexDigit(c)) { - throw invalidChar(read$4()) + if (!util$1.isHexDigit(c)) { + throw invalidChar(read$5()) } - buffer += read$4(); + buffer += read$5(); c = peek(); - if (!util.isHexDigit(c)) { - throw invalidChar(read$4()) + if (!util$1.isHexDigit(c)) { + throw invalidChar(read$5()) } - buffer += read$4(); + buffer += read$5(); return String.fromCodePoint(parseInt(buffer, 16)) } @@ -23588,11 +26172,11 @@ function unicodeEscape () { while (count-- > 0) { const c = peek(); - if (!util.isHexDigit(c)) { - throw invalidChar(read$4()) + if (!util$1.isHexDigit(c)) { + throw invalidChar(read$5()) } - buffer += read$4(); + buffer += read$5(); } return String.fromCodePoint(parseInt(buffer, 16)) @@ -24003,7 +26587,7 @@ var stringify$5 = function stringify (value, replacer, space) { continue case '\0': - if (util.isDigit(value[i + 1])) { + if (util$1.isDigit(value[i + 1])) { product += '\\x00'; continue } @@ -24080,12 +26664,12 @@ var stringify$5 = function stringify (value, replacer, space) { } const firstChar = String.fromCodePoint(key.codePointAt(0)); - if (!util.isIdStartChar(firstChar)) { + if (!util$1.isIdStartChar(firstChar)) { return quoteString(key) } for (let i = firstChar.length; i < key.length; i++) { - if (!util.isIdContinueChar(String.fromCodePoint(key.codePointAt(i)))) { + if (!util$1.isIdContinueChar(String.fromCodePoint(key.codePointAt(i)))) { return quoteString(key) } } @@ -24134,11 +26718,11 @@ const JSON5 = { stringify: stringify$5, }; -var lib$2 = JSON5; +var lib$5 = JSON5; -var dist = /*#__PURE__*/Object.freeze({ +var dist$1 = /*#__PURE__*/Object.freeze({ __proto__: null, - 'default': lib$2 + 'default': lib$5 }); var schema$1 = [ @@ -24244,6 +26828,13 @@ var schema$1 = [ type: "string", value: "" }, + { + long: "ignore-path-resolve-from", + description: "resolve patterns in `ignore-path` from its directory or cwd", + type: "string", + value: "dir|cwd", + "default": "dir" + }, { long: "ignore-pattern", description: "specify ignore patterns", @@ -24296,7 +26887,7 @@ var schema$2 = /*#__PURE__*/Object.freeze({ 'default': schema$1 }); -var json5 = getCjsExportFromNamespace(dist); +var json5 = getCjsExportFromNamespace(dist$1); var schema$3 = getCjsExportFromNamespace(schema$2); @@ -24322,7 +26913,7 @@ function options(flags, configuration) { var ext; var report; - schema$3.forEach(function(option) { + schema$3.forEach(function (option) { if (option.type === 'string' && config[option.long] === '') { throw fault_1('Missing value:%s', inspect$1(option).join(' ')) } @@ -24370,6 +26961,7 @@ function options(flags, configuration) { settings: settings(config.setting), ignoreName: configuration.ignoreName, ignorePath: config.ignorePath, + ignorePathResolveFrom: config.ignorePathResolveFrom, ignorePatterns: commaSeparated(config.ignorePattern), detectIgnore: config.ignore, pluginPrefix: configuration.pluginPrefix, @@ -24408,7 +27000,7 @@ function plugins(value) { normalize$1(value) .map(splitOptions) - .forEach(function(value) { + .forEach(function (value) { result[value[0]] = value[1] ? parseConfig(value[1], {}) : null; }); @@ -24419,7 +27011,7 @@ function plugins(value) { function reporter$1(value) { var all = normalize$1(value) .map(splitOptions) - .map(function(value) { + .map(function (value) { return [value[0], value[1] ? parseConfig(value[1], {}) : null] }); @@ -24430,7 +27022,7 @@ function reporter$1(value) { function settings(value) { var cache = {}; - normalize$1(value).forEach(function(value) { + normalize$1(value).forEach(function (value) { parseConfig(value, cache); }); @@ -24471,10 +27063,7 @@ function handleUnknownArgument(flag) { } // Short options, can be grouped. - flag - .slice(1) - .split('') - .forEach(each); + flag.slice(1).split('').forEach(each); function each(key) { var length = schema$3.length; @@ -24574,7 +27163,7 @@ function parseJSON(value) { return json5.parse('{' + value + '}') } -var lib$3 = start; +var lib$6 = start; var noop$1 = Function.prototype; @@ -24637,7 +27226,7 @@ function start(cliConfig) { config.out = false; process.stderr.write( - chalk.bold('Watching...') + ' (press CTRL+C to exit)\n', + source.bold('Watching...') + ' (press CTRL+C to exit)\n', noop$1 ); @@ -24646,14 +27235,14 @@ function start(cliConfig) { config.output = false; process.stderr.write( - chalk.yellow('Note') + ': Ignoring `--output` until exit.\n', + source.yellow('Note') + ': Ignoring `--output` until exit.\n', noop$1 ); } } // Initial run. - lib$1(config, done); + lib$4(config, done); // Handle complete run. function done(err, code, context) { @@ -24689,7 +27278,7 @@ function start(cliConfig) { function onchange(filePath) { config.files = [filePath]; - lib$1(config, done); + lib$4(config, done); } function onsigint() { @@ -24702,7 +27291,7 @@ function start(cliConfig) { if (output === true) { config.output = output; config.watch = false; - lib$1(config, done); + lib$4(config, done); } } } @@ -24725,7 +27314,7 @@ function onexit() { /* eslint-enable unicorn/no-process-exit */ } -var unifiedArgs = lib$3; +var unifiedArgs = lib$6; var markdownExtensions = [ "md", @@ -24743,9 +27332,17 @@ var markdownExtensions$1 = /*#__PURE__*/Object.freeze({ 'default': markdownExtensions }); -var require$$0$1 = getCjsExportFromNamespace(markdownExtensions$1); +var require$$0$2 = getCjsExportFromNamespace(markdownExtensions$1); + +var markdownExtensions$2 = require$$0$2; + +var bail_1 = bail; -var markdownExtensions$2 = require$$0$1; +function bail(err) { + if (err) { + throw err + } +} var hasOwn = Object.prototype.hasOwnProperty; var toStr = Object.prototype.toString; @@ -24809,7 +27406,7 @@ var getProperty = function getProperty(obj, name) { return obj[name]; }; -var extend$3 = function extend() { +var extend$2 = function extend() { var options, name, src, copy, copyIsArray, clone; var target = arguments[0]; var i = 1; @@ -24863,23 +27460,6 @@ var extend$3 = function extend() { return target; }; -var bail_1 = bail; - -function bail(err) { - if (err) { - throw err - } -} - -var isPlainObj = value => { - if (Object.prototype.toString.call(value) !== '[object Object]') { - return false; - } - - const prototype = Object.getPrototypeOf(value); - return prototype === null || prototype === Object.getPrototypeOf({}); -}; - // Expose a frozen processor. var unified_1 = unified().freeze(); @@ -24911,7 +27491,14 @@ function pipelineRun(p, ctx, next) { } function pipelineStringify(p, ctx) { - ctx.file.contents = p.stringify(ctx.tree, ctx.file); + var result = p.stringify(ctx.tree, ctx.file); + var file = ctx.file; + + if (result === undefined || result === null) ; else if (typeof result === 'string' || isBuffer(result)) { + file.contents = result; + } else { + file.result = result; + } } // Function to create the first processor. @@ -24953,7 +27540,7 @@ function unified() { destination.use.apply(null, attachers[index]); } - destination.data(extend$3(true, {}, namespace)); + destination.data(extend$2(true, {}, namespace)); return destination } @@ -25055,7 +27642,7 @@ function unified() { } if (settings) { - namespace.settings = extend$3(namespace.settings || {}, settings); + namespace.settings = extend$2(namespace.settings || {}, settings); } return processor @@ -25064,7 +27651,7 @@ function unified() { addList(result.plugins); if (result.settings) { - settings = extend$3(settings || {}, result.settings); + settings = extend$2(settings || {}, result.settings); } } @@ -25103,7 +27690,7 @@ function unified() { if (entry) { if (isPlainObj(entry[1]) && isPlainObj(value)) { - value = extend$3(entry[1], value); + value = extend$2(entry[1], value); } entry[1] = value; @@ -25332,6 +27919,26 @@ function assertDone(name, asyncName, complete) { } } +var immutable = extend$3; + +var hasOwnProperty = Object.prototype.hasOwnProperty; + +function extend$3() { + var target = {}; + + for (var i = 0; i < arguments.length; i++) { + var source = arguments[i]; + + for (var key in source) { + if (hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + } + + return target +} + var unherit_1 = unherit; // Create a custom constructor which can be modified without affecting the @@ -25478,26 +28085,26 @@ function factory$3(ctx, key) { // De-escape a string using the expression at `key` in `ctx`. function unescape(value) { - var prev = 0; + var previous = 0; var index = value.indexOf(backslash$1); var escape = ctx[key]; var queue = []; var character; while (index !== -1) { - queue.push(value.slice(prev, index)); - prev = index + 1; - character = value.charAt(prev); + queue.push(value.slice(previous, index)); + previous = index + 1; + character = value.charAt(previous); // If the following character is not a valid escape, add the slash. if (!character || escape.indexOf(character) === -1) { queue.push(backslash$1); } - index = value.indexOf(backslash$1, prev + 1); + index = value.indexOf(backslash$1, previous + 1); } - queue.push(value.slice(prev)); + queue.push(value.slice(previous)); return queue.join('') } @@ -27344,7 +29951,7 @@ const minusdu = "⨪"; const mlcp = "⫛"; const mldr = "…"; const mnplus = "∓"; -const models$1 = "⊧"; +const models$2 = "⊧"; const mopf = "𝕞"; const mp = "∓"; const mscr = "𝓂"; @@ -29567,7 +32174,7 @@ var index$3 = { mlcp: mlcp, mldr: mldr, mnplus: mnplus, - models: models$1, + models: models$2, mopf: mopf, mp: mp, mscr: mscr, @@ -31791,7 +34398,7 @@ var characterEntities = /*#__PURE__*/Object.freeze({ mlcp: mlcp, mldr: mldr, mnplus: mnplus, - models: models$1, + models: models$2, mopf: mopf, mp: mp, mscr: mscr, @@ -32619,15 +35226,15 @@ var defaults = { // Characters. var tab = 9; // '\t' var lineFeed = 10; // '\n' -var formFeed = 12; // '\f' +var formFeed = 12; // '\f' var space = 32; // ' ' -var ampersand = 38; // '&' -var semicolon = 59; // ';' -var lessThan = 60; // '<' -var equalsTo = 61; // '=' -var numberSign = 35; // '#' -var uppercaseX = 88; // 'X' -var lowercaseX = 120; // 'x' +var ampersand = 38; // '&' +var semicolon = 59; // ';' +var lessThan = 60; // '<' +var equalsTo = 61; // '=' +var numberSign = 35; // '#' +var uppercaseX = 88; // 'X' +var lowercaseX = 120; // 'x' var replacementCharacter = 65533; // '�' // Reference types. @@ -32749,7 +35356,8 @@ function parse$8(value, settings) { // Wrap `handleWarning`. warning = handleWarning ? parseError : noop$2; - // Ensure the algorithm walks over the first character and the end (inclusive). + // Ensure the algorithm walks over the first character and the end + // (inclusive). index--; length++; @@ -32980,7 +35588,7 @@ function parse$8(value, settings) { } } - // Return the reduced nodes, and any possible warnings. + // Return the reduced nodes. return result.join('') // Get current position. @@ -33136,11 +35744,15 @@ function factory$5(type) { name = methods[index]; method = tokenizers[name]; + // Previously, we had constructs such as footnotes and YAML that used + // these properties. + // Those are now external (plus there are userland extensions), that may + // still use them. if ( method && /* istanbul ignore next */ (!method.onlyAtStart || self.atStart) && - (!method.notInList || !self.inList) && - (!method.notInBlock || !self.inBlock) && + /* istanbul ignore next */ (!method.notInList || !self.inList) && + /* istanbul ignore next */ (!method.notInBlock || !self.inBlock) && (!method.notInLink || !self.inLink) ) { valueLength = value.length; @@ -33199,7 +35811,7 @@ function factory$5(type) { // Done. Called when the last character is eaten to retrieve the range’s // offsets. - return function() { + return function () { var last = line + 1; while (pos < last) { @@ -33250,10 +35862,10 @@ function factory$5(type) { // Add the position to a node. function update(node, indent) { - var prev = node.position; - var start = prev ? prev.start : before; + var previous = node.position; + var start = previous ? previous.start : before; var combined = []; - var n = prev && prev.end.line; + var n = previous && previous.end.line; var l = before.line; node.position = new Position(start); @@ -33263,8 +35875,8 @@ function factory$5(type) { // because some information, the indent between `n` and `l` wasn’t // tracked. Luckily, that space is (should be?) empty, so we can // safely check for it now. - if (prev && indent && prev.indent) { - combined = prev.indent; + if (previous && indent && previous.indent) { + combined = previous.indent; if (n < l) { while (++n < l) { @@ -33287,21 +35899,21 @@ function factory$5(type) { // possible. function add(node, parent) { var children = parent ? parent.children : tokens; - var prev = children[children.length - 1]; + var previous = children[children.length - 1]; var fn; if ( - prev && - node.type === prev.type && + previous && + node.type === previous.type && (node.type === 'text' || node.type === 'blockquote') && - mergeable(prev) && + mergeable(previous) && mergeable(node) ) { fn = node.type === 'text' ? mergeText : mergeBlockquote; - node = fn.call(self, prev, node); + node = fn.call(self, previous, node); } - if (node !== prev) { + if (node !== previous) { children.push(node); } @@ -33386,21 +35998,21 @@ function mergeable(node) { } // Merge two text nodes: `node` into `prev`. -function mergeText(prev, node) { - prev.value += node.value; +function mergeText(previous, node) { + previous.value += node.value; - return prev + return previous } // Merge two blockquotes: `node` into `prev`, unless in CommonMark or gfm modes. -function mergeBlockquote(prev, node) { +function mergeBlockquote(previous, node) { if (this.options.commonmark || this.options.gfm) { return node } - prev.children = prev.children.concat(node.children); + previous.children = previous.children.concat(node.children); - return prev + return previous } var markdownEscapes = escapes; @@ -33532,7 +36144,6 @@ var defaults$2 = { position: true, gfm: true, commonmark: false, - footnotes: false, pedantic: false, blocks: blockElements }; @@ -33578,9 +36189,9 @@ function setOptions(options) { return self } -var convert_1 = convert$1; +var convert_1 = convert$3; -function convert$1(test) { +function convert$3(test) { if (typeof test === 'string') { return typeFactory(test) } @@ -33606,7 +36217,7 @@ function convertAll(tests) { var index = -1; while (++index < length) { - results[index] = convert$1(tests[index]); + results[index] = convert$3(tests[index]); } return results @@ -33822,31 +36433,37 @@ function parse$9() { return node } -var isWhitespaceCharacter = whitespace; +// A line containing no characters, or a line containing only spaces (U+0020) or +// tabs (U+0009), is called a blank line. +// See . +var reBlankLine = /^[ \t]*(\n|$)/; -var fromCode = String.fromCharCode; -var re$1 = /\s/; +// Note that though blank lines play a special role in lists to determine +// whether the list is tight or loose +// (), it’s done by the list +// tokenizer and this blank line tokenizer does not have to be responsible for +// that. +// Therefore, configs such as `blankLine.notInList` do not have to be set here. +var blankLine_1 = blankLine; -// Check if the given character code, or the character code at the first -// character, is a whitespace character. -function whitespace(character) { - return re$1.test( - typeof character === 'number' ? fromCode(character) : character.charAt(0) - ) -} +function blankLine(eat, value, silent) { + var match; + var subvalue = ''; + var index = 0; + var length = value.length; -var newline_1 = newline; + while (index < length) { + match = reBlankLine.exec(value.slice(index)); -var lineFeed$2 = '\n'; + if (match == null) { + break + } -function newline(eat, value, silent) { - var character = value.charAt(0); - var length; - var subvalue; - var queue; - var index; + index += match[0].length; + subvalue += match[0]; + } - if (character !== lineFeed$2) { + if (subvalue === '') { return } @@ -33855,28 +36472,6 @@ function newline(eat, value, silent) { return true } - index = 1; - length = value.length; - subvalue = character; - queue = ''; - - while (index < length) { - character = value.charAt(index); - - if (!isWhitespaceCharacter(character)) { - break - } - - queue += character; - - if (character === lineFeed$2) { - subvalue += queue; - queue = ''; - } - - index++; - } - eat(subvalue); } @@ -33898,7 +36493,7 @@ function trimTrailingLines(value) { var codeIndented = indentedCode; -var lineFeed$3 = '\n'; +var lineFeed$2 = '\n'; var tab$1 = '\t'; var space$1 = ' '; @@ -33927,7 +36522,7 @@ function indentedCode(eat, value, silent) { subvalueQueue = ''; contentQueue = ''; - if (character === lineFeed$3) { + if (character === lineFeed$2) { subvalueQueue = character; contentQueue = character; } else { @@ -33937,7 +36532,7 @@ function indentedCode(eat, value, silent) { while (++index < length) { character = value.charAt(index); - if (!character || character === lineFeed$3) { + if (!character || character === lineFeed$2) { contentQueue = character; subvalueQueue = character; break @@ -33967,7 +36562,7 @@ function indentedCode(eat, value, silent) { character = value.charAt(++index); } - if (character !== lineFeed$3) { + if (character !== lineFeed$2) { break } @@ -33992,7 +36587,7 @@ function indentedCode(eat, value, silent) { var codeFenced = fencedCode; -var lineFeed$4 = '\n'; +var lineFeed$3 = '\n'; var tab$2 = '\t'; var space$2 = ' '; var tilde$1 = '~'; @@ -34087,7 +36682,7 @@ function fencedCode(eat, value, silent) { character = value.charAt(index); if ( - character === lineFeed$4 || + character === lineFeed$3 || (marker === graveAccent && character === marker) ) { break @@ -34105,7 +36700,7 @@ function fencedCode(eat, value, silent) { character = value.charAt(index); - if (character && character !== lineFeed$4) { + if (character && character !== lineFeed$3) { return } @@ -34139,7 +36734,7 @@ function fencedCode(eat, value, silent) { closing = ''; exdentedClosing = ''; - if (character !== lineFeed$4) { + if (character !== lineFeed$3) { content += character; exdentedClosing += character; index++; @@ -34210,7 +36805,7 @@ function fencedCode(eat, value, silent) { index++; } - if (!character || character === lineFeed$4) { + if (!character || character === lineFeed$3) { break } } @@ -34262,7 +36857,7 @@ var trim_3 = trim_1.right; var interrupt_1 = interrupt; -function interrupt(interruptors, tokenizers, ctx, params) { +function interrupt(interruptors, tokenizers, ctx, parameters) { var length = interruptors.length; var index = -1; var interruptor; @@ -34286,7 +36881,7 @@ function interrupt(interruptors, tokenizers, ctx, params) { continue } - if (tokenizers[interruptor[0]].apply(ctx, params)) { + if (tokenizers[interruptor[0]].apply(ctx, parameters)) { return true } } @@ -34296,7 +36891,7 @@ function interrupt(interruptors, tokenizers, ctx, params) { var blockquote_1 = blockquote; -var lineFeed$5 = '\n'; +var lineFeed$4 = '\n'; var tab$3 = '\t'; var space$3 = ' '; var greaterThan = '>'; @@ -34344,7 +36939,7 @@ function blockquote(eat, value, silent) { index = 0; while (index < length) { - nextIndex = value.indexOf(lineFeed$5, index); + nextIndex = value.indexOf(lineFeed$4, index); startIndex = index; prefixed = false; @@ -34400,7 +36995,7 @@ function blockquote(eat, value, silent) { index = -1; length = indents.length; - add = eat(values.join(lineFeed$5)); + add = eat(values.join(lineFeed$4)); while (++index < length) { offsets[currentLine] = (offsets[currentLine] || 0) + indents[index]; @@ -34408,7 +37003,7 @@ function blockquote(eat, value, silent) { } exit = self.enterBlock(); - contents = self.tokenizeBlock(contents.join(lineFeed$5), now); + contents = self.tokenizeBlock(contents.join(lineFeed$4), now); exit(); return add({type: 'blockquote', children: contents}) @@ -34416,7 +37011,7 @@ function blockquote(eat, value, silent) { var headingAtx = atxHeading; -var lineFeed$6 = '\n'; +var lineFeed$5 = '\n'; var tab$4 = '\t'; var space$4 = ' '; var numberSign$1 = '#'; @@ -34487,7 +37082,7 @@ function atxHeading(eat, value, silent) { } // Exit when not in pedantic mode without spacing. - if (!pedantic && queue.length === 0 && character && character !== lineFeed$6) { + if (!pedantic && queue.length === 0 && character && character !== lineFeed$5) { return } @@ -34503,7 +37098,7 @@ function atxHeading(eat, value, silent) { while (++index < length) { character = value.charAt(index); - if (!character || character === lineFeed$6) { + if (!character || character === lineFeed$5) { break } @@ -34551,7 +37146,7 @@ function atxHeading(eat, value, silent) { var thematicBreak_1 = thematicBreak; var tab$5 = '\t'; -var lineFeed$7 = '\n'; +var lineFeed$6 = '\n'; var space$5 = ' '; var asterisk = '*'; var dash$1 = '-'; @@ -34602,7 +37197,7 @@ function thematicBreak(eat, value, silent) { queue += character; } else if ( markerCount >= maxCount && - (!character || character === lineFeed$7) + (!character || character === lineFeed$6) ) { subvalue += queue; @@ -34632,6 +37227,7 @@ function indentation(value) { var character = value.charAt(index); var stops = {}; var size; + var lastIndent = 0; while (character === tab$6 || character === space$6) { size = character === tab$6 ? tabSize$2 : spaceSize; @@ -34642,7 +37238,10 @@ function indentation(value) { indent = Math.floor(indent / size) * size; } - stops[indent] = index; + while (lastIndent < indent) { + stops[++lastIndent] = index; + } + character = value.charAt(++index); } @@ -34651,22 +37250,20 @@ function indentation(value) { var removeIndentation = indentation$1; -var tab$7 = '\t'; -var lineFeed$8 = '\n'; +var lineFeed$7 = '\n'; var space$7 = ' '; var exclamationMark = '!'; // Remove the minimum indent from every line in `value`. Supports both tab, // spaced, and mixed indentation (as well as possible). function indentation$1(value, maximum) { - var values = value.split(lineFeed$8); + var values = value.split(lineFeed$7); var position = values.length + 1; var minIndent = Infinity; var matrix = []; var index; var indentation; var stops; - var padding; values.unshift(repeatString(space$7, maximum) + exclamationMark); @@ -34701,24 +37298,13 @@ function indentation$1(value, maximum) { index--; } - if ( - trim_1(values[position]).length !== 0 && - minIndent && - index !== minIndent - ) { - padding = tab$7; - } else { - padding = ''; - } - - values[position] = - padding + values[position].slice(index in stops ? stops[index] + 1 : 0); + values[position] = values[position].slice(stops[index] + 1); } } values.shift(); - return values.join(lineFeed$8) + return values.join(lineFeed$7) } var list_1 = list; @@ -34729,14 +37315,14 @@ var plusSign = '+'; var dash$2 = '-'; var dot$1 = '.'; var space$8 = ' '; -var lineFeed$9 = '\n'; -var tab$8 = '\t'; +var lineFeed$8 = '\n'; +var tab$7 = '\t'; var rightParenthesis = ')'; var lowercaseX$1 = 'x'; var tabSize$3 = 4; var looseListItemExpression = /\n\n(?!\s*$)/; -var taskItemExpression = /^\[([ \t]|x|X)][ \t]/; +var taskItemExpression = /^\[([ X\tx])][ \t]/; var bulletExpression = /^([ \t]*)([*+-]|\d+[.)])( {1,4}(?! )| |\t|$|(?=\n))([^\n]*)/; var pedanticBulletExpression = /^([ \t]*)([*+-]|\d+[.)])([ \t]+)/; var initialIndentExpression = /^( {1,4}|\t)?/gm; @@ -34750,7 +37336,7 @@ function list(eat, value, silent) { var index = 0; var length = value.length; var start = null; - var size = 0; + var size; var queue; var ordered; var character; @@ -34761,7 +37347,7 @@ function list(eat, value, silent) { var currentMarker; var content; var line; - var prevEmpty; + var previousEmpty; var empty; var items; var allLines; @@ -34778,21 +37364,13 @@ function list(eat, value, silent) { while (index < length) { character = value.charAt(index); - if (character === tab$8) { - size += tabSize$3 - (size % tabSize$3); - } else if (character === space$8) { - size++; - } else { + if (character !== tab$7 && character !== space$8) { break } index++; } - if (size >= tabSize$3) { - return - } - character = value.charAt(index); if (character === asterisk$1 || character === plusSign || character === dash$2) { @@ -34822,6 +37400,14 @@ function list(eat, value, silent) { return } + /* Slightly abusing `silent` mode, whose goal is to make interrupting + * paragraphs work. + * Well, that’s exactly what we want to do here: don’t interrupt: + * 2. here, because the “list” doesn’t start with `1`. */ + if (silent && queue !== '1') { + return + } + start = parseInt(queue, 10); marker = character; } @@ -34830,8 +37416,8 @@ function list(eat, value, silent) { if ( character !== space$8 && - character !== tab$8 && - (pedantic || (character !== lineFeed$9 && character !== '')) + character !== tab$7 && + (pedantic || (character !== lineFeed$8 && character !== '')) ) { return } @@ -34846,7 +37432,7 @@ function list(eat, value, silent) { emptyLines = []; while (index < length) { - nextIndex = value.indexOf(lineFeed$9, index); + nextIndex = value.indexOf(lineFeed$8, index); startIndex = index; prefixed = false; indented = false; @@ -34855,13 +37441,12 @@ function list(eat, value, silent) { nextIndex = length; } - end = index + tabSize$3; size = 0; while (index < length) { character = value.charAt(index); - if (character === tab$8) { + if (character === tab$7) { size += tabSize$3 - (size % tabSize$3); } else if (character === space$8) { size++; @@ -34872,10 +37457,6 @@ function list(eat, value, silent) { index++; } - if (size >= tabSize$3) { - indented = true; - } - if (item && size >= item.indent) { indented = true; } @@ -34921,7 +37502,7 @@ function list(eat, value, silent) { if (currentMarker) { character = value.charAt(index); - if (character === tab$8) { + if (character === tab$7) { size += tabSize$3 - (size % tabSize$3); index++; } else if (character === space$8) { @@ -34940,7 +37521,7 @@ function list(eat, value, silent) { index -= tabSize$3 - 1; size -= tabSize$3 - 1; } - } else if (character !== lineFeed$9 && character !== '') { + } else if (character !== lineFeed$8 && character !== '') { currentMarker = null; } } @@ -34976,7 +37557,7 @@ function list(eat, value, silent) { } } - prevEmpty = empty; + previousEmpty = empty; empty = !prefixed && !trim_1(content).length; if (indented && item) { @@ -35000,13 +37581,13 @@ function list(eat, value, silent) { allLines = allLines.concat(emptyLines, line); emptyLines = []; } else if (empty) { - if (prevEmpty && !commonmark) { + if (previousEmpty && !commonmark) { break } emptyLines.push(line); } else { - if (prevEmpty) { + if (previousEmpty) { break } @@ -35022,7 +37603,7 @@ function list(eat, value, silent) { index = nextIndex + 1; } - node = eat(allLines.join(lineFeed$9)).reset({ + node = eat(allLines.join(lineFeed$8)).reset({ type: 'list', ordered: ordered, start: start, @@ -35036,15 +37617,15 @@ function list(eat, value, silent) { length = items.length; while (++index < length) { - item = items[index].value.join(lineFeed$9); + item = items[index].value.join(lineFeed$8); now = eat.now(); eat(item)(listItem(self, item, now), node); - item = items[index].trail.join(lineFeed$9); + item = items[index].trail.join(lineFeed$8); if (index !== length - 1) { - item += lineFeed$9; + item += lineFeed$8; } eat(item); @@ -35122,9 +37703,9 @@ function normalListItem(ctx, value, position) { // Remove the list-item’s bullet. value = value.replace(bulletExpression, replacer); - lines = value.split(lineFeed$9); + lines = value.split(lineFeed$8); - trimmedLines = removeIndentation(value, getIndentation(max).indent).split(lineFeed$9); + trimmedLines = removeIndentation(value, getIndentation(max).indent).split(lineFeed$8); // We replaced the initial bullet with something else above, which was used // to trick `removeIndentation` into removing some more characters when @@ -35144,7 +37725,7 @@ function normalListItem(ctx, value, position) { line++; } - return trimmedLines.join(lineFeed$9) + return trimmedLines.join(lineFeed$8) /* eslint-disable-next-line max-params */ function replacer($0, $1, $2, $3, $4) { @@ -35166,8 +37747,8 @@ function normalListItem(ctx, value, position) { var headingSetext = setextHeading; -var lineFeed$a = '\n'; -var tab$9 = '\t'; +var lineFeed$9 = '\n'; +var tab$8 = '\t'; var space$9 = ' '; var equalsTo$1 = '='; var dash$3 = '-'; @@ -35208,12 +37789,12 @@ function setextHeading(eat, value, silent) { while (++index < length) { character = value.charAt(index); - if (character === lineFeed$a) { + if (character === lineFeed$9) { index--; break } - if (character === space$9 || character === tab$9) { + if (character === space$9 || character === tab$8) { queue += character; } else { content += queue + character; @@ -35229,7 +37810,7 @@ function setextHeading(eat, value, silent) { character = value.charAt(++index); marker = value.charAt(++index); - if (character !== lineFeed$a || (marker !== equalsTo$1 && marker !== dash$3)) { + if (character !== lineFeed$9 || (marker !== equalsTo$1 && marker !== dash$3)) { return } @@ -35243,7 +37824,7 @@ function setextHeading(eat, value, silent) { character = value.charAt(index); if (character !== marker) { - if (character !== lineFeed$a) { + if (character !== lineFeed$9) { return } @@ -35307,9 +37888,9 @@ var openCloseTag$1 = html.openCloseTag; var htmlBlock = blockHtml; -var tab$a = '\t'; +var tab$9 = '\t'; var space$a = ' '; -var lineFeed$b = '\n'; +var lineFeed$a = '\n'; var lessThan$1 = '<'; var rawOpenExpression = /^<(script|pre|style)(?=(\s|>|$))/i; @@ -35321,7 +37902,7 @@ var instructionCloseExpression = /\?>/; var directiveOpenExpression = /^/; var cdataOpenExpression = /^/; +var cdataCloseExpression = /]]>/; var elementCloseExpression = /^$/; var otherElementOpenExpression = new RegExp(openCloseTag$1.source + '\\s*$'); @@ -35356,7 +37937,7 @@ function blockHtml(eat, value, silent) { while (index < length) { character = value.charAt(index); - if (character !== tab$a && character !== space$a) { + if (character !== tab$9 && character !== space$a) { break } @@ -35367,7 +37948,7 @@ function blockHtml(eat, value, silent) { return } - next = value.indexOf(lineFeed$b, index + 1); + next = value.indexOf(lineFeed$a, index + 1); next = next === -1 ? length : next; line = value.slice(index, next); offset = -1; @@ -35392,7 +37973,7 @@ function blockHtml(eat, value, silent) { if (!sequence[1].test(line)) { while (index < length) { - next = value.indexOf(lineFeed$b, index + 1); + next = value.indexOf(lineFeed$a, index + 1); next = next === -1 ? length : next; line = value.slice(index + 1, next); @@ -35413,6 +37994,19 @@ function blockHtml(eat, value, silent) { return eat(subvalue)({type: 'html', value: subvalue}) } +var isWhitespaceCharacter = whitespace; + +var fromCode = String.fromCharCode; +var re$1 = /\s/; + +// Check if the given character code, or the character code at the first +// character, is a whitespace character. +function whitespace(character) { + return re$1.test( + typeof character === 'number' ? fromCode(character) : character.charAt(0) + ) +} + var collapseWhiteSpace = collapse; // `collapse(' \t\nbar \nbaz\t') // ' bar baz '` @@ -35428,201 +38022,19 @@ function normalize$2(value) { return collapseWhiteSpace(value).toLowerCase() } -var footnoteDefinition_1 = footnoteDefinition; -footnoteDefinition.notInList = true; -footnoteDefinition.notInBlock = true; +var definition_1 = definition; +var quotationMark = '"'; +var apostrophe = "'"; var backslash$2 = '\\'; -var lineFeed$c = '\n'; -var tab$b = '\t'; +var lineFeed$b = '\n'; +var tab$a = '\t'; var space$b = ' '; var leftSquareBracket = '['; var rightSquareBracket = ']'; -var caret$1 = '^'; -var colon$1 = ':'; - -var EXPRESSION_INITIAL_TAB = /^( {4}|\t)?/gm; - -function footnoteDefinition(eat, value, silent) { - var self = this; - var offsets = self.offset; - var index; - var length; - var subvalue; - var now; - var currentLine; - var content; - var queue; - var subqueue; - var character; - var identifier; - var add; - var exit; - - if (!self.options.footnotes) { - return - } - - index = 0; - length = value.length; - subvalue = ''; - now = eat.now(); - currentLine = now.line; - - while (index < length) { - character = value.charAt(index); - - if (!isWhitespaceCharacter(character)) { - break - } - - subvalue += character; - index++; - } - - if ( - value.charAt(index) !== leftSquareBracket || - value.charAt(index + 1) !== caret$1 - ) { - return - } - - subvalue += leftSquareBracket + caret$1; - index = subvalue.length; - queue = ''; - - while (index < length) { - character = value.charAt(index); - - if (character === rightSquareBracket) { - break - } else if (character === backslash$2) { - queue += character; - index++; - character = value.charAt(index); - } - - queue += character; - index++; - } - - if ( - !queue || - value.charAt(index) !== rightSquareBracket || - value.charAt(index + 1) !== colon$1 - ) { - return - } - - if (silent) { - return true - } - - identifier = queue; - subvalue += queue + rightSquareBracket + colon$1; - index = subvalue.length; - - while (index < length) { - character = value.charAt(index); - - if (character !== tab$b && character !== space$b) { - break - } - - subvalue += character; - index++; - } - - now.column += subvalue.length; - now.offset += subvalue.length; - queue = ''; - content = ''; - subqueue = ''; - - while (index < length) { - character = value.charAt(index); - - if (character === lineFeed$c) { - subqueue = character; - index++; - - while (index < length) { - character = value.charAt(index); - - if (character !== lineFeed$c) { - break - } - - subqueue += character; - index++; - } - - queue += subqueue; - subqueue = ''; - - while (index < length) { - character = value.charAt(index); - - if (character !== space$b) { - break - } - - subqueue += character; - index++; - } - - if (subqueue.length === 0) { - break - } - - queue += subqueue; - } - - if (queue) { - content += queue; - queue = ''; - } - - content += character; - index++; - } - - subvalue += content; - - content = content.replace(EXPRESSION_INITIAL_TAB, function(line) { - offsets[currentLine] = (offsets[currentLine] || 0) + line.length; - currentLine++; - - return '' - }); - - add = eat(subvalue); - - exit = self.enterBlock(); - content = self.tokenizeBlock(content, now); - exit(); - - return add({ - type: 'footnoteDefinition', - identifier: normalize_1(identifier), - label: identifier, - children: content - }) -} - -var definition_1 = definition; - -var quotationMark = '"'; -var apostrophe = "'"; -var backslash$3 = '\\'; -var lineFeed$d = '\n'; -var tab$c = '\t'; -var space$c = ' '; -var leftSquareBracket$1 = '['; -var rightSquareBracket$1 = ']'; var leftParenthesis = '('; var rightParenthesis$1 = ')'; -var colon$2 = ':'; +var colon$1 = ':'; var lessThan$2 = '<'; var greaterThan$1 = '>'; @@ -35644,7 +38056,7 @@ function definition(eat, value, silent) { while (index < length) { character = value.charAt(index); - if (character !== space$c && character !== tab$c) { + if (character !== space$b && character !== tab$a) { break } @@ -35654,7 +38066,7 @@ function definition(eat, value, silent) { character = value.charAt(index); - if (character !== leftSquareBracket$1) { + if (character !== leftSquareBracket) { return } @@ -35665,9 +38077,9 @@ function definition(eat, value, silent) { while (index < length) { character = value.charAt(index); - if (character === rightSquareBracket$1) { + if (character === rightSquareBracket) { break - } else if (character === backslash$3) { + } else if (character === backslash$2) { queue += character; index++; character = value.charAt(index); @@ -35679,21 +38091,21 @@ function definition(eat, value, silent) { if ( !queue || - value.charAt(index) !== rightSquareBracket$1 || - value.charAt(index + 1) !== colon$2 + value.charAt(index) !== rightSquareBracket || + value.charAt(index + 1) !== colon$1 ) { return } identifier = queue; - subvalue += queue + rightSquareBracket$1 + colon$2; + subvalue += queue + rightSquareBracket + colon$1; index = subvalue.length; queue = ''; while (index < length) { character = value.charAt(index); - if (character !== tab$c && character !== space$c && character !== lineFeed$d) { + if (character !== tab$a && character !== space$b && character !== lineFeed$b) { break } @@ -35759,7 +38171,7 @@ function definition(eat, value, silent) { while (index < length) { character = value.charAt(index); - if (character !== tab$c && character !== space$c && character !== lineFeed$d) { + if (character !== tab$a && character !== space$b && character !== lineFeed$b) { break } @@ -35793,15 +38205,15 @@ function definition(eat, value, silent) { break } - if (character === lineFeed$d) { + if (character === lineFeed$b) { index++; character = value.charAt(index); - if (character === lineFeed$d || character === test) { + if (character === lineFeed$b || character === test) { return } - queue += lineFeed$d; + queue += lineFeed$b; } queue += character; @@ -35826,7 +38238,7 @@ function definition(eat, value, silent) { while (index < length) { character = value.charAt(index); - if (character !== tab$c && character !== space$c) { + if (character !== tab$a && character !== space$b) { break } @@ -35836,7 +38248,7 @@ function definition(eat, value, silent) { character = value.charAt(index); - if (!character || character === lineFeed$d) { + if (!character || character === lineFeed$b) { if (silent) { return true } @@ -35863,8 +38275,8 @@ function definition(eat, value, silent) { function isEnclosedURLCharacter(character) { return ( character !== greaterThan$1 && - character !== leftSquareBracket$1 && - character !== rightSquareBracket$1 + character !== leftSquareBracket && + character !== rightSquareBracket ) } @@ -35873,20 +38285,20 @@ isEnclosedURLCharacter.delimiter = greaterThan$1; // Check if `character` can be inside an unclosed URI. function isUnclosedURLCharacter(character) { return ( - character !== leftSquareBracket$1 && - character !== rightSquareBracket$1 && + character !== leftSquareBracket && + character !== rightSquareBracket && !isWhitespaceCharacter(character) ) } var table_1 = table; -var tab$d = '\t'; -var lineFeed$e = '\n'; -var space$d = ' '; +var tab$b = '\t'; +var lineFeed$c = '\n'; +var space$c = ' '; var dash$4 = '-'; -var colon$3 = ':'; -var backslash$4 = '\\'; +var colon$2 = ':'; +var backslash$3 = '\\'; var verticalBar = '|'; var minColumns = 1; @@ -35936,7 +38348,7 @@ function table(eat, value, silent) { lines = []; while (index < length) { - lineIndex = value.indexOf(lineFeed$e, index); + lineIndex = value.indexOf(lineFeed$c, index); pipeIndex = value.indexOf(verticalBar, index + 1); if (lineIndex === -1) { @@ -35957,7 +38369,7 @@ function table(eat, value, silent) { } // Parse the alignment row. - subvalue = lines.join(lineFeed$e); + subvalue = lines.join(lineFeed$c); alignments = lines.splice(1, 1)[0] || []; index = 0; length = alignments.length; @@ -35984,7 +38396,7 @@ function table(eat, value, silent) { } else if (character === dash$4) { hasDash = true; alignment = alignment || null; - } else if (character === colon$3) { + } else if (character === colon$2) { if (alignment === left) { alignment = center; } else if (hasDash && alignment === null) { @@ -36025,7 +38437,7 @@ function table(eat, value, silent) { // Eat a newline character when this is not the first row. if (position) { - eat(lineFeed$e); + eat(lineFeed$c); } // Eat the row. @@ -36040,7 +38452,7 @@ function table(eat, value, silent) { while (index < length) { character = line.charAt(index); - if (character === tab$d || character === space$d) { + if (character === tab$b || character === space$c) { if (cell) { queue += character; } else { @@ -36060,7 +38472,7 @@ function table(eat, value, silent) { if (queue.length > 1) { if (character) { - subvalue += queue.slice(0, queue.length - 1); + subvalue += queue.slice(0, -1); queue = queue.charAt(queue.length - 1); } else { subvalue += queue; @@ -36089,7 +38501,7 @@ function table(eat, value, silent) { cell += character; - if (character === backslash$4 && index !== length - 2) { + if (character === backslash$3 && index !== length - 2) { cell += line.charAt(index + 1); index++; } @@ -36101,7 +38513,7 @@ function table(eat, value, silent) { // Eat the alignment row. if (!position) { - eat(lineFeed$e + alignments); + eat(lineFeed$c + alignments); } } @@ -36110,9 +38522,9 @@ function table(eat, value, silent) { var paragraph_1 = paragraph; -var tab$e = '\t'; -var lineFeed$f = '\n'; -var space$e = ' '; +var tab$c = '\t'; +var lineFeed$d = '\n'; +var space$d = ' '; var tabSize$4 = 4; @@ -36121,10 +38533,9 @@ function paragraph(eat, value, silent) { var self = this; var settings = self.options; var commonmark = settings.commonmark; - var gfm = settings.gfm; var tokenizers = self.blockTokenizers; var interruptors = self.interruptParagraph; - var index = value.indexOf(lineFeed$f); + var index = value.indexOf(lineFeed$d); var length = value.length; var position; var subvalue; @@ -36140,7 +38551,7 @@ function paragraph(eat, value, silent) { } // Stop if the next character is NEWLINE. - if (value.charAt(index + 1) === lineFeed$f) { + if (value.charAt(index + 1) === lineFeed$d) { break } @@ -36152,10 +38563,10 @@ function paragraph(eat, value, silent) { while (position < length) { character = value.charAt(position); - if (character === tab$e) { + if (character === tab$c) { size = tabSize$4; break - } else if (character === space$e) { + } else if (character === space$d) { size++; } else { break @@ -36164,8 +38575,8 @@ function paragraph(eat, value, silent) { position++; } - if (size >= tabSize$4 && character !== lineFeed$f) { - index = value.indexOf(lineFeed$f, index + 1); + if (size >= tabSize$4 && character !== lineFeed$d) { + index = value.indexOf(lineFeed$d, index + 1); continue } } @@ -36177,19 +38588,8 @@ function paragraph(eat, value, silent) { break } - // Break if the following line starts a list, when already in a list, or - // when in commonmark, or when in gfm mode and the bullet is *not* numeric. - if ( - tokenizers.list.call(self, eat, subvalue, true) && - (self.inList || - commonmark || - (gfm && !isDecimal(trim_1.left(subvalue).charAt(0)))) - ) { - break - } - position = index; - index = value.indexOf(lineFeed$f, index + 1); + index = value.indexOf(lineFeed$d, index + 1); if (index !== -1 && trim_1(value.slice(position, index)) === '') { index = position; @@ -36199,12 +38599,6 @@ function paragraph(eat, value, silent) { subvalue = value.slice(0, index); - if (trim_1(subvalue) === '') { - eat(subvalue); - - return null - } - /* istanbul ignore if - never used (yet) */ if (silent) { return true @@ -36228,15 +38622,15 @@ function locate(value, fromIndex) { var _escape$1 = escape$1; escape$1.locator = _escape; -var lineFeed$g = '\n'; -var backslash$5 = '\\'; +var lineFeed$e = '\n'; +var backslash$4 = '\\'; function escape$1(eat, value, silent) { var self = this; var character; var node; - if (value.charAt(0) === backslash$5) { + if (value.charAt(0) === backslash$4) { character = value.charAt(1); if (self.escape.indexOf(character) !== -1) { @@ -36245,13 +38639,13 @@ function escape$1(eat, value, silent) { return true } - if (character === lineFeed$g) { + if (character === lineFeed$e) { node = {type: 'break'}; } else { node = {type: 'text', value: character}; } - return eat(backslash$5 + character)(node) + return eat(backslash$4 + character)(node) } } } @@ -36390,24 +38784,48 @@ function autoLink(eat, value, silent) { }) } +var ccount_1 = ccount; + +function ccount(value, character) { + var val = String(value); + var count = 0; + var index; + + if (typeof character !== 'string' || character.length !== 1) { + throw new Error('Expected character') + } + + index = val.indexOf(character); + + while (index !== -1) { + count++; + index = val.indexOf(character, index + 1); + } + + return count +} + var url = locate$2; -var protocols = ['https://', 'http://', 'mailto:']; +var values = ['www.', 'http://', 'https://']; function locate$2(value, fromIndex) { - var length = protocols.length; - var index = -1; var min = -1; + var index; + var length; var position; if (!this.options.gfm) { - return -1 + return min } + length = values.length; + index = -1; + while (++index < length) { - position = value.indexOf(protocols[index], fromIndex); + position = value.indexOf(values[index], fromIndex); - if (position !== -1 && (position < min || min === -1)) { + if (position !== -1 && (min === -1 || position < min)) { min = position; } } @@ -36419,126 +38837,335 @@ var url_1 = url$1; url$1.locator = url; url$1.notInLink = true; -var quotationMark$1 = '"'; -var apostrophe$1 = "'"; -var leftParenthesis$1 = '('; -var rightParenthesis$2 = ')'; -var comma$1 = ','; -var dot$2 = '.'; -var colon$4 = ':'; -var semicolon$1 = ';'; -var lessThan$4 = '<'; -var atSign$1 = '@'; -var leftSquareBracket$2 = '['; -var rightSquareBracket$2 = ']'; - -var http = 'http://'; -var https = 'https://'; -var mailto$1 = 'mailto:'; - -var protocols$1 = [http, https, mailto$1]; - -var protocolsLength = protocols$1.length; +var exclamationMark$1 = 33; // '!' +var ampersand$1 = 38; // '&' +var rightParenthesis$2 = 41; // ')' +var asterisk$2 = 42; // '*' +var comma$1 = 44; // ',' +var dash$5 = 45; // '-' +var dot$2 = 46; // '.' +var colon$3 = 58; // ':' +var semicolon$1 = 59; // ';' +var questionMark = 63; // '?' +var lessThan$4 = 60; // '<' +var underscore$2 = 95; // '_' +var tilde$2 = 126; // '~' + +var leftParenthesisCharacter = '('; +var rightParenthesisCharacter = ')'; function url$1(eat, value, silent) { var self = this; - var subvalue; - var content; - var character; + var gfm = self.options.gfm; + var tokenizers = self.inlineTokenizers; + var length = value.length; + var previousDot = -1; + var protocolless = false; + var dots; + var lastTwoPartsStart; + var start; var index; - var position; - var protocol; - var match; - var length; - var queue; - var parenCount; - var nextCharacter; - var tokenizers; + var pathStart; + var path; + var code; + var end; + var leftCount; + var rightCount; + var content; + var children; + var url; var exit; - if (!self.options.gfm) { + if (!gfm) { return } - subvalue = ''; - index = -1; + // `WWW.` doesn’t work. + if (value.slice(0, 4) === 'www.') { + protocolless = true; + index = 4; + } else if (value.slice(0, 7).toLowerCase() === 'http://') { + index = 7; + } else if (value.slice(0, 8).toLowerCase() === 'https://') { + index = 8; + } else { + return + } - while (++index < protocolsLength) { - protocol = protocols$1[index]; - match = value.slice(0, protocol.length); + // Act as if the starting boundary is a dot. + previousDot = index - 1; - if (match.toLowerCase() === protocol) { - subvalue = match; - break + // Parse a valid domain. + start = index; + dots = []; + + while (index < length) { + code = value.charCodeAt(index); + + if (code === dot$2) { + // Dots may not appear after each other. + if (previousDot === index - 1) { + break + } + + dots.push(index); + previousDot = index; + index++; + continue } + + if ( + isDecimal(code) || + isAlphabetical(code) || + code === dash$5 || + code === underscore$2 + ) { + index++; + continue + } + + break } - if (!subvalue) { + // Ignore a final dot: + if (code === dot$2) { + dots.pop(); + index--; + } + + // If there are not dots, exit. + if (dots[0] === undefined) { return } - index = subvalue.length; - length = value.length; - queue = ''; - parenCount = 0; + // If there is an underscore in the last two domain parts, exit: + // `www.example.c_m` and `www.ex_ample.com` are not OK, but + // `www.sub_domain.example.com` is. + lastTwoPartsStart = dots.length < 2 ? start : dots[dots.length - 2] + 1; + + if (value.slice(lastTwoPartsStart, index).indexOf('_') !== -1) { + return + } + /* istanbul ignore if - never used (yet) */ + if (silent) { + return true + } + + end = index; + pathStart = index; + + // Parse a path. while (index < length) { - character = value.charAt(index); + code = value.charCodeAt(index); - if (isWhitespaceCharacter(character) || character === lessThan$4) { + if (isWhitespaceCharacter(code) || code === lessThan$4) { break } - if ( - character === dot$2 || - character === comma$1 || - character === colon$4 || - character === semicolon$1 || - character === quotationMark$1 || - character === apostrophe$1 || - character === rightParenthesis$2 || - character === rightSquareBracket$2 - ) { - nextCharacter = value.charAt(index + 1); + index++; - if (!nextCharacter || isWhitespaceCharacter(nextCharacter)) { - break - } + if ( + code === exclamationMark$1 || + code === asterisk$2 || + code === comma$1 || + code === dot$2 || + code === colon$3 || + code === questionMark || + code === underscore$2 || + code === tilde$2 + ) ; else { + end = index; } + } - if (character === leftParenthesis$1 || character === leftSquareBracket$2) { - parenCount++; + index = end; + + // If the path ends in a closing paren, and the count of closing parens is + // higher than the opening count, then remove the supefluous closing parens. + if (value.charCodeAt(index - 1) === rightParenthesis$2) { + path = value.slice(pathStart, index); + leftCount = ccount_1(path, leftParenthesisCharacter); + rightCount = ccount_1(path, rightParenthesisCharacter); + + while (rightCount > leftCount) { + index = pathStart + path.lastIndexOf(rightParenthesisCharacter); + path = value.slice(pathStart, index); + rightCount--; } + } - if (character === rightParenthesis$2 || character === rightSquareBracket$2) { - parenCount--; + if (value.charCodeAt(index - 1) === semicolon$1) { + // GitHub doesn’t document this, but final semicolons aren’t paret of the + // URL either. + index--; - if (parenCount < 0) { - break + // // If the path ends in what looks like an entity, it’s not part of the path. + if (isAlphabetical(value.charCodeAt(index - 1))) { + end = index - 2; + + while (isAlphabetical(value.charCodeAt(end))) { + end--; + } + + if (value.charCodeAt(end) === ampersand$1) { + index = end; } } + } - queue += character; - index++; + content = value.slice(0, index); + url = parseEntities_1(content, {nonTerminated: false}); + + if (protocolless) { + url = 'http://' + url; } - if (!queue) { + exit = self.enterLink(); + + // Temporarily remove all tokenizers except text in url. + self.inlineTokenizers = {text: tokenizers.text}; + children = self.tokenizeInline(content, eat.now()); + self.inlineTokenizers = tokenizers; + + exit(); + + return eat(content)({type: 'link', title: null, url: url, children: children}) +} + +var plusSign$1 = 43; // '+' +var dash$6 = 45; // '-' +var dot$3 = 46; // '.' +var underscore$3 = 95; // '_' + +var email = locate$3; + +// See: +function locate$3(value, fromIndex) { + var self = this; + var at; + var position; + + if (!this.options.gfm) { + return -1 + } + + at = value.indexOf('@', fromIndex); + + if (at === -1) { + return -1 + } + + position = at; + + if (position === fromIndex || !isGfmAtext(value.charCodeAt(position - 1))) { + return locate$3.call(self, value, at + 1) + } + + while (position > fromIndex && isGfmAtext(value.charCodeAt(position - 1))) { + position--; + } + + return position +} + +function isGfmAtext(code) { + return ( + isDecimal(code) || + isAlphabetical(code) || + code === plusSign$1 || + code === dash$6 || + code === dot$3 || + code === underscore$3 + ) +} + +var email_1 = email$1; +email$1.locator = email; +email$1.notInLink = true; + +var plusSign$2 = 43; // '+' +var dash$7 = 45; // '-' +var dot$4 = 46; // '.' +var atSign$1 = 64; // '@' +var underscore$4 = 95; // '_' + +function email$1(eat, value, silent) { + var self = this; + var gfm = self.options.gfm; + var tokenizers = self.inlineTokenizers; + var index = 0; + var length = value.length; + var firstDot = -1; + var code; + var content; + var children; + var exit; + + if (!gfm) { return } - subvalue += queue; - content = subvalue; + code = value.charCodeAt(index); - if (protocol === mailto$1) { - position = queue.indexOf(atSign$1); + while ( + isDecimal(code) || + isAlphabetical(code) || + code === plusSign$2 || + code === dash$7 || + code === dot$4 || + code === underscore$4 + ) { + code = value.charCodeAt(++index); + } - if (position === -1 || position === length - 1) { - return + if (index === 0) { + return + } + + if (code !== atSign$1) { + return + } + + index++; + + while (index < length) { + code = value.charCodeAt(index); + + if ( + isDecimal(code) || + isAlphabetical(code) || + code === dash$7 || + code === dot$4 || + code === underscore$4 + ) { + index++; + + if (firstDot === -1 && code === dot$4) { + firstDot = index; + } + + continue } - content = content.slice(mailto$1.length); + break } + if ( + firstDot === -1 || + firstDot === index || + code === dash$7 || + code === underscore$4 + ) { + return + } + + if (code === dot$4) { + index--; + } + + content = value.slice(0, index); + /* istanbul ignore if - never used (yet) */ if (silent) { return true @@ -36547,19 +39174,17 @@ function url$1(eat, value, silent) { exit = self.enterLink(); // Temporarily remove all tokenizers except text in url. - tokenizers = self.inlineTokenizers; self.inlineTokenizers = {text: tokenizers.text}; - - content = self.tokenizeInline(content, eat.now()); - + children = self.tokenizeInline(content, eat.now()); self.inlineTokenizers = tokenizers; + exit(); - return eat(subvalue)({ + return eat(content)({ type: 'link', title: null, - url: parseEntities_1(subvalue, {nonTerminated: false}), - children: content + url: 'mailto:' + parseEntities_1(content, {nonTerminated: false}), + children: children }) } @@ -36569,8 +39194,8 @@ var htmlInline = inlineHTML; inlineHTML.locator = tag$1; var lessThan$5 = '<'; -var questionMark = '?'; -var exclamationMark$1 = '!'; +var questionMark$1 = '?'; +var exclamationMark$2 = '!'; var slash$2 = '/'; var htmlLinkOpenExpression = /^= opening) { opening = 0; } - } else if (character === backslash$6) { + } else if (character === backslash$5) { // Allow brackets to be escaped. index++; subqueue += value.charAt(index); - } else if ((!opening || gfm) && character === leftSquareBracket$3) { + } else if ((!opening || gfm) && character === leftSquareBracket$1) { // In GFM mode, brackets in code still count. In all other modes, // they don’t. depth++; - } else if ((!opening || gfm) && character === rightSquareBracket$3) { + } else if ((!opening || gfm) && character === rightSquareBracket$1) { if (depth) { depth--; } else { - // Allow white-space between content and url in GFM mode. - if (!pedantic) { - while (index < length) { - character = value.charAt(index + 1); - - if (!isWhitespaceCharacter(character)) { - break - } - - subqueue += character; - index++; - } - } - - if (value.charAt(index + 1) !== leftParenthesis$2) { + if (value.charAt(index + 1) !== leftParenthesis$1) { return } - subqueue += leftParenthesis$2; + subqueue += leftParenthesis$1; closed = true; index++; @@ -36805,7 +39416,7 @@ function link$2(eat, value, silent) { break } - if (commonmark && character === lineFeed$h) { + if (commonmark && character === lineFeed$f) { return } @@ -36829,9 +39440,9 @@ function link$2(eat, value, silent) { if ( subqueue && - (character === quotationMark$2 || - character === apostrophe$2 || - (commonmark && character === leftParenthesis$2)) + (character === quotationMark$1 || + character === apostrophe$1 || + (commonmark && character === leftParenthesis$1)) ) { break } @@ -36843,7 +39454,7 @@ function link$2(eat, value, silent) { subqueue += character; } else { - if (character === leftParenthesis$2) { + if (character === leftParenthesis$1) { depth++; } else if (character === rightParenthesis$3) { if (depth === 0) { @@ -36856,8 +39467,8 @@ function link$2(eat, value, silent) { queue += subqueue; subqueue = ''; - if (character === backslash$6) { - queue += backslash$6; + if (character === backslash$5) { + queue += backslash$5; character = value.charAt(++index); } @@ -36892,14 +39503,14 @@ function link$2(eat, value, silent) { // Eat the title. if ( queue && - (character === quotationMark$2 || - character === apostrophe$2 || - (commonmark && character === leftParenthesis$2)) + (character === quotationMark$1 || + character === apostrophe$1 || + (commonmark && character === leftParenthesis$1)) ) { index++; subvalue += character; queue = ''; - marker = character === leftParenthesis$2 ? rightParenthesis$3 : character; + marker = character === leftParenthesis$1 ? rightParenthesis$3 : character; beforeTitle = subvalue; // In commonmark-mode, things are pretty easy: the marker cannot occur @@ -36913,8 +39524,8 @@ function link$2(eat, value, silent) { break } - if (character === backslash$6) { - queue += backslash$6; + if (character === backslash$5) { + queue += backslash$5; character = value.charAt(++index); } @@ -37012,31 +39623,27 @@ function link$2(eat, value, silent) { } var reference_1 = reference; -reference.locator = link$1; +reference.locator = link$2; -var link$3 = 'link'; +var link$4 = 'link'; var image$1 = 'image'; -var footnote = 'footnote'; var shortcut = 'shortcut'; var collapsed = 'collapsed'; var full = 'full'; -var space$f = ' '; -var exclamationMark$3 = '!'; -var leftSquareBracket$4 = '['; -var backslash$7 = '\\'; -var rightSquareBracket$4 = ']'; -var caret$2 = '^'; +var exclamationMark$4 = '!'; +var leftSquareBracket$2 = '['; +var backslash$6 = '\\'; +var rightSquareBracket$2 = ']'; function reference(eat, value, silent) { var self = this; var commonmark = self.options.commonmark; - var footnotes = self.options.footnotes; var character = value.charAt(0); var index = 0; var length = value.length; var subvalue = ''; var intro = ''; - var type = link$3; + var type = link$4; var referenceType = shortcut; var content; var identifier; @@ -37048,13 +39655,13 @@ function reference(eat, value, silent) { var depth; // Check whether we’re eating an image. - if (character === exclamationMark$3) { + if (character === exclamationMark$4) { type = image$1; intro = character; character = value.charAt(++index); } - if (character !== leftSquareBracket$4) { + if (character !== leftSquareBracket$2) { return } @@ -37062,29 +39669,16 @@ function reference(eat, value, silent) { intro += character; queue = ''; - // Check whether we’re eating a footnote. - if (footnotes && value.charAt(index) === caret$2) { - // Exit if `![^` is found, so the `!` will be seen as text after this, - // and we’ll enter this function again when `[^` is found. - if (type === image$1) { - return - } - - intro += caret$2; - index++; - type = footnote; - } - // Eat the text. depth = 0; while (index < length) { character = value.charAt(index); - if (character === leftSquareBracket$4) { + if (character === leftSquareBracket$2) { bracketed = true; depth++; - } else if (character === rightSquareBracket$4) { + } else if (character === rightSquareBracket$2) { if (!depth) { break } @@ -37092,8 +39686,8 @@ function reference(eat, value, silent) { depth--; } - if (character === backslash$7) { - queue += backslash$7; + if (character === backslash$6) { + queue += backslash$6; character = value.charAt(++index); } @@ -37105,7 +39699,7 @@ function reference(eat, value, silent) { content = queue; character = value.charAt(index); - if (character !== rightSquareBracket$4) { + if (character !== rightSquareBracket$2) { return } @@ -37131,13 +39725,7 @@ function reference(eat, value, silent) { character = value.charAt(index); - // Inline footnotes cannot have a label. - // If footnotes are enabled, link labels cannot start with a caret. - if ( - type !== footnote && - character === leftSquareBracket$4 && - (!footnotes || value.charAt(index + 1) !== caret$2) - ) { + if (character === leftSquareBracket$2) { identifier = ''; queue += character; index++; @@ -37145,12 +39733,12 @@ function reference(eat, value, silent) { while (index < length) { character = value.charAt(index); - if (character === leftSquareBracket$4 || character === rightSquareBracket$4) { + if (character === leftSquareBracket$2 || character === rightSquareBracket$2) { break } - if (character === backslash$7) { - identifier += backslash$7; + if (character === backslash$6) { + identifier += backslash$6; character = value.charAt(++index); } @@ -37160,7 +39748,7 @@ function reference(eat, value, silent) { character = value.charAt(index); - if (character === rightSquareBracket$4) { + if (character === rightSquareBracket$2) { referenceType = identifier ? full : collapsed; queue += identifier + character; index++; @@ -37185,7 +39773,7 @@ function reference(eat, value, silent) { subvalue = intro + subvalue; - if (type === link$3 && self.inLink) { + if (type === link$4 && self.inLink) { return null } @@ -37194,13 +39782,6 @@ function reference(eat, value, silent) { return true } - if (type === footnote && content.indexOf(space$f) !== -1) { - return eat(subvalue)({ - type: footnote, - children: this.tokenizeInline(content, eat.now()) - }) - } - now = eat.now(); now.column += intro.length; now.offset += intro.length; @@ -37209,27 +39790,24 @@ function reference(eat, value, silent) { node = { type: type + 'Reference', identifier: normalize_1(identifier), - label: identifier + label: identifier, + referenceType: referenceType }; - if (type === link$3 || type === image$1) { - node.referenceType = referenceType; - } - - if (type === link$3) { + if (type === link$4) { exit = self.enterLink(); node.children = self.tokenizeInline(content, now); exit(); - } else if (type === image$1) { + } else { node.alt = self.decode.raw(self.unescape(content), now) || null; } return eat(subvalue)(node) } -var strong = locate$4; +var strong = locate$5; -function locate$4(value, fromIndex) { +function locate$5(value, fromIndex) { var asterisk = value.indexOf('**', fromIndex); var underscore = value.indexOf('__', fromIndex); @@ -37247,9 +39825,9 @@ function locate$4(value, fromIndex) { var strong_1 = strong$1; strong$1.locator = strong; -var backslash$8 = '\\'; -var asterisk$2 = '*'; -var underscore$2 = '_'; +var backslash$7 = '\\'; +var asterisk$3 = '*'; +var underscore$5 = '_'; function strong$1(eat, value, silent) { var self = this; @@ -37261,10 +39839,10 @@ function strong$1(eat, value, silent) { var queue; var subvalue; var length; - var prev; + var previous; if ( - (character !== asterisk$2 && character !== underscore$2) || + (character !== asterisk$3 && character !== underscore$5) || value.charAt(++index) !== character ) { return @@ -37283,13 +39861,13 @@ function strong$1(eat, value, silent) { } while (index < length) { - prev = character; + previous = character; character = value.charAt(index); if ( character === marker && value.charAt(index + 1) === marker && - (!pedantic || !isWhitespaceCharacter(prev)) + (!pedantic || !isWhitespaceCharacter(previous)) ) { character = value.charAt(index + 2); @@ -37314,7 +39892,7 @@ function strong$1(eat, value, silent) { } } - if (!pedantic && character === backslash$8) { + if (!pedantic && character === backslash$7) { queue += character; character = value.charAt(++index); } @@ -37337,9 +39915,9 @@ function wordCharacter(character) { ) } -var emphasis = locate$5; +var emphasis = locate$6; -function locate$5(value, fromIndex) { +function locate$6(value, fromIndex) { var asterisk = value.indexOf('*', fromIndex); var underscore = value.indexOf('_', fromIndex); @@ -37357,9 +39935,9 @@ function locate$5(value, fromIndex) { var emphasis_1 = emphasis$1; emphasis$1.locator = emphasis; -var asterisk$3 = '*'; -var underscore$3 = '_'; -var backslash$9 = '\\'; +var asterisk$4 = '*'; +var underscore$6 = '_'; +var backslash$8 = '\\'; function emphasis$1(eat, value, silent) { var self = this; @@ -37371,9 +39949,9 @@ function emphasis$1(eat, value, silent) { var queue; var subvalue; var length; - var prev; + var previous; - if (character !== asterisk$3 && character !== underscore$3) { + if (character !== asterisk$4 && character !== underscore$6) { return } @@ -37390,18 +39968,18 @@ function emphasis$1(eat, value, silent) { } while (index < length) { - prev = character; + previous = character; character = value.charAt(index); - if (character === marker && (!pedantic || !isWhitespaceCharacter(prev))) { + if (character === marker && (!pedantic || !isWhitespaceCharacter(previous))) { character = value.charAt(++index); if (character !== marker) { - if (!trim_1(queue) || prev === marker) { + if (!trim_1(queue) || previous === marker) { return } - if (!pedantic && marker === underscore$3 && isWordCharacter(character)) { + if (!pedantic && marker === underscore$6 && isWordCharacter(character)) { queue += marker; continue } @@ -37424,7 +40002,7 @@ function emphasis$1(eat, value, silent) { queue += marker; } - if (!pedantic && character === backslash$9) { + if (!pedantic && character === backslash$8) { queue += character; character = value.charAt(++index); } @@ -37434,16 +40012,16 @@ function emphasis$1(eat, value, silent) { } } -var _delete = locate$6; +var _delete = locate$7; -function locate$6(value, fromIndex) { +function locate$7(value, fromIndex) { return value.indexOf('~~', fromIndex) } var _delete$1 = strikethrough; strikethrough.locator = _delete; -var tilde$2 = '~'; +var tilde$3 = '~'; var fence = '~~'; function strikethrough(eat, value, silent) { @@ -37458,8 +40036,8 @@ function strikethrough(eat, value, silent) { if ( !self.options.gfm || - value.charAt(0) !== tilde$2 || - value.charAt(1) !== tilde$2 || + value.charAt(0) !== tilde$3 || + value.charAt(1) !== tilde$3 || isWhitespaceCharacter(value.charAt(2)) ) { return @@ -37475,8 +40053,8 @@ function strikethrough(eat, value, silent) { character = value.charAt(index); if ( - character === tilde$2 && - previous === tilde$2 && + character === tilde$3 && + previous === tilde$3 && (!preceding || !isWhitespaceCharacter(preceding)) ) { /* istanbul ignore if - never used (yet) */ @@ -37496,17 +40074,17 @@ function strikethrough(eat, value, silent) { } } -var codeInline = locate$7; +var codeInline = locate$8; -function locate$7(value, fromIndex) { +function locate$8(value, fromIndex) { return value.indexOf('`', fromIndex) } var codeInline$1 = inlineCode; inlineCode.locator = codeInline; -var lineFeed$i = 10; // '\n' -var space$g = 32; // ' ' +var lineFeed$g = 10; // '\n' +var space$e = 32; // ' ' var graveAccent$2 = 96; // '`' function inlineCode(eat, value, silent) { @@ -37579,8 +40157,8 @@ function inlineCode(eat, value, silent) { if ( length - index > 2 && - (code === space$g || code === lineFeed$i) && - (next === space$g || next === lineFeed$i) + (code === space$e || code === lineFeed$g) && + (next === space$e || next === lineFeed$g) ) { index++; length--; @@ -37588,7 +40166,7 @@ function inlineCode(eat, value, silent) { while (index < length) { code = value.charCodeAt(index); - if (code !== space$g && code !== lineFeed$i) { + if (code !== space$e && code !== lineFeed$g) { found = true; break } @@ -37608,9 +40186,9 @@ function inlineCode(eat, value, silent) { }) } -var _break = locate$8; +var _break = locate$9; -function locate$8(value, fromIndex) { +function locate$9(value, fromIndex) { var index = value.indexOf('\n', fromIndex); while (index > fromIndex) { @@ -37627,8 +40205,8 @@ function locate$8(value, fromIndex) { var _break$1 = hardBreak; hardBreak.locator = _break; -var space$h = ' '; -var lineFeed$j = '\n'; +var space$f = ' '; +var lineFeed$h = '\n'; var minBreakLength = 2; function hardBreak(eat, value, silent) { @@ -37640,7 +40218,7 @@ function hardBreak(eat, value, silent) { while (++index < length) { character = value.charAt(index); - if (character === lineFeed$j) { + if (character === lineFeed$h) { if (index < minBreakLength) { return } @@ -37655,7 +40233,7 @@ function hardBreak(eat, value, silent) { return eat(queue)({type: 'break'}) } - if (character !== space$h) { + if (character !== space$f) { return } @@ -37737,20 +40315,20 @@ function Parser(doc, file) { this.decode = decode(this); } -var proto$3 = Parser.prototype; +var proto$4 = Parser.prototype; // Expose core. -proto$3.setOptions = setOptions_1; -proto$3.parse = parse_1$3; +proto$4.setOptions = setOptions_1; +proto$4.parse = parse_1$3; // Expose `defaults`. -proto$3.options = defaults$2; +proto$4.options = defaults$2; // Enter and exit helpers. -proto$3.exitStart = stateToggle('atStart', true); -proto$3.enterList = stateToggle('inList', false); -proto$3.enterLink = stateToggle('inLink', false); -proto$3.enterBlock = stateToggle('inBlock', false); +proto$4.exitStart = stateToggle('atStart', true); +proto$4.enterList = stateToggle('inList', false); +proto$4.enterLink = stateToggle('inLink', false); +proto$4.enterBlock = stateToggle('inBlock', false); // Nodes that can interupt a paragraph: // @@ -37760,15 +40338,15 @@ proto$3.enterBlock = stateToggle('inBlock', false); // ``` // // In the above example, the thematic break “interupts” the paragraph. -proto$3.interruptParagraph = [ +proto$4.interruptParagraph = [ ['thematicBreak'], + ['list'], ['atxHeading'], ['fencedCode'], ['blockquote'], ['html'], ['setextHeading', {commonmark: false}], - ['definition', {commonmark: false}], - ['footnote', {commonmark: false}] + ['definition', {commonmark: false}] ]; // Nodes that can interupt a list: @@ -37779,12 +40357,11 @@ proto$3.interruptParagraph = [ // ``` // // In the above example, the thematic break “interupts” the list. -proto$3.interruptList = [ +proto$4.interruptList = [ ['atxHeading', {pedantic: false}], ['fencedCode', {pedantic: false}], ['thematicBreak', {pedantic: false}], - ['definition', {commonmark: false}], - ['footnote', {commonmark: false}] + ['definition', {commonmark: false}] ]; // Nodes that can interupt a blockquote: @@ -37795,7 +40372,7 @@ proto$3.interruptList = [ // ``` // // In the above example, the thematic break “interupts” the blockquote. -proto$3.interruptBlockquote = [ +proto$4.interruptBlockquote = [ ['indentedCode', {commonmark: true}], ['fencedCode', {commonmark: true}], ['atxHeading', {commonmark: true}], @@ -37803,13 +40380,12 @@ proto$3.interruptBlockquote = [ ['thematicBreak', {commonmark: true}], ['html', {commonmark: true}], ['list', {commonmark: true}], - ['definition', {commonmark: false}], - ['footnote', {commonmark: false}] + ['definition', {commonmark: false}] ]; // Handlers. -proto$3.blockTokenizers = { - newline: newline_1, +proto$4.blockTokenizers = { + blankLine: blankLine_1, indentedCode: codeIndented, fencedCode: codeFenced, blockquote: blockquote_1, @@ -37818,16 +40394,16 @@ proto$3.blockTokenizers = { list: list_1, setextHeading: headingSetext, html: htmlBlock, - footnote: footnoteDefinition_1, definition: definition_1, table: table_1, paragraph: paragraph_1 }; -proto$3.inlineTokenizers = { +proto$4.inlineTokenizers = { escape: _escape$1, autoLink: autoLink_1, url: url_1, + email: email_1, html: htmlInline, link: link_1, reference: reference_1, @@ -37840,13 +40416,13 @@ proto$3.inlineTokenizers = { }; // Expose precedence. -proto$3.blockMethods = keys$1(proto$3.blockTokenizers); -proto$3.inlineMethods = keys$1(proto$3.inlineTokenizers); +proto$4.blockMethods = keys$1(proto$4.blockTokenizers); +proto$4.inlineMethods = keys$1(proto$4.inlineTokenizers); // Tokenizers. -proto$3.tokenizeBlock = tokenizer('block'); -proto$3.tokenizeInline = tokenizer('inline'); -proto$3.tokenizeFactory = tokenizer; +proto$4.tokenizeBlock = tokenizer('block'); +proto$4.tokenizeInline = tokenizer('inline'); +proto$4.tokenizeFactory = tokenizer; // Get all keys in `value`. function keys$1(value) { @@ -37915,9 +40491,8 @@ var defaults$3 = { entities: 'false', setext: false, closeAtx: false, - looseTable: false, - spacedTable: true, - paddedTable: true, + tableCellPadding: true, + tablePipeAlign: true, stringLength: stringLength, incrementListMarker: true, fences: false, @@ -38165,7 +40740,7 @@ const Scaron$1 = "Š"; const scaron$1 = "š"; const Yuml$1 = "Ÿ"; const circ$1 = "ˆ"; -const tilde$3 = "˜"; +const tilde$4 = "˜"; const ensp$1 = " "; const emsp$1 = " "; const thinsp$1 = " "; @@ -38418,7 +40993,7 @@ var index$4 = { scaron: scaron$1, Yuml: Yuml$1, circ: circ$1, - tilde: tilde$3, + tilde: tilde$4, ensp: ensp$1, emsp: emsp$1, thinsp: thinsp$1, @@ -38674,7 +41249,7 @@ var characterEntitiesHtml4 = /*#__PURE__*/Object.freeze({ scaron: scaron$1, Yuml: Yuml$1, circ: circ$1, - tilde: tilde$3, + tilde: tilde$4, ensp: ensp$1, emsp: emsp$1, thinsp: thinsp$1, @@ -38728,6 +41303,9 @@ encode.escape = escape$2; var own$5 = {}.hasOwnProperty; +// Characters +var equalsTo$2 = 61; + // List of enforced escapes. var escapes$1 = ['"', "'", '<', '>', '&', '`']; @@ -38762,19 +41340,19 @@ function encode(value, options) { .replace(surrogatePair, replaceSurrogatePair) .replace(bmp, replace) - function replaceSurrogatePair(pair, pos, val) { + function replaceSurrogatePair(pair, pos, slice) { return toHexReference( (pair.charCodeAt(0) - 0xd800) * 0x400 + pair.charCodeAt(1) - 0xdc00 + 0x10000, - val.charAt(pos + 2), + slice.charCodeAt(pos + 2), omit ) } - function replace(char, pos, val) { - return one$1(char, val.charAt(pos + 1), settings) + function replace(char, pos, slice) { + return one$1(char, slice.charCodeAt(pos + 1), settings) } } @@ -38834,7 +41412,7 @@ function toNamed(name, next, omit, attribute) { omit && own$5.call(legacy, name) && dangerous$2.indexOf(name) === -1 && - (!attribute || (next && next !== '=' && !isAlphanumerical(next))) + (!attribute || (next && next !== equalsTo$2 && !isAlphanumerical(next))) ) { return value } @@ -38881,7 +41459,7 @@ var isAlphanumeric = function (str) { var entityPrefixLength = length; -var ampersand$1 = '&'; +var ampersand$2 = '&'; // Returns the length of HTML entity that is a prefix of the given string // (excluding the ampersand), 0 if it does not start with an entity. @@ -38890,39 +41468,39 @@ function length(value) { /* istanbul ignore if - Currently also tested for at implemention, but we * keep it here because that’s proper. */ - if (value.charAt(0) !== ampersand$1) { + if (value.charAt(0) !== ampersand$2) { return 0 } - prefix = value.split(ampersand$1, 2).join(ampersand$1); + prefix = value.split(ampersand$2, 2).join(ampersand$2); return prefix.length - parseEntities_1(prefix).length } var _escape$2 = factory$6; -var tab$f = '\t'; -var lineFeed$k = '\n'; -var space$i = ' '; +var tab$d = '\t'; +var lineFeed$i = '\n'; +var space$g = ' '; var numberSign$2 = '#'; -var ampersand$2 = '&'; -var leftParenthesis$3 = '('; +var ampersand$3 = '&'; +var leftParenthesis$2 = '('; var rightParenthesis$4 = ')'; -var asterisk$4 = '*'; -var plusSign$1 = '+'; -var dash$5 = '-'; -var dot$3 = '.'; -var colon$5 = ':'; +var asterisk$5 = '*'; +var plusSign$3 = '+'; +var dash$8 = '-'; +var dot$5 = '.'; +var colon$4 = ':'; var lessThan$7 = '<'; var greaterThan$4 = '>'; -var leftSquareBracket$5 = '['; -var backslash$a = '\\'; -var rightSquareBracket$5 = ']'; -var underscore$4 = '_'; +var leftSquareBracket$3 = '['; +var backslash$9 = '\\'; +var rightSquareBracket$3 = ']'; +var underscore$7 = '_'; var graveAccent$3 = '`'; var verticalBar$1 = '|'; -var tilde$4 = '~'; -var exclamationMark$4 = '!'; +var tilde$5 = '~'; +var exclamationMark$5 = '!'; var entities$1 = { '<': '<', @@ -38933,9 +41511,9 @@ var entities$1 = { }; var shortcut$1 = 'shortcut'; -var mailto$2 = 'mailto'; -var https$1 = 'https'; -var http$1 = 'http'; +var mailto$1 = 'mailto'; +var https = 'https'; +var http = 'http'; var blankExpression = /\n\s*$/; @@ -38949,10 +41527,10 @@ function factory$6(options) { var gfm = options.gfm; var commonmark = options.commonmark; var pedantic = options.pedantic; - var markers = commonmark ? [dot$3, rightParenthesis$4] : [dot$3]; + var markers = commonmark ? [dot$5, rightParenthesis$4] : [dot$5]; var siblings = parent && parent.children; var index = siblings && siblings.indexOf(node); - var prev = siblings && siblings[index - 1]; + var previous = siblings && siblings[index - 1]; var next = siblings && siblings[index + 1]; var length = value.length; var escapable = markdownEscapes(options); @@ -38966,8 +41544,8 @@ function factory$6(options) { var offset; var replace; - if (prev) { - afterNewLine = text$1(prev) && blankExpression.test(prev.value); + if (previous) { + afterNewLine = text$1(previous) && blankExpression.test(previous.value); } else { afterNewLine = !parent || parent.type === 'root' || parent.type === 'paragraph'; @@ -38980,34 +41558,34 @@ function factory$6(options) { if (character === '\n') { afterNewLine = true; } else if ( - character === backslash$a || + character === backslash$9 || character === graveAccent$3 || - character === asterisk$4 || - character === leftSquareBracket$5 || + character === asterisk$5 || + character === leftSquareBracket$3 || character === lessThan$7 || - (character === ampersand$2 && entityPrefixLength(value.slice(position)) > 0) || - (character === rightSquareBracket$5 && self.inLink) || - (gfm && character === tilde$4 && value.charAt(position + 1) === tilde$4) || + (character === ampersand$3 && entityPrefixLength(value.slice(position)) > 0) || + (character === rightSquareBracket$3 && self.inLink) || + (gfm && character === tilde$5 && value.charAt(position + 1) === tilde$5) || (gfm && character === verticalBar$1 && (self.inTable || alignment(value, position))) || - (character === underscore$4 && + (character === underscore$7 && // Delegate leading/trailing underscores to the multinode version below. position > 0 && position < length - 1 && (pedantic || !isAlphanumeric(value.charAt(position - 1)) || !isAlphanumeric(value.charAt(position + 1)))) || - (gfm && !self.inLink && character === colon$5 && protocol(queue.join(''))) + (gfm && !self.inLink && character === colon$4 && protocol(queue.join(''))) ) { replace = true; } else if (afterNewLine) { if ( character === greaterThan$4 || character === numberSign$2 || - character === asterisk$4 || - character === dash$5 || - character === plusSign$1 + character === asterisk$5 || + character === dash$8 || + character === plusSign$3 ) { replace = true; } else if (isDecimal(character)) { @@ -39024,7 +41602,7 @@ function factory$6(options) { if (markers.indexOf(value.charAt(offset)) !== -1) { next = value.charAt(offset + 1); - if (!next || next === space$i || next === tab$f || next === lineFeed$k) { + if (!next || next === space$g || next === tab$d || next === lineFeed$i) { queue.push(value.slice(position, offset)); position = offset; character = value.charAt(position); @@ -39045,18 +41623,18 @@ function factory$6(options) { if (siblings && text$1(node)) { // Check for an opening parentheses after a link-reference (which can be // joined by white-space). - if (prev && prev.referenceType === shortcut$1) { + if (previous && previous.referenceType === shortcut$1) { position = -1; length = escaped.length; while (++position < length) { character = escaped[position]; - if (character === space$i || character === tab$f) { + if (character === space$g || character === tab$d) { continue } - if (character === leftParenthesis$3 || character === colon$5) { + if (character === leftParenthesis$2 || character === colon$4) { escaped[position] = one(character); } @@ -39068,9 +41646,9 @@ function factory$6(options) { if ( text$1(next) && position === length && - next.value.charAt(0) === leftParenthesis$3 + next.value.charAt(0) === leftParenthesis$2 ) { - escaped.push(backslash$a); + escaped.push(backslash$9); } } @@ -39079,67 +41657,67 @@ function factory$6(options) { if ( gfm && !self.inLink && - text$1(prev) && - value.charAt(0) === colon$5 && - protocol(prev.value.slice(-6)) + text$1(previous) && + value.charAt(0) === colon$4 && + protocol(previous.value.slice(-6)) ) { - escaped[0] = one(colon$5); + escaped[0] = one(colon$4); } // Escape ampersand if it would otherwise start an entity. if ( text$1(next) && - value.charAt(length - 1) === ampersand$2 && - entityPrefixLength(ampersand$2 + next.value) !== 0 + value.charAt(length - 1) === ampersand$3 && + entityPrefixLength(ampersand$3 + next.value) !== 0 ) { - escaped[escaped.length - 1] = one(ampersand$2); + escaped[escaped.length - 1] = one(ampersand$3); } // Escape exclamation marks immediately followed by links. if ( next && next.type === 'link' && - value.charAt(length - 1) === exclamationMark$4 + value.charAt(length - 1) === exclamationMark$5 ) { - escaped[escaped.length - 1] = one(exclamationMark$4); + escaped[escaped.length - 1] = one(exclamationMark$5); } // Escape double tildes in GFM. if ( gfm && text$1(next) && - value.charAt(length - 1) === tilde$4 && - next.value.charAt(0) === tilde$4 + value.charAt(length - 1) === tilde$5 && + next.value.charAt(0) === tilde$5 ) { - escaped.splice(escaped.length - 1, 0, backslash$a); + escaped.splice(-1, 0, backslash$9); } // Escape underscores, but not mid-word (unless in pedantic mode). - wordCharBefore = text$1(prev) && isAlphanumeric(prev.value.slice(-1)); + wordCharBefore = text$1(previous) && isAlphanumeric(previous.value.slice(-1)); wordCharAfter = text$1(next) && isAlphanumeric(next.value.charAt(0)); if (length === 1) { if ( - value === underscore$4 && + value === underscore$7 && (pedantic || !wordCharBefore || !wordCharAfter) ) { - escaped.unshift(backslash$a); + escaped.unshift(backslash$9); } } else { if ( - value.charAt(0) === underscore$4 && + value.charAt(0) === underscore$7 && (pedantic || !wordCharBefore || !isAlphanumeric(value.charAt(1))) ) { - escaped.unshift(backslash$a); + escaped.unshift(backslash$9); } if ( - value.charAt(length - 1) === underscore$4 && + value.charAt(length - 1) === underscore$7 && (pedantic || !wordCharAfter || !isAlphanumeric(value.charAt(length - 2))) ) { - escaped.splice(escaped.length - 1, 0, backslash$a); + escaped.splice(-1, 0, backslash$9); } } } @@ -39149,15 +41727,15 @@ function factory$6(options) { function one(character) { return escapable.indexOf(character) === -1 ? entities$1[character] - : backslash$a + character + : backslash$9 + character } } } // Check if `index` in `value` is inside an alignment row. function alignment(value, index) { - var start = value.lastIndexOf(lineFeed$k, index); - var end = value.indexOf(lineFeed$k, index); + var start = value.lastIndexOf(lineFeed$i, index); + var end = value.indexOf(lineFeed$i, index); var char; end = end === -1 ? value.length : end; @@ -39166,9 +41744,9 @@ function alignment(value, index) { char = value.charAt(start); if ( - char !== colon$5 && - char !== dash$5 && - char !== space$i && + char !== colon$4 && + char !== dash$8 && + char !== space$g && char !== verticalBar$1 ) { return false @@ -39185,8 +41763,8 @@ function text$1(node) { // Check if `value` ends in a protocol. function protocol(value) { - var val = value.slice(-6).toLowerCase(); - return val === mailto$2 || val.slice(-5) === https$1 || val.slice(-4) === http$1 + var tail = value.slice(-6).toLowerCase(); + return tail === mailto$1 || tail.slice(-5) === https || tail.slice(-4) === http } var setOptions_1$1 = setOptions$1; @@ -39445,10 +42023,10 @@ function all(parent) { var block_1 = block$1; -var lineFeed$l = '\n'; +var lineFeed$j = '\n'; -var blank$1 = lineFeed$l + lineFeed$l; -var triple = blank$1 + lineFeed$l; +var blank$1 = lineFeed$j + lineFeed$j; +var triple = blank$1 + lineFeed$j; var comment$1 = blank$1 + '' + blank$1; // Stringify a block node with block children (e.g., `root` or `blockquote`). @@ -39463,14 +42041,14 @@ function block$1(node) { var children = node.children; var length = children.length; var index = -1; - var prev; + var previous; var child; while (++index < length) { - prev = child; + previous = child; child = children[index]; - if (prev) { + if (previous) { // A list preceding another list that are equally ordered, or a // list preceding an indented code block, need a gap between them, // so as not to see them as one list, or content of the list, @@ -39480,8 +42058,8 @@ function block$1(node) { // so we opt for an empty, invisible comment. In other flavours, // two blank lines are fine. if ( - prev.type === 'list' && - ((child.type === 'list' && prev.ordered === child.ordered) || + previous.type === 'list' && + ((child.type === 'list' && previous.ordered === child.ordered) || (child.type === 'code' && !child.lang && !fences)) ) { values.push(gap); @@ -39498,10 +42076,10 @@ function block$1(node) { var orderedItems_1 = orderedItems; -var lineFeed$m = '\n'; -var dot$4 = '.'; +var lineFeed$k = '\n'; +var dot$6 = '.'; -var blank$2 = lineFeed$m + lineFeed$m; +var blank$2 = lineFeed$k + lineFeed$k; // Visit ordered list items. // @@ -39531,18 +42109,18 @@ function orderedItems(node) { start = start == null ? 1 : start; while (++index < length) { - bullet = (increment ? start + index : start) + dot$4; + bullet = (increment ? start + index : start) + dot$6; values[index] = fn.call(self, children[index], node, index, bullet); } - return values.join(node.spread ? blank$2 : lineFeed$m) + return values.join(node.spread ? blank$2 : lineFeed$k) } var unorderedItems_1 = unorderedItems; -var lineFeed$n = '\n'; +var lineFeed$l = '\n'; -var blank$3 = lineFeed$n + lineFeed$n; +var blank$3 = lineFeed$l + lineFeed$l; // Visit unordered list items. Uses `options.bullet` as each item’s bullet. function unorderedItems(node) { @@ -39558,20 +42136,20 @@ function unorderedItems(node) { values[index] = fn.call(self, children[index], node, index, bullet); } - return values.join(node.spread ? blank$3 : lineFeed$n) + return values.join(node.spread ? blank$3 : lineFeed$l) } var root_1 = root$1; -var lineFeed$o = '\n'; +var lineFeed$m = '\n'; // Stringify a root. // Adds a final newline to ensure valid POSIX files. */ function root$1(node) { var doc = this.block(node); - if (doc.charAt(doc.length - 1) !== lineFeed$o) { - doc += lineFeed$o; + if (doc.charAt(doc.length - 1) !== lineFeed$m) { + doc += lineFeed$m; } return doc @@ -39597,11 +42175,11 @@ function text$2(node, parent) { var heading_1 = heading; -var lineFeed$p = '\n'; -var space$j = ' '; +var lineFeed$n = '\n'; +var space$h = ' '; var numberSign$3 = '#'; -var dash$6 = '-'; -var equalsTo$2 = '='; +var dash$9 = '-'; +var equalsTo$3 = '='; // Stringify a heading. // @@ -39634,13 +42212,13 @@ function heading(node) { if (setext && depth < 3) { return ( - content + lineFeed$p + repeatString(depth === 1 ? equalsTo$2 : dash$6, content.length) + content + lineFeed$n + repeatString(depth === 1 ? equalsTo$3 : dash$9, content.length) ) } prefix = repeatString(numberSign$3, node.depth); - return prefix + space$j + content + (closeAtx ? space$j + prefix : '') + return prefix + space$h + content + (closeAtx ? space$h + prefix : '') } var paragraph_1$1 = paragraph$1; @@ -39651,12 +42229,12 @@ function paragraph$1(node) { var blockquote_1$1 = blockquote$1; -var lineFeed$q = '\n'; -var space$k = ' '; +var lineFeed$o = '\n'; +var space$i = ' '; var greaterThan$5 = '>'; function blockquote$1(node) { - var values = this.block(node).split(lineFeed$q); + var values = this.block(node).split(lineFeed$o); var result = []; var length = values.length; var index = -1; @@ -39664,10 +42242,10 @@ function blockquote$1(node) { while (++index < length) { value = values[index]; - result[index] = (value ? space$k : '') + value; + result[index] = (value ? space$i : '') + value; } - return greaterThan$5 + result.join(lineFeed$q + greaterThan$5) + return greaterThan$5 + result.join(lineFeed$o + greaterThan$5) } var list_1$1 = list$1; @@ -39679,17 +42257,17 @@ function list$1(node) { var pad_1 = pad$1; -var lineFeed$r = '\n'; -var space$l = ' '; +var lineFeed$p = '\n'; +var space$j = ' '; var tabSize$5 = 4; // Pad `value` with `level * tabSize` spaces. Respects lines. Ignores empty // lines. function pad$1(value, level) { - var values = value.split(lineFeed$r); + var values = value.split(lineFeed$p); var index = values.length; - var padding = repeatString(space$l, level * tabSize$5); + var padding = repeatString(space$j, level * tabSize$5); while (index--) { if (values[index].length !== 0) { @@ -39697,19 +42275,19 @@ function pad$1(value, level) { } } - return values.join(lineFeed$r) + return values.join(lineFeed$p) } var listItem_1 = listItem$1; -var lineFeed$s = '\n'; -var space$m = ' '; -var leftSquareBracket$6 = '['; -var rightSquareBracket$6 = ']'; +var lineFeed$q = '\n'; +var space$k = ' '; +var leftSquareBracket$4 = '['; +var rightSquareBracket$4 = ']'; var lowercaseX$2 = 'x'; var ceil = Math.ceil; -var blank$4 = lineFeed$s + lineFeed$s; +var blank$4 = lineFeed$q + lineFeed$q; var tabSize$6 = 4; @@ -39744,26 +42322,26 @@ function listItem$1(node, parent, position, bullet) { values[index] = self.visit(children[index], node); } - value = values.join(spread ? blank$4 : lineFeed$s); + value = values.join(spread ? blank$4 : lineFeed$q); if (typeof checked === 'boolean') { // Note: I’d like to be able to only add the space between the check and // the value, but unfortunately github does not support empty list-items // with a checkbox :( value = - leftSquareBracket$6 + - (checked ? lowercaseX$2 : space$m) + - rightSquareBracket$6 + - space$m + + leftSquareBracket$4 + + (checked ? lowercaseX$2 : space$k) + + rightSquareBracket$4 + + space$k + value; } - if (style === '1' || (style === 'mixed' && value.indexOf(lineFeed$s) === -1)) { + if (style === '1' || (style === 'mixed' && value.indexOf(lineFeed$q) === -1)) { indent = marker.length + 1; - spacing = space$m; + spacing = space$k; } else { indent = ceil((marker.length + 1) / tabSize$6) * tabSize$6; - spacing = repeatString(space$m, indent - marker.length); + spacing = repeatString(space$k, indent - marker.length); } return value @@ -39809,8 +42387,8 @@ function longestStreak(value, character) { var inlineCode_1 = inlineCode$1; var graveAccentChar = '`'; -var lineFeed$t = 10; // '\n' -var space$n = 32; // ' ' +var lineFeed$r = 10; // '\n' +var space$l = 32; // ' ' var graveAccent$4 = 96; // '`' // Stringify inline code. @@ -39862,14 +42440,14 @@ function inlineCode$1(node) { } function ws(code) { - return code === lineFeed$t || code === space$n + return code === lineFeed$r || code === space$l } var code_1 = code; -var lineFeed$u = '\n'; -var space$o = ' '; -var tilde$5 = '~'; +var lineFeed$s = '\n'; +var space$m = ' '; +var tilde$6 = '~'; var graveAccent$5 = '`'; // Stringify code. @@ -39913,7 +42491,7 @@ function code(node, parent) { var fence; if (info && node.meta) { - info += space$o + node.meta; + info += space$m + node.meta; } info = self.encode(self.escape(info, node)); @@ -39923,8 +42501,8 @@ function code(node, parent) { !info && !options.fences && value && - value.charAt(0) !== lineFeed$u && - value.charAt(value.length - 1) !== lineFeed$u + value.charAt(0) !== lineFeed$s && + value.charAt(value.length - 1) !== lineFeed$s ) { // Throw when pedantic, in a list item which isn’t compiled using a tab. if ( @@ -39945,12 +42523,12 @@ function code(node, parent) { // Backticks in the info string don’t work with backtick fenced code. // Backticks (and tildes) are fine in tilde fenced code. if (marker === graveAccent$5 && info.indexOf(graveAccent$5) !== -1) { - marker = tilde$5; + marker = tilde$6; } fence = repeatString(marker, Math.max(longestStreak_1(value, marker) + 1, 3)); - return fence + info + lineFeed$u + value + lineFeed$u + fence + return fence + info + lineFeed$s + value + lineFeed$s + fence } var html_1 = html$1; @@ -39961,7 +42539,7 @@ function html$1(node) { var thematicBreak$1 = thematic; -var space$p = ' '; +var space$n = ' '; // Stringify a `thematic-break`. // The character used is configurable through `rule`: (`'_'`): @@ -39984,7 +42562,7 @@ var space$p = ' '; function thematic() { var options = this.options; var rule = repeatString(options.rule, options.ruleRepetition); - return options.ruleSpaces ? rule.split('').join(space$p) : rule + return options.ruleSpaces ? rule.split('').join(space$n) : rule } var strong_1$1 = strong$2; @@ -40004,8 +42582,8 @@ function strong$2(node) { var emphasis_1$1 = emphasis$2; -var underscore$5 = '_'; -var asterisk$5 = '*'; +var underscore$8 = '_'; +var asterisk$6 = '*'; // Stringify an `emphasis`. // @@ -40030,10 +42608,10 @@ function emphasis$2(node) { // are underscores in the content. if ( this.options.pedantic && - marker === underscore$5 && + marker === underscore$8 && content.indexOf(marker) !== -1 ) { - marker = asterisk$5; + marker = asterisk$6; } return marker + content + marker @@ -40041,12 +42619,12 @@ function emphasis$2(node) { var _break$2 = lineBreak; -var backslash$b = '\\'; -var lineFeed$v = '\n'; -var space$q = ' '; +var backslash$a = '\\'; +var lineFeed$t = '\n'; +var space$o = ' '; -var commonmark$1 = backslash$b + lineFeed$v; -var normal = space$q + space$q + lineFeed$v; +var commonmark$1 = backslash$a + lineFeed$t; +var normal = space$o + space$o + lineFeed$t; function lineBreak() { return this.options.commonmark ? commonmark$1 : normal @@ -40054,39 +42632,17 @@ function lineBreak() { var _delete$2 = strikethrough$1; -var tilde$6 = '~'; +var tilde$7 = '~'; -var fence$1 = tilde$6 + tilde$6; +var fence$1 = tilde$7 + tilde$7; function strikethrough$1(node) { return fence$1 + this.all(node).join('') + fence$1 } -var ccount_1 = ccount; - -function ccount(value, character) { - var count = 0; - var index; - - value = String(value); - - if (typeof character !== 'string' || character.length !== 1) { - throw new Error('Expected character') - } - - index = value.indexOf(character); - - while (index !== -1) { - count++; - index = value.indexOf(character, index + 1); - } - - return count -} - var encloseUri = enclose; -var leftParenthesis$4 = '('; +var leftParenthesis$3 = '('; var rightParenthesis$5 = ')'; var lessThan$8 = '<'; var greaterThan$6 = '>'; @@ -40106,7 +42662,7 @@ function enclose(uri, always) { always || uri.length === 0 || expression.test(uri) || - ccount_1(uri, leftParenthesis$4) !== ccount_1(uri, rightParenthesis$5) + ccount_1(uri, leftParenthesis$3) !== ccount_1(uri, rightParenthesis$5) ) { return lessThan$8 + uri + greaterThan$6 } @@ -40116,8 +42672,8 @@ function enclose(uri, always) { var encloseTitle = enclose$1; -var quotationMark$3 = '"'; -var apostrophe$3 = "'"; +var quotationMark$2 = '"'; +var apostrophe$2 = "'"; // There is currently no way to support nested delimiters across Markdown.pl, // CommonMark, and GitHub (RedCarpet). The following code supports Markdown.pl @@ -40126,16 +42682,16 @@ var apostrophe$3 = "'"; // title. function enclose$1(title) { var delimiter = - title.indexOf(quotationMark$3) === -1 ? quotationMark$3 : apostrophe$3; + title.indexOf(quotationMark$2) === -1 ? quotationMark$2 : apostrophe$2; return delimiter + title + delimiter } -var link_1$1 = link$4; +var link_1$1 = link$5; -var space$r = ' '; -var leftSquareBracket$7 = '['; -var rightSquareBracket$7 = ']'; -var leftParenthesis$5 = '('; +var space$p = ' '; +var leftSquareBracket$5 = '['; +var rightSquareBracket$5 = ']'; +var leftParenthesis$4 = '('; var rightParenthesis$6 = ')'; // Expression for a protocol: @@ -40161,7 +42717,7 @@ var protocol$1 = /^[a-z][a-z+.-]+:\/?/i; // // Supports named entities in the `url` and `title` when in `settings.encode` // mode. -function link$4(node) { +function link$5(node) { var self = this; var content = self.encode(node.url || '', node); var exit = self.enterLink(); @@ -40178,14 +42734,14 @@ function link$4(node) { content = encloseUri(content); if (node.title) { - content += space$r + encloseTitle(self.encode(self.escape(node.title, node), node)); + content += space$p + encloseTitle(self.encode(self.escape(node.title, node), node)); } return ( - leftSquareBracket$7 + + leftSquareBracket$5 + value + - rightSquareBracket$7 + - leftParenthesis$5 + + rightSquareBracket$5 + + leftParenthesis$4 + content + rightParenthesis$6 ) @@ -40193,7 +42749,7 @@ function link$4(node) { var copyIdentifierEncoding = copy$4; -var ampersand$3 = '&'; +var ampersand$4 = '&'; var punctuationExppresion = /[-!"#$%&'()*+,./:;<=>?@[\\\]^`{|}~_]/; @@ -40237,7 +42793,7 @@ function copy$4(value, identifier) { position < count && punctuationExppresion.test(identifier.charAt(position)) ) { - if (identifier.charAt(position) === ampersand$3) { + if (identifier.charAt(position) === ampersand$4) { position += entityPrefixLength(identifier.slice(position)); } @@ -40257,8 +42813,8 @@ function copy$4(value, identifier) { var label_1 = label; -var leftSquareBracket$8 = '['; -var rightSquareBracket$8 = ']'; +var leftSquareBracket$6 = '['; +var rightSquareBracket$6 = ']'; var shortcut$2 = 'shortcut'; var collapsed$1 = 'collapsed'; @@ -40275,16 +42831,16 @@ function label(node) { } return ( - leftSquareBracket$8 + + leftSquareBracket$6 + (type === collapsed$1 ? '' : node.label || node.identifier) + - rightSquareBracket$8 + rightSquareBracket$6 ) } var linkReference_1 = linkReference; -var leftSquareBracket$9 = '['; -var rightSquareBracket$9 = ']'; +var leftSquareBracket$7 = '['; +var rightSquareBracket$7 = ']'; var shortcut$3 = 'shortcut'; var collapsed$2 = 'collapsed'; @@ -40301,31 +42857,31 @@ function linkReference(node) { value = copyIdentifierEncoding(value, node.label || node.identifier); } - return leftSquareBracket$9 + value + rightSquareBracket$9 + label_1(node) + return leftSquareBracket$7 + value + rightSquareBracket$7 + label_1(node) } var imageReference_1 = imageReference; -var leftSquareBracket$a = '['; -var rightSquareBracket$a = ']'; -var exclamationMark$5 = '!'; +var leftSquareBracket$8 = '['; +var rightSquareBracket$8 = ']'; +var exclamationMark$6 = '!'; function imageReference(node) { return ( - exclamationMark$5 + - leftSquareBracket$a + + exclamationMark$6 + + leftSquareBracket$8 + (this.encode(node.alt, node) || '') + - rightSquareBracket$a + + rightSquareBracket$8 + label_1(node) ) } var definition_1$1 = definition$1; -var space$s = ' '; -var colon$6 = ':'; -var leftSquareBracket$b = '['; -var rightSquareBracket$b = ']'; +var space$q = ' '; +var colon$5 = ':'; +var leftSquareBracket$9 = '['; +var rightSquareBracket$9 = ']'; // Stringify an URL definition. // @@ -40339,27 +42895,27 @@ function definition$1(node) { var content = encloseUri(node.url); if (node.title) { - content += space$s + encloseTitle(node.title); + content += space$q + encloseTitle(node.title); } return ( - leftSquareBracket$b + + leftSquareBracket$9 + (node.label || node.identifier) + - rightSquareBracket$b + - colon$6 + - space$s + + rightSquareBracket$9 + + colon$5 + + space$q + content ) } var image_1 = image$3; -var space$t = ' '; -var leftParenthesis$6 = '('; +var space$r = ' '; +var leftParenthesis$5 = '('; var rightParenthesis$7 = ')'; -var leftSquareBracket$c = '['; -var rightSquareBracket$c = ']'; -var exclamationMark$6 = '!'; +var leftSquareBracket$a = '['; +var rightSquareBracket$a = ']'; +var exclamationMark$7 = '!'; // Stringify an image. // @@ -40381,341 +42937,281 @@ function image$3(node) { exit(); if (node.title) { - content += space$t + encloseTitle(self.encode(node.title, node)); + content += space$r + encloseTitle(self.encode(node.title, node)); } return ( - exclamationMark$6 + - leftSquareBracket$c + + exclamationMark$7 + + leftSquareBracket$a + alt + - rightSquareBracket$c + - leftParenthesis$6 + + rightSquareBracket$a + + leftParenthesis$5 + content + rightParenthesis$7 ) } -var footnote_1 = footnote$1; - -var leftSquareBracket$d = '['; -var rightSquareBracket$d = ']'; -var caret$3 = '^'; - -function footnote$1(node) { - return ( - leftSquareBracket$d + caret$3 + this.all(node).join('') + rightSquareBracket$d - ) -} - -var footnoteReference_1 = footnoteReference; - -var leftSquareBracket$e = '['; -var rightSquareBracket$e = ']'; -var caret$4 = '^'; - -function footnoteReference(node) { - return ( - leftSquareBracket$e + - caret$4 + - (node.label || node.identifier) + - rightSquareBracket$e - ) -} - -var lineFeed$w = '\n'; -var space$u = ' '; -var colon$7 = ':'; -var leftSquareBracket$f = '['; -var rightSquareBracket$f = ']'; -var caret$5 = '^'; - -var tabSize$7 = 4; -var blank$5 = lineFeed$w + lineFeed$w; -var indent = repeatString(space$u, tabSize$7); - -var footnoteDefinition_1$1 = footnoteDefinition$1; - -function footnoteDefinition$1(node) { - var content = this.all(node).join(blank$5 + indent); - - return ( - leftSquareBracket$f + - caret$5 + - (node.label || node.identifier) + - rightSquareBracket$f + - colon$7 + - space$u + - content - ) -} - var markdownTable_1 = markdownTable; -var dotRe = /\./; -var lastDotRe = /\.[^.]*$/; +var trailingWhitespace = / +$/; // Characters. -var space$v = ' '; -var lineFeed$x = '\n'; -var dash$7 = '-'; -var dot$5 = '.'; -var colon$8 = ':'; -var lowercaseC = 'c'; -var lowercaseL = 'l'; -var lowercaseR = 'r'; +var space$s = ' '; +var lineFeed$u = '\n'; +var dash$a = '-'; +var colon$6 = ':'; var verticalBar$2 = '|'; -var minCellSize = 3; +var x = 0; +var C = 67; +var L$1 = 76; +var R = 82; +var c$1 = 99; +var l$1 = 108; +var r = 114; // Create a table from a matrix of strings. function markdownTable(table, options) { var settings = options || {}; - var delimiter = settings.delimiter; - var start = settings.start; - var end = settings.end; - var alignment = settings.align; - var calculateStringLength = settings.stringLength || lengthNoop; - var cellCount = 0; + var padding = settings.padding !== false; + var start = settings.delimiterStart !== false; + var end = settings.delimiterEnd !== false; + var align = (settings.align || []).concat(); + var alignDelimiters = settings.alignDelimiters !== false; + var alignments = []; + var stringLength = settings.stringLength || defaultStringLength; var rowIndex = -1; var rowLength = table.length; + var cellMatrix = []; + var sizeMatrix = []; + var row = []; var sizes = []; - var align; - var rule; - var rows; - var row; + var longestCellByColumn = []; + var mostCellsPerRow = 0; var cells; - var index; - var position; + var columnIndex; + var columnLength; + var largest; var size; - var value; - var spacing; + var cell; + var lines; + var line; var before; var after; + var code; - alignment = alignment ? alignment.concat() : []; - - if (delimiter === null || delimiter === undefined) { - delimiter = space$v + verticalBar$2 + space$v; - } - - if (start === null || start === undefined) { - start = verticalBar$2 + space$v; - } - - if (end === null || end === undefined) { - end = space$v + verticalBar$2; - } - + // This is a superfluous loop if we don’t align delimiters, but otherwise we’d + // do superfluous work when aligning, so optimize for aligning. while (++rowIndex < rowLength) { - row = table[rowIndex]; + cells = table[rowIndex]; + columnIndex = -1; + columnLength = cells.length; + row = []; + sizes = []; - index = -1; - - if (row.length > cellCount) { - cellCount = row.length; + if (columnLength > mostCellsPerRow) { + mostCellsPerRow = columnLength; } - while (++index < cellCount) { - position = row[index] ? dotindex$1(row[index]) : null; - - if (!sizes[index]) { - sizes[index] = minCellSize; - } + while (++columnIndex < columnLength) { + cell = serialize(cells[columnIndex]); - if (position > sizes[index]) { - sizes[index] = position; - } - } - } + if (alignDelimiters === true) { + size = stringLength(cell); + sizes[columnIndex] = size; - if (typeof alignment === 'string') { - alignment = pad$2(cellCount, alignment).split(''); - } + largest = longestCellByColumn[columnIndex]; - // Make sure only valid alignments are used. - index = -1; - - while (++index < cellCount) { - align = alignment[index]; + if (largest === undefined || size > largest) { + longestCellByColumn[columnIndex] = size; + } + } - if (typeof align === 'string') { - align = align.charAt(0).toLowerCase(); + row.push(cell); } - if ( - align !== lowercaseL && - align !== lowercaseR && - align !== lowercaseC && - align !== dot$5 - ) { - align = ''; - } - - alignment[index] = align; + cellMatrix[rowIndex] = row; + sizeMatrix[rowIndex] = sizes; } - rowIndex = -1; - rows = []; - - while (++rowIndex < rowLength) { - row = table[rowIndex]; - - index = -1; - cells = []; - - while (++index < cellCount) { - value = row[index]; - - value = stringify$6(value); - - if (alignment[index] === dot$5) { - position = dotindex$1(value); - - size = - sizes[index] + - (dotRe.test(value) ? 0 : 1) - - (calculateStringLength(value) - position); + // Figure out which alignments to use. + columnIndex = -1; + columnLength = mostCellsPerRow; - cells[index] = value + pad$2(size - 1); - } else { - cells[index] = value; - } + if (typeof align === 'object' && 'length' in align) { + while (++columnIndex < columnLength) { + alignments[columnIndex] = toAlignment(align[columnIndex]); } + } else { + code = toAlignment(align); - rows[rowIndex] = cells; + while (++columnIndex < columnLength) { + alignments[columnIndex] = code; + } } + // Inject the alignment row. + columnIndex = -1; + columnLength = mostCellsPerRow; + row = []; sizes = []; - rowIndex = -1; - while (++rowIndex < rowLength) { - cells = rows[rowIndex]; + while (++columnIndex < columnLength) { + code = alignments[columnIndex]; + before = ''; + after = ''; + + if (code === l$1) { + before = colon$6; + } else if (code === r) { + after = colon$6; + } else if (code === c$1) { + before = colon$6; + after = colon$6; + } + + // There *must* be at least one hyphen-minus in each alignment cell. + size = alignDelimiters + ? Math.max( + 1, + longestCellByColumn[columnIndex] - before.length - after.length + ) + : 1; - index = -1; + cell = before + repeatString(dash$a, size) + after; - while (++index < cellCount) { - value = cells[index]; + if (alignDelimiters === true) { + size = before.length + size + after.length; - if (!sizes[index]) { - sizes[index] = minCellSize; + if (size > longestCellByColumn[columnIndex]) { + longestCellByColumn[columnIndex] = size; } - size = calculateStringLength(value); - - if (size > sizes[index]) { - sizes[index] = size; - } + sizes[columnIndex] = size; } + + row[columnIndex] = cell; } + // Inject the alignment row. + cellMatrix.splice(1, 0, row); + sizeMatrix.splice(1, 0, sizes); + rowIndex = -1; + rowLength = cellMatrix.length; + lines = []; while (++rowIndex < rowLength) { - cells = rows[rowIndex]; - - index = -1; - - if (settings.pad !== false) { - while (++index < cellCount) { - value = cells[index]; - - position = sizes[index] - (calculateStringLength(value) || 0); - spacing = pad$2(position); - - if (alignment[index] === lowercaseR || alignment[index] === dot$5) { - value = spacing + value; - } else if (alignment[index] === lowercaseC) { - position /= 2; + row = cellMatrix[rowIndex]; + sizes = sizeMatrix[rowIndex]; + columnIndex = -1; + columnLength = mostCellsPerRow; + line = []; - if (position % 1 === 0) { - before = position; - after = position; + while (++columnIndex < columnLength) { + cell = row[columnIndex] || ''; + before = ''; + after = ''; + + if (alignDelimiters === true) { + size = longestCellByColumn[columnIndex] - (sizes[columnIndex] || 0); + code = alignments[columnIndex]; + + if (code === r) { + before = repeatString(space$s, size); + } else if (code === c$1) { + if (size % 2 === 0) { + before = repeatString(space$s, size / 2); + after = before; } else { - before = position + 0.5; - after = position - 0.5; + before = repeatString(space$s, size / 2 + 0.5); + after = repeatString(space$s, size / 2 - 0.5); } - - value = pad$2(before) + value + pad$2(after); } else { - value += spacing; + after = repeatString(space$s, size); } + } - cells[index] = value; + if (start === true && columnIndex === 0) { + line.push(verticalBar$2); } - } - rows[rowIndex] = cells.join(delimiter); - } + if ( + padding === true && + // Don’t add the opening space if we’re not aligning and the cell is + // empty: there will be a closing space. + !(alignDelimiters === false && cell === '') && + (start === true || columnIndex !== 0) + ) { + line.push(space$s); + } - if (settings.rule !== false) { - index = -1; - rule = []; - - while (++index < cellCount) { - // When `pad` is false, make the rule the same size as the first row. - if (settings.pad === false) { - value = table[0][index]; - spacing = calculateStringLength(stringify$6(value)); - spacing = spacing > minCellSize ? spacing : minCellSize; - } else { - spacing = sizes[index]; + if (alignDelimiters === true) { + line.push(before); } - align = alignment[index]; + line.push(cell); - // When `align` is left, don't add colons. - value = align === lowercaseR || align === '' ? dash$7 : colon$8; - value += pad$2(spacing - 2, dash$7); - value += align !== lowercaseL && align !== '' ? colon$8 : dash$7; + if (alignDelimiters === true) { + line.push(after); + } + + if (padding === true) { + line.push(space$s); + } - rule[index] = value; + if (end === true || columnIndex !== columnLength - 1) { + line.push(verticalBar$2); + } } - rows.splice(1, 0, rule.join(delimiter)); + line = line.join(''); + + if (end === false) { + line = line.replace(trailingWhitespace, ''); + } + + lines.push(line); } - return start + rows.join(end + lineFeed$x + start) + end + return lines.join(lineFeed$u) } -function stringify$6(value) { +function serialize(value) { return value === null || value === undefined ? '' : String(value) } -// Get the length of `value`. -function lengthNoop(value) { - return String(value).length -} - -// Get a string consisting of `length` `character`s. -function pad$2(length, character) { - return new Array(length + 1).join(character || space$v) +function defaultStringLength(value) { + return value.length } -// Get the position of the last dot in `value`. -function dotindex$1(value) { - var match = lastDotRe.exec(value); +function toAlignment(value) { + var code = typeof value === 'string' ? value.charCodeAt(0) : x; - return match ? match.index + 1 : value.length + return code === L$1 || code === l$1 + ? l$1 + : code === R || code === r + ? r + : code === C || code === c$1 + ? c$1 + : x } var table_1$1 = table$1; -var space$w = ' '; -var verticalBar$3 = '|'; - // Stringify table. // -// Creates a fenced table by default, but not in `looseTable: true` mode: +// Creates a fenced table. +// The table has aligned delimiters by default, but not in +// `tablePipeAlign: false`: // // ```markdown -// Foo | Bar -// :-: | --- -// Baz | Qux -// -// NOTE: Be careful with `looseTable: true` mode, as a loose table inside an -// indented code block on GitHub renders as an actual table! +// | Header 1 | Header 2 | +// | :-: | - | +// | Alpha | Bravo | +// ``` // -// Creates a spaced table by default, but not in `spacedTable: false`: +// The table is spaced by default, but not in `tableCellPadding: false`: // // ```markdown // |Foo|Bar| @@ -40725,16 +43221,13 @@ var verticalBar$3 = '|'; function table$1(node) { var self = this; var options = self.options; - var loose = options.looseTable; - var spaced = options.spacedTable; - var pad = options.paddedTable; + var padding = options.tableCellPadding; + var alignDelimiters = options.tablePipeAlign; var stringLength = options.stringLength; var rows = node.children; var index = rows.length; var exit = self.enterTable(); var result = []; - var start; - var end; while (index--) { result[index] = self.all(rows[index]); @@ -40742,35 +43235,20 @@ function table$1(node) { exit(); - if (loose) { - start = ''; - end = ''; - } else if (spaced) { - start = verticalBar$3 + space$w; - end = space$w + verticalBar$3; - } else { - start = verticalBar$3; - end = verticalBar$3; - } - return markdownTable_1(result, { align: node.align, - pad: pad, - start: start, - end: end, - stringLength: stringLength, - delimiter: spaced ? space$w + verticalBar$3 + space$w : verticalBar$3 + alignDelimiters: alignDelimiters, + padding: padding, + stringLength: stringLength }) } var tableCell_1 = tableCell; -var lineFeed$y = /\r?\n/g; +var lineFeed$v = /\r?\n/g; function tableCell(node) { - return this.all(node) - .join('') - .replace(lineFeed$y, ' ') + return this.all(node).join('').replace(lineFeed$v, ' ') } var compiler = Compiler; @@ -40785,26 +43263,26 @@ function Compiler(tree, file) { this.setOptions({}); } -var proto$4 = Compiler.prototype; +var proto$5 = Compiler.prototype; // Enter and exit helpers. */ -proto$4.enterLink = stateToggle('inLink', false); -proto$4.enterTable = stateToggle('inTable', false); -proto$4.enterLinkReference = enterLinkReference; +proto$5.enterLink = stateToggle('inLink', false); +proto$5.enterTable = stateToggle('inTable', false); +proto$5.enterLinkReference = enterLinkReference; // Configuration. -proto$4.options = defaults$3; -proto$4.setOptions = setOptions_1$1; +proto$5.options = defaults$3; +proto$5.setOptions = setOptions_1$1; -proto$4.compile = compile_1$1; -proto$4.visit = one_1; -proto$4.all = all_1; -proto$4.block = block_1; -proto$4.visitOrderedItems = orderedItems_1; -proto$4.visitUnorderedItems = unorderedItems_1; +proto$5.compile = compile_1$1; +proto$5.visit = one_1; +proto$5.all = all_1; +proto$5.block = block_1; +proto$5.visitOrderedItems = orderedItems_1; +proto$5.visitUnorderedItems = unorderedItems_1; // Expose visitors. -proto$4.visitors = { +proto$5.visitors = { root: root_1, text: text_1$1, heading: heading_1, @@ -40825,17 +43303,14 @@ proto$4.visitors = { imageReference: imageReference_1, definition: definition_1$1, image: image_1, - footnote: footnote_1, - footnoteReference: footnoteReference_1, - footnoteDefinition: footnoteDefinition_1$1, table: table_1$1, tableCell: tableCell_1 }; -var remarkStringify = stringify$7; -stringify$7.Compiler = compiler; +var remarkStringify = stringify$6; +stringify$6.Compiler = compiler; -function stringify$7(options) { +function stringify$6(options) { var Local = unherit_1(compiler); Local.prototype.options = immutable( Local.prototype.options, @@ -40845,15 +43320,65 @@ function stringify$7(options) { this.Compiler = Local; } -var remark = unified_1() - .use(remarkParse) - .use(remarkStringify) - .freeze(); - -const name$1 = "remark"; -const version$1 = "11.0.2"; -const description = "Markdown processor powered by plugins"; -const license = "MIT"; +var remark = unified_1().use(remarkParse).use(remarkStringify).freeze(); + +const _from = "remark@latest"; +const _id = "remark@12.0.0"; +const _inBundle = false; +const _integrity = "sha512-oX4lMIS0csgk8AEbzY0h2jdR0ngiCHOpwwpxjmRa5TqAkeknY+tkhjRJGZqnCmvyuWh55/0SW5WY3R3nn3PH9A=="; +const _location = "/remark"; +const _phantomChildren = { +}; +const _requested = { + type: "tag", + registry: true, + raw: "remark@latest", + name: "remark", + escapedName: "remark", + rawSpec: "latest", + saveSpec: null, + fetchSpec: "latest" +}; +const _requiredBy = [ + "#USER", + "/" +]; +const _resolved = "https://registry.npmjs.org/remark/-/remark-12.0.0.tgz"; +const _shasum = "d1c145c07341c9232f93b2f8539d56da15a2548c"; +const _spec = "remark@latest"; +const _where = "/Users/trott/io.js/tools/node-lint-md-cli-rollup"; +const author = { + name: "Titus Wormer", + email: "tituswormer@gmail.com", + url: "https://wooorm.com" +}; +const bugs = { + url: "https://github.com/remarkjs/remark/issues" +}; +const bundleDependencies = false; +const contributors = [ + { + name: "Titus Wormer", + email: "tituswormer@gmail.com", + url: "https://wooorm.com" + } +]; +const dependencies = { + "remark-parse": "^8.0.0", + "remark-stringify": "^8.0.0", + unified: "^9.0.0" +}; +const deprecated$1 = false; +const description = "Markdown processor powered by plugins part of the unified collective"; +const files = [ + "index.js", + "types/index.d.ts" +]; +const funding = { + type: "opencollective", + url: "https://opencollective.com/unified" +}; +const homepage = "https://remark.js.org"; const keywords = [ "unified", "remark", @@ -40865,79 +43390,87 @@ const keywords = [ "ast", "parse", "stringify", + "serialize", + "compile", "process" ]; -const homepage = "https://remark.js.org"; -const repository = "https://github.com/remarkjs/remark/tree/master/packages/remark"; -const bugs = "https://github.com/remarkjs/remark/issues"; -const funding = { - type: "opencollective", - url: "https://opencollective.com/unified" -}; -const author = "Titus Wormer (https://wooorm.com)"; -const contributors = [ - "Titus Wormer (https://wooorm.com)" -]; -const files = [ - "index.js", - "types/index.d.ts" -]; -const types = "types/index.d.ts"; -const dependencies = { - "remark-parse": "^7.0.0", - "remark-stringify": "^7.0.0", - unified: "^8.2.0" +const license = "MIT"; +const name$1 = "remark"; +const repository = { + type: "git", + url: "https://github.com/remarkjs/remark/tree/master/packages/remark" }; const scripts = { test: "tape test.js" }; +const types = "types/index.d.ts"; +const version$1 = "12.0.0"; const xo = false; -const _resolved = "https://registry.npmjs.org/remark/-/remark-11.0.2.tgz"; -const _integrity = "sha512-bh+eJgn8wgmbHmIBOuwJFdTVRVpl3fcVP6HxmpPWO0ULGP9Qkh6INJh0N5Uy7GqlV7DQYGoqaKiEIpM5LLvJ8w=="; -const _from = "remark@11.0.2"; var _package = { - name: name$1, - version: version$1, - description: description, - license: license, - keywords: keywords, - homepage: homepage, - repository: repository, - bugs: bugs, - funding: funding, + _from: _from, + _id: _id, + _inBundle: _inBundle, + _integrity: _integrity, + _location: _location, + _phantomChildren: _phantomChildren, + _requested: _requested, + _requiredBy: _requiredBy, + _resolved: _resolved, + _shasum: _shasum, + _spec: _spec, + _where: _where, author: author, + bugs: bugs, + bundleDependencies: bundleDependencies, contributors: contributors, - files: files, - types: types, dependencies: dependencies, + deprecated: deprecated$1, + description: description, + files: files, + funding: funding, + homepage: homepage, + keywords: keywords, + license: license, + name: name$1, + repository: repository, scripts: scripts, - xo: xo, - _resolved: _resolved, - _integrity: _integrity, - _from: _from + types: types, + version: version$1, + xo: xo }; var _package$1 = /*#__PURE__*/Object.freeze({ __proto__: null, - name: name$1, - version: version$1, - description: description, - license: license, - keywords: keywords, - homepage: homepage, - repository: repository, - bugs: bugs, - funding: funding, + _from: _from, + _id: _id, + _inBundle: _inBundle, + _integrity: _integrity, + _location: _location, + _phantomChildren: _phantomChildren, + _requested: _requested, + _requiredBy: _requiredBy, + _resolved: _resolved, + _shasum: _shasum, + _spec: _spec, + _where: _where, author: author, + bugs: bugs, + bundleDependencies: bundleDependencies, contributors: contributors, - files: files, - types: types, dependencies: dependencies, + deprecated: deprecated$1, + description: description, + files: files, + funding: funding, + homepage: homepage, + keywords: keywords, + license: license, + name: name$1, + repository: repository, scripts: scripts, + types: types, + version: version$1, xo: xo, - _resolved: _resolved, - _integrity: _integrity, - _from: _from, 'default': _package }); @@ -40953,10 +43486,10 @@ const devDependencies = { }; const dependencies$1 = { "markdown-extensions": "^1.1.1", - remark: "^11.0.2", - "remark-lint": "^6.0.5", + remark: "^12.0.0", + "remark-lint": "^7.0.0", "remark-preset-lint-node": "^1.15.0", - "unified-args": "^7.1.0" + "unified-args": "^8.0.0" }; const main = "dist/index.js"; const scripts$1 = { @@ -41058,9 +43591,9 @@ function indices$1(value) { return result } -var convert_1$1 = convert$2; +var convert_1$1 = convert$4; -function convert$2(test) { +function convert$4(test) { if (typeof test === 'string') { return typeFactory$1(test) } @@ -41086,7 +43619,7 @@ function convertAll$1(tests) { var index = -1; while (++index < length) { - results[index] = convert$2(tests[index]); + results[index] = convert$4(tests[index]); } return results @@ -41712,9 +44245,9 @@ function indices$2(value) { return result } -var convert_1$2 = convert$3; +var convert_1$2 = convert$5; -function convert$3(test) { +function convert$5(test) { if (typeof test === 'string') { return typeFactory$2(test) } @@ -41740,7 +44273,7 @@ function convertAll$2(tests) { var index = -1; while (++index < length) { - results[index] = convert$3(tests[index]); + results[index] = convert$5(tests[index]); } return results @@ -42385,7 +44918,7 @@ function toThunk(obj, ctx) { return obj; } - if (isObject$4(obj) || Array.isArray(obj)) { + if (isObject$3(obj) || Array.isArray(obj)) { return objectToThunk.call(ctx, obj); } @@ -42519,7 +45052,7 @@ function isGeneratorFunction(obj) { * @api private */ -function isObject$4(val) { +function isObject$3(val) { return val && Object == val.constructor; } @@ -42595,7 +45128,7 @@ function wrapped(fn) { } // sync - return sync$2(fn, done).apply(ctx, args); + return sync$5(fn, done).apply(ctx, args); } return wrap; @@ -42610,7 +45143,7 @@ function wrapped(fn) { * @api private */ -function sync$2(fn, done) { +function sync$5(fn, done) { return function () { var ret; @@ -43280,9 +45813,9 @@ var pluralize = createCommonjsModule(function (module, exports) { }); }); -var convert_1$3 = convert$4; +var convert_1$3 = convert$6; -function convert$4(test) { +function convert$6(test) { if (typeof test === 'string') { return typeFactory$3(test) } @@ -43308,7 +45841,7 @@ function convertAll$3(tests) { var index = -1; while (++index < length) { - results[index] = convert$4(tests[index]); + results[index] = convert$6(tests[index]); } return results @@ -43555,9 +46088,9 @@ function listItemBulletIndent(tree, file) { } } -var convert_1$4 = convert$5; +var convert_1$4 = convert$7; -function convert$5(test) { +function convert$7(test) { if (typeof test === 'string') { return typeFactory$4(test) } @@ -43583,7 +46116,7 @@ function convertAll$4(tests) { var index = -1; while (++index < length) { - results[index] = convert$5(tests[index]); + results[index] = convert$7(tests[index]); } return results @@ -43750,13 +46283,13 @@ var remarkLintListItemIndent = unifiedLintRule('remark-lint:list-item-indent', l var start$3 = unistUtilPosition.start; -var styles = {'tab-size': true, mixed: true, space: true}; +var styles$1 = {'tab-size': true, mixed: true, space: true}; function listItemIndent(tree, file, option) { var contents = String(file); var preferred = typeof option === 'string' ? option : 'tab-size'; - if (styles[preferred] !== true) { + if (styles$1[preferred] !== true) { file.fail( 'Incorrect list-item indent style `' + preferred + @@ -43812,9 +46345,9 @@ function listItemIndent(tree, file, option) { } } -var convert_1$5 = convert$6; +var convert_1$5 = convert$8; -function convert$6(test) { +function convert$8(test) { if (typeof test === 'string') { return typeFactory$5(test) } @@ -43840,7 +46373,7 @@ function convertAll$5(tests) { var index = -1; while (++index < length) { - results[index] = convert$6(tests[index]); + results[index] = convert$8(tests[index]); } return results @@ -44003,12 +46536,12 @@ function visit$5(tree, test, visitor, reverse) { } } -var mdastUtilToString = toString$4; +var mdastUtilToString = toString$3; // Get the text content of a node. // Prefer the node’s plain-text fields, otherwise serialize its children, // and if the given value is an array, serialize the nodes in it. -function toString$4(node) { +function toString$3(node) { return ( (node && (node.value || @@ -44026,7 +46559,7 @@ function all$1(values) { var index = -1; while (++index < length) { - result[index] = toString$4(values[index]); + result[index] = toString$3(values[index]); } return result.join('') @@ -44139,9 +46672,9 @@ function indices$3(value) { return result } -var convert_1$6 = convert$7; +var convert_1$6 = convert$9; -function convert$7(test) { +function convert$9(test) { if (typeof test === 'string') { return typeFactory$6(test) } @@ -44167,7 +46700,7 @@ function convertAll$6(tests) { var index = -1; while (++index < length) { - results[index] = convert$7(tests[index]); + results[index] = convert$9(tests[index]); } return results @@ -44384,9 +46917,9 @@ function noBlockquoteWithoutMarker(tree, file) { } } -var convert_1$7 = convert$8; +var convert_1$7 = convert$a; -function convert$8(test) { +function convert$a(test) { if (typeof test === 'string') { return typeFactory$7(test) } @@ -44412,7 +46945,7 @@ function convertAll$7(tests) { var index = -1; while (++index < length) { - results[index] = convert$8(tests[index]); + results[index] = convert$a(tests[index]); } return results @@ -44579,7 +47112,7 @@ var remarkLintNoLiteralUrls = unifiedLintRule('remark-lint:no-literal-urls', noL var start$5 = unistUtilPosition.start; var end$2 = unistUtilPosition.end; -var mailto$3 = 'mailto:'; +var mailto$2 = 'mailto:'; var reason$2 = 'Don’t use literal URLs without angle brackets'; function noLiteralURLs(tree, file) { @@ -44593,16 +47126,16 @@ function noLiteralURLs(tree, file) { !unistUtilGenerated(node) && start$5(node).column === start$5(children[0]).column && end$2(node).column === end$2(children[children.length - 1]).column && - (node.url === mailto$3 + value || node.url === value) + (node.url === mailto$2 + value || node.url === value) ) { file.message(reason$2, node); } } } -var convert_1$8 = convert$9; +var convert_1$8 = convert$b; -function convert$9(test) { +function convert$b(test) { if (typeof test === 'string') { return typeFactory$8(test) } @@ -44628,7 +47161,7 @@ function convertAll$8(tests) { var index = -1; while (++index < length) { - results[index] = convert$9(tests[index]); + results[index] = convert$b(tests[index]); } return results @@ -44798,7 +47331,7 @@ var remarkLintOrderedListMarkerStyle = unifiedLintRule( var start$6 = unistUtilPosition.start; -var styles$1 = { +var styles$2 = { ')': true, '.': true, null: true @@ -44809,7 +47342,7 @@ function orderedListMarkerStyle(tree, file, option) { var preferred = typeof option !== 'string' || option === 'consistent' ? null : option; - if (styles$1[preferred] !== true) { + if (styles$2[preferred] !== true) { file.fail( 'Incorrect ordered list item marker style `' + preferred + @@ -44847,9 +47380,9 @@ function orderedListMarkerStyle(tree, file, option) { } } -var convert_1$9 = convert$a; +var convert_1$9 = convert$c; -function convert$a(test) { +function convert$c(test) { if (typeof test === 'string') { return typeFactory$9(test) } @@ -44875,7 +47408,7 @@ function convertAll$9(tests) { var index = -1; while (++index < length) { - results[index] = convert$a(tests[index]); + results[index] = convert$c(tests[index]); } return results @@ -45063,9 +47596,9 @@ function hardBreakSpaces(tree, file) { } } -var convert_1$a = convert$b; +var convert_1$a = convert$d; -function convert$b(test) { +function convert$d(test) { if (typeof test === 'string') { return typeFactory$a(test) } @@ -45091,7 +47624,7 @@ function convertAll$a(tests) { var index = -1; while (++index < length) { - results[index] = convert$b(tests[index]); + results[index] = convert$d(tests[index]); } return results @@ -45286,9 +47819,9 @@ function noDuplicateDefinitions(tree, file) { } } -var convert_1$b = convert$c; +var convert_1$b = convert$e; -function convert$c(test) { +function convert$e(test) { if (typeof test === 'string') { return typeFactory$b(test) } @@ -45314,7 +47847,7 @@ function convertAll$b(tests) { var index = -1; while (++index < length) { - results[index] = convert$c(tests[index]); + results[index] = convert$e(tests[index]); } return results @@ -45613,9 +48146,9 @@ function noHeadingContentIndent(tree, file) { } } -var convert_1$c = convert$d; +var convert_1$c = convert$f; -function convert$d(test) { +function convert$f(test) { if (typeof test === 'string') { return typeFactory$c(test) } @@ -45641,7 +48174,7 @@ function convertAll$c(tests) { var index = -1; while (++index < length) { - results[index] = convert$d(tests[index]); + results[index] = convert$f(tests[index]); } return results @@ -45825,9 +48358,9 @@ function noInlinePadding(tree, file) { } } -var convert_1$d = convert$e; +var convert_1$d = convert$g; -function convert$e(test) { +function convert$g(test) { if (typeof test === 'string') { return typeFactory$d(test) } @@ -45853,7 +48386,7 @@ function convertAll$d(tests) { var index = -1; while (++index < length) { - results[index] = convert$e(tests[index]); + results[index] = convert$g(tests[index]); } return results @@ -46033,9 +48566,9 @@ function noShortcutReferenceImage(tree, file) { } } -var convert_1$e = convert$f; +var convert_1$e = convert$h; -function convert$f(test) { +function convert$h(test) { if (typeof test === 'string') { return typeFactory$e(test) } @@ -46061,7 +48594,7 @@ function convertAll$e(tests) { var index = -1; while (++index < length) { - results[index] = convert$f(tests[index]); + results[index] = convert$h(tests[index]); } return results @@ -46241,9 +48774,9 @@ function noShortcutReferenceLink(tree, file) { } } -var convert_1$f = convert$g; +var convert_1$f = convert$i; -function convert$g(test) { +function convert$i(test) { if (typeof test === 'string') { return typeFactory$f(test) } @@ -46269,7 +48802,7 @@ function convertAll$f(tests) { var index = -1; while (++index < length) { - results[index] = convert$g(tests[index]); + results[index] = convert$i(tests[index]); } return results @@ -46471,9 +49004,9 @@ function noUndefinedReferences(tree, file, option) { } } -var convert_1$g = convert$h; +var convert_1$g = convert$j; -function convert$h(test) { +function convert$j(test) { if (typeof test === 'string') { return typeFactory$g(test) } @@ -46499,7 +49032,7 @@ function convertAll$g(tests) { var index = -1; while (++index < length) { - results[index] = convert$h(tests[index]); + results[index] = convert$j(tests[index]); } return results @@ -46724,9 +49257,9 @@ var remarkPresetLintRecommended = { plugins: plugins$1 }; -var convert_1$h = convert$i; +var convert_1$h = convert$k; -function convert$i(test) { +function convert$k(test) { if (typeof test === 'string') { return typeFactory$h(test) } @@ -46752,7 +49285,7 @@ function convertAll$h(tests) { var index = -1; while (++index < length) { - results[index] = convert$i(tests[index]); + results[index] = convert$k(tests[index]); } return results @@ -47040,9 +49573,9 @@ function indices$4(value) { return result } -var convert_1$i = convert$j; +var convert_1$i = convert$l; -function convert$j(test) { +function convert$l(test) { if (typeof test === 'string') { return typeFactory$i(test) } @@ -47068,7 +49601,7 @@ function convertAll$i(tests) { var index = -1; while (++index < length) { - results[index] = convert$j(tests[index]); + results[index] = convert$l(tests[index]); } return results @@ -47385,9 +49918,9 @@ function indices$5(value) { return result } -var convert_1$j = convert$k; +var convert_1$j = convert$m; -function convert$k(test) { +function convert$m(test) { if (typeof test === 'string') { return typeFactory$j(test) } @@ -47413,7 +49946,7 @@ function convertAll$j(tests) { var index = -1; while (++index < length) { - results[index] = convert$k(tests[index]); + results[index] = convert$m(tests[index]); } return results @@ -47624,9 +50157,9 @@ function checkboxContentIndent(tree, file) { } } -var convert_1$k = convert$l; +var convert_1$k = convert$n; -function convert$l(test) { +function convert$n(test) { if (typeof test === 'string') { return typeFactory$k(test) } @@ -47652,7 +50185,7 @@ function convertAll$k(tests) { var index = -1; while (++index < length) { - results[index] = convert$l(tests[index]); + results[index] = convert$n(tests[index]); } return results @@ -47820,14 +50353,14 @@ var remarkLintCodeBlockStyle = unifiedLintRule('remark-lint:code-block-style', c var start$a = unistUtilPosition.start; var end$6 = unistUtilPosition.end; -var styles$2 = {null: true, fenced: true, indented: true}; +var styles$3 = {null: true, fenced: true, indented: true}; function codeBlockStyle(tree, file, option) { var contents = String(file); var preferred = typeof option === 'string' && option !== 'consistent' ? option : null; - if (styles$2[preferred] !== true) { + if (styles$3[preferred] !== true) { file.fail( 'Incorrect code block style `' + preferred + @@ -47864,9 +50397,9 @@ function codeBlockStyle(tree, file, option) { } } -var convert_1$l = convert$m; +var convert_1$l = convert$o; -function convert$m(test) { +function convert$o(test) { if (typeof test === 'string') { return typeFactory$l(test) } @@ -47892,7 +50425,7 @@ function convertAll$l(tests) { var index = -1; while (++index < length) { - results[index] = convert$m(tests[index]); + results[index] = convert$o(tests[index]); } return results @@ -48078,9 +50611,9 @@ function definitionSpacing(tree, file) { } } -var convert_1$m = convert$n; +var convert_1$m = convert$p; -function convert$n(test) { +function convert$p(test) { if (typeof test === 'string') { return typeFactory$m(test) } @@ -48106,7 +50639,7 @@ function convertAll$m(tests) { var index = -1; while (++index < length) { - results[index] = convert$n(tests[index]); + results[index] = convert$p(tests[index]); } return results @@ -48314,9 +50847,9 @@ function fencedCodeFlag(tree, file, option) { } } -var convert_1$n = convert$o; +var convert_1$n = convert$q; -function convert$o(test) { +function convert$q(test) { if (typeof test === 'string') { return typeFactory$n(test) } @@ -48342,7 +50875,7 @@ function convertAll$n(tests) { var index = -1; while (++index < length) { - results[index] = convert$o(tests[index]); + results[index] = convert$q(tests[index]); } return results @@ -48569,9 +51102,9 @@ function fileExtension(tree, file, option) { } } -var convert_1$o = convert$p; +var convert_1$o = convert$r; -function convert$p(test) { +function convert$r(test) { if (typeof test === 'string') { return typeFactory$o(test) } @@ -48597,7 +51130,7 @@ function convertAll$o(tests) { var index = -1; while (++index < length) { - results[index] = convert$p(tests[index]); + results[index] = convert$r(tests[index]); } return results @@ -48792,9 +51325,9 @@ function finalDefinition(tree, file) { } } -var convert_1$p = convert$q; +var convert_1$p = convert$s; -function convert$q(test) { +function convert$s(test) { if (typeof test === 'string') { return typeFactory$p(test) } @@ -48820,7 +51353,7 @@ function convertAll$p(tests) { var index = -1; while (++index < length) { - results[index] = convert$q(tests[index]); + results[index] = convert$s(tests[index]); } return results @@ -49021,9 +51554,9 @@ function infer(node) { return results ? Number(results[1]) : undefined } -var convert_1$q = convert$r; +var convert_1$q = convert$t; -function convert$r(test) { +function convert$t(test) { if (typeof test === 'string') { return typeFactory$q(test) } @@ -49049,7 +51582,7 @@ function convertAll$q(tests) { var index = -1; while (++index < length) { - results[index] = convert$r(tests[index]); + results[index] = convert$t(tests[index]); } return results @@ -49234,9 +51767,9 @@ function headingStyle(tree, file, option) { } } -var convert_1$r = convert$s; +var convert_1$r = convert$u; -function convert$s(test) { +function convert$u(test) { if (typeof test === 'string') { return typeFactory$r(test) } @@ -49262,7 +51795,7 @@ function convertAll$r(tests) { var index = -1; while (++index < length) { - results[index] = convert$s(tests[index]); + results[index] = convert$u(tests[index]); } return results @@ -49503,9 +52036,9 @@ function maximumLineLength(tree, file, option) { } } -var convert_1$s = convert$t; +var convert_1$s = convert$v; -function convert$t(test) { +function convert$v(test) { if (typeof test === 'string') { return typeFactory$s(test) } @@ -49531,7 +52064,7 @@ function convertAll$s(tests) { var index = -1; while (++index < length) { - results[index] = convert$t(tests[index]); + results[index] = convert$v(tests[index]); } return results @@ -49801,9 +52334,9 @@ function noFileNameOuterDashes(tree, file) { } } -var convert_1$t = convert$u; +var convert_1$t = convert$w; -function convert$u(test) { +function convert$w(test) { if (typeof test === 'string') { return typeFactory$t(test) } @@ -49829,7 +52362,7 @@ function convertAll$t(tests) { var index = -1; while (++index < length) { - results[index] = convert$u(tests[index]); + results[index] = convert$w(tests[index]); } return results @@ -50039,9 +52572,9 @@ function noHeadingIndent(tree, file) { } } -var convert_1$u = convert$v; +var convert_1$u = convert$x; -function convert$v(test) { +function convert$x(test) { if (typeof test === 'string') { return typeFactory$u(test) } @@ -50067,7 +52600,7 @@ function convertAll$u(tests) { var index = -1; while (++index < length) { - results[index] = convert$v(tests[index]); + results[index] = convert$x(tests[index]); } return results @@ -50259,9 +52792,9 @@ function noMultipleToplevelHeadings(tree, file, option) { } } -var convert_1$v = convert$w; +var convert_1$v = convert$y; -function convert$w(test) { +function convert$y(test) { if (typeof test === 'string') { return typeFactory$v(test) } @@ -50287,7 +52820,7 @@ function convertAll$v(tests) { var index = -1; while (++index < length) { - results[index] = convert$w(tests[index]); + results[index] = convert$y(tests[index]); } return results @@ -50502,9 +53035,9 @@ function noShellDollars(tree, file) { } } -var convert_1$w = convert$x; +var convert_1$w = convert$z; -function convert$x(test) { +function convert$z(test) { if (typeof test === 'string') { return typeFactory$w(test) } @@ -50530,7 +53063,7 @@ function convertAll$w(tests) { var index = -1; while (++index < length) { - results[index] = convert$x(tests[index]); + results[index] = convert$z(tests[index]); } return results @@ -50845,9 +53378,9 @@ var escapeStringRegexp$1 = string => { .replace(/-/g, '\\x2d'); }; -var convert_1$x = convert$y; +var convert_1$x = convert$A; -function convert$y(test) { +function convert$A(test) { if (typeof test === 'string') { return typeFactory$x(test) } @@ -50873,7 +53406,7 @@ function convertAll$x(tests) { var index = -1; while (++index < length) { - results[index] = convert$y(tests[index]); + results[index] = convert$A(tests[index]); } return results @@ -51182,9 +53715,9 @@ function prohibitedStrings (ast, file, strings) { } } -var convert_1$y = convert$z; +var convert_1$y = convert$B; -function convert$z(test) { +function convert$B(test) { if (typeof test === 'string') { return typeFactory$y(test) } @@ -51210,7 +53743,7 @@ function convertAll$y(tests) { var index = -1; while (++index < length) { - results[index] = convert$z(tests[index]); + results[index] = convert$B(tests[index]); } return results @@ -51415,9 +53948,9 @@ function ruleStyle(tree, file, option) { } } -var convert_1$z = convert$A; +var convert_1$z = convert$C; -function convert$A(test) { +function convert$C(test) { if (typeof test === 'string') { return typeFactory$z(test) } @@ -51443,7 +53976,7 @@ function convertAll$z(tests) { var index = -1; while (++index < length) { - results[index] = convert$A(tests[index]); + results[index] = convert$C(tests[index]); } return results @@ -51643,9 +54176,9 @@ function strongMarker(tree, file, option) { } } -var convert_1$A = convert$B; +var convert_1$A = convert$D; -function convert$B(test) { +function convert$D(test) { if (typeof test === 'string') { return typeFactory$A(test) } @@ -51671,7 +54204,7 @@ function convertAll$A(tests) { var index = -1; while (++index < length) { - results[index] = convert$B(tests[index]); + results[index] = convert$D(tests[index]); } return results @@ -51839,14 +54372,14 @@ var remarkLintTableCellPadding = unifiedLintRule('remark-lint:table-cell-padding var start$i = unistUtilPosition.start; var end$a = unistUtilPosition.end; -var styles$3 = {null: true, padded: true, compact: true}; +var styles$4 = {null: true, padded: true, compact: true}; function tableCellPadding(tree, file, option) { var contents = String(file); var preferred = typeof option === 'string' && option !== 'consistent' ? option : null; - if (styles$3[preferred] !== true) { + if (styles$4[preferred] !== true) { file.fail( 'Incorrect table cell padding style `' + preferred + @@ -51970,9 +54503,9 @@ function size(node) { return end$a(node).offset - start$i(node).offset } -var convert_1$B = convert$C; +var convert_1$B = convert$E; -function convert$C(test) { +function convert$E(test) { if (typeof test === 'string') { return typeFactory$B(test) } @@ -51998,7 +54531,7 @@ function convertAll$B(tests) { var index = -1; while (++index < length) { - results[index] = convert$C(tests[index]); + results[index] = convert$E(tests[index]); } return results @@ -52207,9 +54740,9 @@ function tablePipes(tree, file) { } } -var convert_1$C = convert$D; +var convert_1$C = convert$F; -function convert$D(test) { +function convert$F(test) { if (typeof test === 'string') { return typeFactory$C(test) } @@ -52235,7 +54768,7 @@ function convertAll$C(tests) { var index = -1; while (++index < length) { - results[index] = convert$D(tests[index]); + results[index] = convert$F(tests[index]); } return results @@ -52405,7 +54938,7 @@ var remarkLintUnorderedListMarkerStyle = unifiedLintRule( var start$k = unistUtilPosition.start; -var styles$4 = { +var styles$5 = { '-': true, '*': true, '+': true, @@ -52417,7 +54950,7 @@ function unorderedListMarkerStyle(tree, file, option) { var preferred = typeof option === 'string' && option !== 'consistent' ? option : null; - if (styles$4[preferred] !== true) { + if (styles$5[preferred] !== true) { file.fail( 'Incorrect unordered list item marker style `' + preferred + diff --git a/tools/node-lint-md-cli-rollup/package-lock.json b/tools/node-lint-md-cli-rollup/package-lock.json index f1a8df25bef8c1..efd36027c65c22 100644 --- a/tools/node-lint-md-cli-rollup/package-lock.json +++ b/tools/node-lint-md-cli-rollup/package-lock.json @@ -4,6 +4,75 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "requires": { + "@babel/highlight": "^7.8.3" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.9.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz", + "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==" + }, + "@babel/highlight": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz", + "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==", + "requires": { + "@babel/helper-validator-identifier": "^7.9.0", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, "@rollup/plugin-commonjs": { "version": "11.0.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-11.0.1.tgz", @@ -48,6 +117,11 @@ "estree-walker": "^0.6.1" } }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" + }, "@types/estree": { "version": "0.0.39", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", @@ -86,11 +160,12 @@ "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" }, "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", "requires": { - "color-convert": "^1.9.0" + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" } }, "anymatch": { @@ -111,9 +186,9 @@ } }, "bail": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.4.tgz", - "integrity": "sha512-S8vuDB4w6YpRhICUDET3guPlQpaJl7od94tpZ0Fvnyp+MKW/HyDTcRDck+29C9g+d/qQHnddRH3+94kZdrW0Ww==" + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", + "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==" }, "balanced-match": { "version": "1.0.0", @@ -159,44 +234,43 @@ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" }, "ccount": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.4.tgz", - "integrity": "sha512-fpZ81yYfzentuieinmGnphk0pLkOTMm6MZdVqwd77ROvhko6iujLNGrHH5E7utq3ygWklwfmwuG+A7P+NpqT6w==" + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.5.tgz", + "integrity": "sha512-MOli1W+nfbPLlKEhInaxhRdp7KVLFxLN5ykwzHgLsLI3H3gs5jjFAK4Eoj3OzzcxCtumDaI8onoVDeQyWaNTkw==" }, "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, "character-entities": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.3.tgz", - "integrity": "sha512-yB4oYSAa9yLcGyTbB4ItFwHw43QHdH129IJ5R+WvxOkWlyFnR5FAaBNnUq4mcxsTVZGh28bHoeTHMKXH1wZf3w==" + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", + "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==" }, "character-entities-html4": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.3.tgz", - "integrity": "sha512-SwnyZ7jQBCRHELk9zf2CN5AnGEc2nA+uKMZLHvcqhpPprjkYhiLn0DywMHgN5ttFZuITMATbh68M6VIVKwJbcg==" + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.4.tgz", + "integrity": "sha512-HRcDxZuZqMx3/a+qrzxdBKBPUpxWEq9xw2OPZ3a/174ihfrQKVsFhqtthBInFy1zZ9GgZyFXOatNujm8M+El3g==" }, "character-entities-legacy": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.3.tgz", - "integrity": "sha512-YAxUpPoPwxYFsslbdKkhrGnXAtXoHNgYjlBM3WMXkWGTl5RsY3QmOyhwAgL8Nxm9l5LBThXGawxKPn68y6/fww==" + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", + "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==" }, "character-reference-invalid": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.3.tgz", - "integrity": "sha512-VOq6PRzQBam/8Jm6XBGk2fNEnHXAdGd6go0rtd4weAGECBamHDwwCQSOT12TACIYUZegUXnV6xBXqUssijtxIg==" + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", + "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==" }, "chokidar": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.1.tgz", - "integrity": "sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.0.tgz", + "integrity": "sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==", "requires": { "anymatch": "~3.1.1", "braces": "~3.0.2", @@ -205,7 +279,7 @@ "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.3.0" + "readdirp": "~3.4.0" } }, "co": { @@ -219,17 +293,17 @@ "integrity": "sha512-703bOOmytCYAX9cXYqoikYIx6twmFCXsnzRQheBcTG3nzKYBR4P/+wkYeH+Mvj7qUz8zZDtdyzbxfnEi/kYzRQ==" }, "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "requires": { - "color-name": "1.1.3" + "color-name": "~1.1.4" } }, "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "concat-map": { "version": "0.0.1", @@ -255,11 +329,6 @@ "ms": "^2.1.1" } }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" - }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -308,6 +377,11 @@ "format": "^0.2.0" } }, + "figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==" + }, "figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -324,10 +398,13 @@ "to-regex-range": "^5.0.1" } }, - "fn-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fn-name/-/fn-name-2.0.1.tgz", - "integrity": "sha1-UhTXU3pNBqSjAcDMJi/rhBiAAuc=" + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } }, "format": { "version": "0.2.2", @@ -340,9 +417,9 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", - "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", "optional": true }, "glob": { @@ -359,17 +436,17 @@ } }, "glob-parent": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", - "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", "requires": { "is-glob": "^4.0.1" } }, "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, "ignore": { "version": "5.1.4", @@ -402,9 +479,9 @@ "dev": true }, "is-alphabetical": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.3.tgz", - "integrity": "sha512-eEMa6MKpHFzw38eKm56iNNi6GJ7lf6aLLio7Kr23sJPAECscgRtZvOBYybejWDQ2bM949Y++61PY+udzj5QMLA==" + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", + "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==" }, "is-alphanumeric": { "version": "1.0.0", @@ -412,9 +489,9 @@ "integrity": "sha1-Spzvcdr0wAHB2B1j0UDPU/1oifQ=" }, "is-alphanumerical": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.3.tgz", - "integrity": "sha512-A1IGAPO5AW9vSh7omxIlOGwIqEvpW/TA+DksVOPM5ODuxKlZS09+TEM1E3275lJqO2oJ38vDpeAL3DCIiHE6eA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", + "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", "requires": { "is-alphabetical": "^1.0.0", "is-decimal": "^1.0.0" @@ -439,9 +516,9 @@ "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==" }, "is-decimal": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.3.tgz", - "integrity": "sha512-bvLSwoDg2q6Gf+E2LEPiklHZxxiSi3XAh4Mav65mKqTfCO1HM3uBs24TjEH8iJX3bbDdLXKJXBTmGzuTUuAEjQ==" + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", + "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==" }, "is-empty": { "version": "1.2.0", @@ -467,14 +544,9 @@ } }, "is-hexadecimal": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.3.tgz", - "integrity": "sha512-zxQ9//Q3D/34poZf8fiy3m3XVpbQc7ren15iKqrTtLPwkPD/t3Scy9Imp63FujULGxuK0ZlCwoo5xNpktFgbOA==" - }, - "is-hidden": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-hidden/-/is-hidden-1.1.3.tgz", - "integrity": "sha512-FFzhGKA9h59OFxeaJl0W5ILTYetI8WsdqdofKr69uLKZdV6hbDKxj8vkpG3L9uS/6Q/XYh1tkXm6xwRGFweETA==" + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", + "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==" }, "is-module": { "version": "1.0.0", @@ -487,15 +559,10 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, - "is-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", - "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=" - }, "is-plain-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.0.0.tgz", - "integrity": "sha512-EYisGhpgSCwspmIuRHGjROWTon2Xp8Z7U03Wubk/bTL5TTRC5R1rGVgyjzBrk9+ULdH6cRD06KRcw/xfqhVYKQ==" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==" }, "is-reference": { "version": "1.1.4", @@ -507,14 +574,19 @@ } }, "is-whitespace-character": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.3.tgz", - "integrity": "sha512-SNPgMLz9JzPccD3nPctcj8sZlX9DAMJSKH8bP7Z6bohCwuNgX8xbWr1eTAYXX9Vpi/aSn8Y1akL9WgM3t43YNQ==" + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz", + "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==" }, "is-word-character": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.3.tgz", - "integrity": "sha512-0wfcrFgOOOBdgRNT9H33xe6Zi6yhX/uoc4U8NBZGeQQB0ctU1dnlNTyL9JM2646bHDTpsDm1Brb3VPoCIMrd/A==" + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz", + "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==" + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "js-yaml": { "version": "3.13.1", @@ -531,26 +603,50 @@ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" }, "json5": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz", - "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "requires": { + "minimist": "^1.2.5" + } + }, + "libnpmconfig": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/libnpmconfig/-/libnpmconfig-1.2.1.tgz", + "integrity": "sha512-9esX8rTQAHqarx6qeZqmGQKBNZR5OIbl/Ayr0qQDy3oXja2iFVQQI81R6GZ2a02bSNZ9p3YOGX1O6HHCb1X7kA==", "requires": { - "minimist": "^1.2.0" + "figgy-pudding": "^3.5.1", + "find-up": "^3.0.0", + "ini": "^1.3.5" } }, + "lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=" + }, "load-plugin": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/load-plugin/-/load-plugin-2.3.1.tgz", - "integrity": "sha512-dYB1lbwqHgPTrruy9glukCu8Ya9vzj6TMfouCtj2H/GuJ+8syioisgKTBPxnCi6m8K8jINKfTOxOHngFkUYqHw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/load-plugin/-/load-plugin-3.0.0.tgz", + "integrity": "sha512-od7eKCCZ62ITvFf8nHHrIiYmgOHb4xVNDRDqxBWSaao5FZyyZVX8OmRCbwjDGPrSrgIulwPNyBsWCGnhiDC0oQ==", "requires": { - "npm-prefix": "^1.2.0", + "libnpmconfig": "^1.0.0", "resolve-from": "^5.0.0" } }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, "longest-streak": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.3.tgz", - "integrity": "sha512-9lz5IVdpwsKLMzQi0MQ+oD9EA0mIGcWYP7jXMTZVXP8D42PwuAk+M/HBFYQoxt1G5OR8m7aSIgb1UymfWGBWEw==" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.4.tgz", + "integrity": "sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg==" }, "magic-string": { "version": "0.25.6", @@ -562,9 +658,9 @@ } }, "markdown-escapes": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.3.tgz", - "integrity": "sha512-XUi5HJhhV5R74k8/0H2oCbCiYf/u4cO/rX8tnGkRvrqhsr5BRNU6Mg0yt/8UIx1iIS8220BNJsDb7XnILhLepw==" + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz", + "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==" }, "markdown-extensions": { "version": "1.1.1", @@ -572,9 +668,12 @@ "integrity": "sha512-WWC0ZuMzCyDHYCasEGs4IPvLyTGftYwh6wIEOULOF0HXcqZlhwRzrK0w2VUlxWA98xnvb/jszw4ZSkJ6ADpM6Q==" }, "markdown-table": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.3.tgz", - "integrity": "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz", + "integrity": "sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A==", + "requires": { + "repeat-string": "^1.0.0" + } }, "mdast-comment-marker": { "version": "1.1.1", @@ -582,11 +681,11 @@ "integrity": "sha512-TWZDaUtPLwKX1pzDIY48MkSUQRDwX/HqbTB4m3iYdL/zosi/Z6Xqfdv0C0hNVKvzrPjZENrpWDt4p4odeVO0Iw==" }, "mdast-util-compact": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.4.tgz", - "integrity": "sha512-3YDMQHI5vRiS2uygEFYaqckibpJtKq5Sj2c8JioeOQBU6INpKbdWzfyLqFFnDwEcEnRFIdMsguzs5pC1Jp4Isg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-2.0.1.tgz", + "integrity": "sha512-7GlnT24gEwDrdAwEHrU4Vv5lLWrEer4KOkAiKT9nYstsTad7Oc1TwqT2zIMKRdZF7cTuaf+GA1E4Kv7jJh8mPA==", "requires": { - "unist-util-visit": "^1.1.0" + "unist-util-visit": "^2.0.0" } }, "mdast-util-heading-style": { @@ -622,16 +721,6 @@ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" }, - "npm-prefix": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/npm-prefix/-/npm-prefix-1.2.0.tgz", - "integrity": "sha1-5hlFX3B0ulTMZtbQ033Z8b5ry8A=", - "requires": { - "rc": "^1.1.0", - "shellsubstitute": "^1.1.0", - "untildify": "^2.1.0" - } - }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -640,15 +729,31 @@ "wrappy": "1" } }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, "parse-entities": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.2.tgz", - "integrity": "sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", + "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", "requires": { "character-entities": "^1.0.0", "character-entities-legacy": "^1.0.0", @@ -659,14 +764,21 @@ } }, "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz", + "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==", "requires": { + "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" + "json-parse-better-errors": "^1.0.1", + "lines-and-columns": "^1.1.6" } }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -679,26 +791,15 @@ "dev": true }, "picomatch": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.1.tgz", - "integrity": "sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA==" + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==" }, "pluralize": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==" }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - } - }, "readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -710,11 +811,11 @@ } }, "readdirp": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.3.0.tgz", - "integrity": "sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", + "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", "requires": { - "picomatch": "^2.0.7" + "picomatch": "^2.2.1" } }, "rechoir": { @@ -727,21 +828,21 @@ } }, "remark": { - "version": "11.0.2", - "resolved": "https://registry.npmjs.org/remark/-/remark-11.0.2.tgz", - "integrity": "sha512-bh+eJgn8wgmbHmIBOuwJFdTVRVpl3fcVP6HxmpPWO0ULGP9Qkh6INJh0N5Uy7GqlV7DQYGoqaKiEIpM5LLvJ8w==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/remark/-/remark-12.0.0.tgz", + "integrity": "sha512-oX4lMIS0csgk8AEbzY0h2jdR0ngiCHOpwwpxjmRa5TqAkeknY+tkhjRJGZqnCmvyuWh55/0SW5WY3R3nn3PH9A==", "requires": { - "remark-parse": "^7.0.0", - "remark-stringify": "^7.0.0", - "unified": "^8.2.0" + "remark-parse": "^8.0.0", + "remark-stringify": "^8.0.0", + "unified": "^9.0.0" } }, "remark-lint": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/remark-lint/-/remark-lint-6.0.5.tgz", - "integrity": "sha512-o1I3ddm+KNsTxk60wWGI+p2yU1jB1gcm8jo2Sy6VhJ4ab2TrQIp1oQbp5xeLoFXYSh/NAqCpKjHkCM/BYpkFdQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/remark-lint/-/remark-lint-7.0.0.tgz", + "integrity": "sha512-OLrWPYy0MUcGLa/2rjuy1kQILTRRK+JiRtyUzqe4XRoHboGuvFDcy/W2e7sq5hu/0xmD+Eh7cEa1Coiqp7LeaA==", "requires": { - "remark-message-control": "^4.0.0" + "remark-message-control": "^6.0.0" } }, "remark-lint-blockquote-indentation": { @@ -2177,34 +2278,34 @@ } }, "remark-message-control": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/remark-message-control/-/remark-message-control-4.2.0.tgz", - "integrity": "sha512-WXH2t5ljTyhsXlK1zPBLF3iPHbXl58R94phPMreS1xcHWBZJt6Oiu8RtNjy1poZFb3PqKnbYLJeR/CWcZ1bTFw==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/remark-message-control/-/remark-message-control-6.0.0.tgz", + "integrity": "sha512-k9bt7BYc3G7YBdmeAhvd3VavrPa/XlKWR3CyHjr4sLO9xJyly8WHHT3Sp+8HPR8lEUv+/sZaffL7IjMLV0f6BA==", "requires": { "mdast-comment-marker": "^1.0.0", - "unified-message-control": "^1.0.0", - "xtend": "^4.0.1" + "unified-message-control": "^3.0.0" } }, "remark-parse": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-7.0.2.tgz", - "integrity": "sha512-9+my0lQS80IQkYXsMA8Sg6m9QfXYJBnXjWYN5U+kFc5/n69t+XZVXU/ZBYr3cYH8FheEGf1v87rkFDhJ8bVgMA==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.2.tgz", + "integrity": "sha512-eMI6kMRjsAGpMXXBAywJwiwAse+KNpmt+BK55Oofy4KvBZEqUDj6mWbGLJZrujoPIPPxDXzn3T9baRlpsm2jnQ==", "requires": { + "ccount": "^1.0.0", "collapse-white-space": "^1.0.2", "is-alphabetical": "^1.0.0", "is-decimal": "^1.0.0", "is-whitespace-character": "^1.0.0", "is-word-character": "^1.0.0", "markdown-escapes": "^1.0.0", - "parse-entities": "^1.1.0", + "parse-entities": "^2.0.0", "repeat-string": "^1.5.4", "state-toggle": "^1.0.0", "trim": "0.0.1", "trim-trailing-lines": "^1.0.0", "unherit": "^1.0.4", - "unist-util-remove-position": "^1.0.0", - "vfile-location": "^2.0.0", + "unist-util-remove-position": "^2.0.0", + "vfile-location": "^3.0.0", "xtend": "^4.0.1" } }, @@ -2384,9 +2485,9 @@ } }, "remark-stringify": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-7.0.4.tgz", - "integrity": "sha512-qck+8NeA1D0utk1ttKcWAoHRrJxERYQzkHDyn+pF5Z4whX1ug98uCNPPSeFgLSaNERRxnD6oxIug6DzZQth6Pg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-8.0.0.tgz", + "integrity": "sha512-cABVYVloFH+2ZI5bdqzoOmemcz/ZuhQSH6W6ZNYnLojAUUn3xtX7u+6BpnYp35qHoGr2NFBsERV14t4vCIeW8w==", "requires": { "ccount": "^1.0.0", "is-alphanumeric": "^1.0.0", @@ -2394,12 +2495,12 @@ "is-whitespace-character": "^1.0.0", "longest-streak": "^2.0.1", "markdown-escapes": "^1.0.0", - "markdown-table": "^1.1.0", - "mdast-util-compact": "^1.0.0", - "parse-entities": "^1.0.2", + "markdown-table": "^2.0.0", + "mdast-util-compact": "^2.0.0", + "parse-entities": "^2.0.0", "repeat-string": "^1.5.4", "state-toggle": "^1.0.0", - "stringify-entities": "^2.0.0", + "stringify-entities": "^3.0.0", "unherit": "^1.0.4", "xtend": "^4.0.1" } @@ -2449,9 +2550,9 @@ } }, "safe-buffer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, "shelljs": { "version": "0.8.3", @@ -2464,11 +2565,6 @@ "rechoir": "^0.6.2" } }, - "shellsubstitute": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shellsubstitute/-/shellsubstitute-1.2.0.tgz", - "integrity": "sha1-5PcCpQxRiw9v6YRRiQ1wWvKba3A=" - }, "shx": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/shx/-/shx-0.3.2.tgz", @@ -2497,9 +2593,9 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "state-toggle": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.2.tgz", - "integrity": "sha512-8LpelPGR0qQM4PnfLiplOQNJcIN1/r2Gy0xKB2zKnIW2YzPMt2sR4I/+gtPjhN7Svh9kw+zqEg2SFwpBO9iNiw==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz", + "integrity": "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==" }, "string-width": { "version": "4.2.0", @@ -2520,9 +2616,9 @@ } }, "stringify-entities": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-2.0.0.tgz", - "integrity": "sha512-fqqhZzXyAM6pGD9lky/GOPq6V4X0SeTAFBl0iXb/BzOegl40gpf/bV3QQP7zULNYvjr6+Dx8SCaDULjVoOru0A==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-3.0.1.tgz", + "integrity": "sha512-Lsk3ISA2++eJYqBMPKcr/8eby1I6L0gP0NlxF8Zja6c05yr/yCYyb2c9PwXjd08Ib3If1vn1rbs1H5ZtVuOfvQ==", "requires": { "character-entities-html4": "^1.0.0", "character-entities-legacy": "^1.0.0", @@ -2539,17 +2635,12 @@ "ansi-regex": "^5.0.0" } }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" - }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", "requires": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" } }, "text-table": { @@ -2580,9 +2671,9 @@ "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=" }, "trim-trailing-lines": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.2.tgz", - "integrity": "sha512-MUjYItdrqqj2zpcHFTkMa9WAv4JHTI6gnRQGPFLrt5L9a6tRMiDnIqYl8JBvu2d2Tc3lWJKQwlGCp0K8AvCM+Q==" + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.3.tgz", + "integrity": "sha512-4ku0mmjXifQcTVfYDfR5lpgV7zVqPg6zV9rdZmwOPqq0+Zq19xDqEgagqVbc4pOOShbncuAOIs59R3+3gcF3ZA==" }, "trough": { "version": "1.0.4", @@ -2595,66 +2686,64 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, "unherit": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.2.tgz", - "integrity": "sha512-W3tMnpaMG7ZY6xe/moK04U9fBhi6wEiCYHUW5Mop/wQHf12+79EQGwxYejNdhEz2mkqkBlGwm7pxmgBKMVUj0w==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz", + "integrity": "sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==", "requires": { - "inherits": "^2.0.1", - "xtend": "^4.0.1" + "inherits": "^2.0.0", + "xtend": "^4.0.0" } }, "unified": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-8.4.2.tgz", - "integrity": "sha512-JCrmN13jI4+h9UAyKEoGcDZV+i1E7BLFuG7OsaDvTXI5P0qhHX+vZO/kOhz9jn8HGENDKbwSeB0nVOg4gVStGA==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/unified/-/unified-9.0.0.tgz", + "integrity": "sha512-ssFo33gljU3PdlWLjNp15Inqb77d6JnJSfyplGJPT/a+fNRNyCBeveBAYJdO5khKdF6WVHa/yYCC7Xl6BDwZUQ==", "requires": { "bail": "^1.0.0", "extend": "^3.0.0", + "is-buffer": "^2.0.0", "is-plain-obj": "^2.0.0", "trough": "^1.0.0", "vfile": "^4.0.0" } }, "unified-args": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/unified-args/-/unified-args-7.1.0.tgz", - "integrity": "sha512-soi9Rn7l5c1g0RfElSCHMwaxeiclSI0EsS3uZmMPUOfwMeeeZjLpNmHAowV9iSlQh59iiZhSMyQu9lB8WnIz5g==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/unified-args/-/unified-args-8.0.0.tgz", + "integrity": "sha512-224jfXOL0Xu0e52fJTfxmAaNTuW1zopPmnXh/5GDAxx4Z6NbcZpjgQPBmo1xoLAhGih0rWVG2+a2kodzrEHfHw==", "requires": { "camelcase": "^5.0.0", - "chalk": "^2.0.0", + "chalk": "^3.0.0", "chokidar": "^3.0.0", "fault": "^1.0.2", "json5": "^2.0.0", "minimist": "^1.2.0", "text-table": "^0.2.0", - "unified-engine": "^7.0.0" + "unified-engine": "^8.0.0" } }, "unified-engine": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/unified-engine/-/unified-engine-7.0.0.tgz", - "integrity": "sha512-zH/MvcISpWg3JZtCoY/GYBw1WnVHkhnPoMBWpmuvAifCPSS9mzT9EbtimesJp6t2nnr/ojI0mg3TmkO1CjIwVA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/unified-engine/-/unified-engine-8.0.0.tgz", + "integrity": "sha512-vLUezxCnjzz+ya4pYouRQVMT8k82Rk4fIj406UidRnSFJdGXFaQyQklAnalsQHJrLqAlaYPkXPUa1upfVSHGCA==", "requires": { "concat-stream": "^2.0.0", "debug": "^4.0.0", "fault": "^1.0.0", "figures": "^3.0.0", - "fn-name": "^2.0.1", "glob": "^7.0.3", "ignore": "^5.0.0", + "is-buffer": "^2.0.0", "is-empty": "^1.0.0", - "is-hidden": "^1.0.1", - "is-object": "^1.0.1", + "is-plain-obj": "^2.0.0", "js-yaml": "^3.6.1", - "load-plugin": "^2.0.0", - "parse-json": "^4.0.0", + "load-plugin": "^3.0.0", + "parse-json": "^5.0.0", "to-vfile": "^6.0.0", "trough": "^1.0.0", - "unist-util-inspect": "^4.1.2", + "unist-util-inspect": "^5.0.0", "vfile-reporter": "^6.0.0", - "vfile-statistics": "^1.1.0", - "x-is-string": "^0.1.0", - "xtend": "^4.0.1" + "vfile-statistics": "^1.1.0" } }, "unified-lint-rule": { @@ -2666,13 +2755,43 @@ } }, "unified-message-control": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unified-message-control/-/unified-message-control-1.0.4.tgz", - "integrity": "sha512-e1dEtN4Z/TvLn/qHm+xeZpzqhJTtfZusFErk336kkZVpqrJYiV9ptxq+SbRPFMlN0OkjDYHmVJ929KYjsMTo3g==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/unified-message-control/-/unified-message-control-3.0.1.tgz", + "integrity": "sha512-K2Kvvp1DBzeuxYLLsumZh/gDWUTl4e2z/P3VReFirC78cfHKtQifbhnfRrSBtKtd1Uc6cvYTW0/SZIUaMAEcTg==", "requires": { - "trim": "0.0.1", - "unist-util-visit": "^1.0.0", - "vfile-location": "^2.0.0" + "unist-util-visit": "^2.0.0", + "vfile-location": "^3.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + }, + "vfile-location": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-3.0.1.tgz", + "integrity": "sha512-yYBO06eeN/Ki6Kh1QAkgzYpWT1d3Qln+ZCtSbJqFExPl1S3y2qqotJQXoh6qEvl/jDlgpUJolBn3PItVnnZRqQ==" + } } }, "unist-util-generated": { @@ -2681,17 +2800,17 @@ "integrity": "sha512-1TC+NxQa4N9pNdayCYA1EGUOCAO0Le3fVp7Jzns6lnua/mYgwHo0tz5WUAfrdpNch1RZLHc61VZ1SDgrtNXLSw==" }, "unist-util-inspect": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/unist-util-inspect/-/unist-util-inspect-4.1.4.tgz", - "integrity": "sha512-7xxyvKiZ1SC9vL5qrMqKub1T31gRHfau4242F69CcaOrXt//5PmRVOmDZ36UAEgiT+tZWzmQmbNZn+mVtnR9HQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/unist-util-inspect/-/unist-util-inspect-5.0.1.tgz", + "integrity": "sha512-fPNWewS593JSmg49HbnE86BJKuBi1/nMWhDSccBvbARfxezEuJV85EaARR9/VplveiwCoLm2kWq+DhP8TBaDpw==", "requires": { "is-empty": "^1.0.0" } }, "unist-util-is": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-3.0.0.tgz", - "integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==" + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" }, "unist-util-position": { "version": "3.1.0", @@ -2699,11 +2818,11 @@ "integrity": "sha512-w+PkwCbYSFw8vpgWD0v7zRCl1FpY3fjDSQ3/N/wNd9Ffa4gPi8+4keqt99N3XW6F99t/mUzp2xAhNmfKWp95QA==" }, "unist-util-remove-position": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.4.tgz", - "integrity": "sha512-tLqd653ArxJIPnKII6LMZwH+mb5q+n/GtXQZo6S6csPRs5zB0u79Yw8ouR3wTw8wxvdJFhpP6Y7jorWdCgLO0A==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-2.0.1.tgz", + "integrity": "sha512-fDZsLYIe2uT+oGFnuZmy73K6ZxOPG/Qcm+w7jbEjaFcJgbQ6cqjs/eSPzXhsmGpAsWPkqZM9pYjww5QTn3LHMA==", "requires": { - "unist-util-visit": "^1.1.0" + "unist-util-visit": "^2.0.0" } }, "unist-util-stringify-position": { @@ -2715,27 +2834,22 @@ } }, "unist-util-visit": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz", - "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", "requires": { - "unist-util-visit-parents": "^2.0.0" + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" } }, "unist-util-visit-parents": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz", - "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==", - "requires": { - "unist-util-is": "^3.0.0" - } - }, - "untildify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-2.1.0.tgz", - "integrity": "sha1-F+soB5h/dpUunASF/DEdBqgmouA=", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", "requires": { - "os-homedir": "^1.0.0" + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" } }, "util-deprecate": { @@ -2756,9 +2870,9 @@ } }, "vfile-location": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.6.tgz", - "integrity": "sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA==" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-3.0.1.tgz", + "integrity": "sha512-yYBO06eeN/Ki6Kh1QAkgzYpWT1d3Qln+ZCtSbJqFExPl1S3y2qqotJQXoh6qEvl/jDlgpUJolBn3PItVnnZRqQ==" }, "vfile-message": { "version": "2.0.2", @@ -2782,6 +2896,11 @@ "vfile-statistics": "^1.1.0" }, "dependencies": { + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, "supports-color": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", @@ -2816,11 +2935,6 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, - "x-is-string": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", - "integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=" - }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/tools/node-lint-md-cli-rollup/package.json b/tools/node-lint-md-cli-rollup/package.json index 58ea5ee80a3dad..aa203f67b33217 100644 --- a/tools/node-lint-md-cli-rollup/package.json +++ b/tools/node-lint-md-cli-rollup/package.json @@ -11,10 +11,10 @@ }, "dependencies": { "markdown-extensions": "^1.1.1", - "remark": "^11.0.2", - "remark-lint": "^6.0.5", + "remark": "^12.0.0", + "remark-lint": "^7.0.0", "remark-preset-lint-node": "^1.15.0", - "unified-args": "^7.1.0" + "unified-args": "^8.0.0" }, "main": "dist/index.js", "scripts": { diff --git a/tools/node_modules/eslint/README.md b/tools/node_modules/eslint/README.md index 0a802b0c25d0ca..427544bad668c0 100644 --- a/tools/node_modules/eslint/README.md +++ b/tools/node_modules/eslint/README.md @@ -250,7 +250,7 @@ The following companies, organizations, and individuals support ESLint's ongoing

Gold Sponsors

-

Shopify Salesforce Airbnb

Silver Sponsors

+

Shopify Salesforce Airbnb

Silver Sponsors

AMP Project

Bronze Sponsors

CasinoTop.com Casino Topp Writers Per Hour Anagram Solver vpn netflix Kasinot.fi Pelisivut Nettikasinot.org BonusFinder Deutschland Top Web Design Agencies Bugsnag Stability Monitoring Mixpanel VPS Server Free Icons by Icons8 UI UX Design Agencies clay Discord ThemeIsle TekHattan Marfeel Fire Stick Tricks

diff --git a/tools/node_modules/eslint/conf/category-list.json b/tools/node_modules/eslint/conf/category-list.json index 6609734950a443..cd3b816b6570a2 100644 --- a/tools/node_modules/eslint/conf/category-list.json +++ b/tools/node_modules/eslint/conf/category-list.json @@ -4,7 +4,6 @@ { "name": "Best Practices", "description": "These rules relate to better ways of doing things to help you avoid problems:" }, { "name": "Strict Mode", "description": "These rules relate to strict mode directives:" }, { "name": "Variables", "description": "These rules relate to variable declarations:" }, - { "name": "Node.js and CommonJS", "description": "These rules relate to code running in Node.js, or in browsers with CommonJS:" }, { "name": "Stylistic Issues", "description": "These rules relate to style guidelines, and are therefore quite subjective:" }, { "name": "ECMAScript 6", "description": "These rules relate to ES6, also known as ES2015:" } ], diff --git a/tools/node_modules/eslint/node_modules/@types/color-name/LICENSE b/tools/node_modules/eslint/node_modules/@types/color-name/LICENSE index 21071075c24599..4b1ad51b2f0efc 100644 --- a/tools/node_modules/eslint/node_modules/@types/color-name/LICENSE +++ b/tools/node_modules/eslint/node_modules/@types/color-name/LICENSE @@ -1,21 +1,21 @@ - MIT License - - Copyright (c) Microsoft Corporation. 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 + MIT License + + Copyright (c) Microsoft Corporation. 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 diff --git a/tools/node_modules/eslint/node_modules/@types/color-name/README.md b/tools/node_modules/eslint/node_modules/@types/color-name/README.md index d08d108b2b5b67..5c77cba829c5bd 100644 --- a/tools/node_modules/eslint/node_modules/@types/color-name/README.md +++ b/tools/node_modules/eslint/node_modules/@types/color-name/README.md @@ -1,16 +1,16 @@ -# Installation -> `npm install --save @types/color-name` - -# Summary -This package contains type definitions for color-name ( https://github.com/colorjs/color-name ). - -# Details -Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/color-name - -Additional Details - * Last updated: Wed, 13 Feb 2019 16:16:48 GMT - * Dependencies: none - * Global values: none - -# Credits -These definitions were written by Junyoung Clare Jang . +# Installation +> `npm install --save @types/color-name` + +# Summary +This package contains type definitions for color-name ( https://github.com/colorjs/color-name ). + +# Details +Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/color-name + +Additional Details + * Last updated: Wed, 13 Feb 2019 16:16:48 GMT + * Dependencies: none + * Global values: none + +# Credits +These definitions were written by Junyoung Clare Jang . diff --git a/tools/node_modules/eslint/node_modules/chalk/node_modules/color-convert/LICENSE b/tools/node_modules/eslint/node_modules/chalk/node_modules/color-convert/LICENSE index 0e2e4909183090..5b4c386f9269b3 100644 --- a/tools/node_modules/eslint/node_modules/chalk/node_modules/color-convert/LICENSE +++ b/tools/node_modules/eslint/node_modules/chalk/node_modules/color-convert/LICENSE @@ -18,3 +18,4 @@ 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. + diff --git a/tools/node_modules/eslint/node_modules/chalk/node_modules/color-convert/route.js b/tools/node_modules/eslint/node_modules/chalk/node_modules/color-convert/route.js index 09ba94309070c5..1a08521b5a0017 100644 --- a/tools/node_modules/eslint/node_modules/chalk/node_modules/color-convert/route.js +++ b/tools/node_modules/eslint/node_modules/chalk/node_modules/color-convert/route.js @@ -94,3 +94,4 @@ module.exports = function (fromModel) { return conversion; }; + diff --git a/tools/node_modules/eslint/node_modules/chalk/node_modules/color-name/LICENSE b/tools/node_modules/eslint/node_modules/chalk/node_modules/color-name/LICENSE index 4d9802a89e2999..c6b10012540c24 100644 --- a/tools/node_modules/eslint/node_modules/chalk/node_modules/color-name/LICENSE +++ b/tools/node_modules/eslint/node_modules/chalk/node_modules/color-name/LICENSE @@ -1,8 +1,8 @@ -The MIT License (MIT) -Copyright (c) 2015 Dmitry Ivanov - -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 MIT License (MIT) +Copyright (c) 2015 Dmitry Ivanov + +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. \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/chalk/node_modules/color-name/README.md b/tools/node_modules/eslint/node_modules/chalk/node_modules/color-name/README.md index 3611a6b523fe85..932b979176f33b 100644 --- a/tools/node_modules/eslint/node_modules/chalk/node_modules/color-name/README.md +++ b/tools/node_modules/eslint/node_modules/chalk/node_modules/color-name/README.md @@ -1,11 +1,11 @@ -A JSON with color names and its values. Based on http://dev.w3.org/csswg/css-color/#named-colors. - -[![NPM](https://nodei.co/npm/color-name.png?mini=true)](https://nodei.co/npm/color-name/) - - -```js -var colors = require('color-name'); -colors.red //[255,0,0] -``` - - +A JSON with color names and its values. Based on http://dev.w3.org/csswg/css-color/#named-colors. + +[![NPM](https://nodei.co/npm/color-name.png?mini=true)](https://nodei.co/npm/color-name/) + + +```js +var colors = require('color-name'); +colors.red //[255,0,0] +``` + + diff --git a/tools/node_modules/eslint/node_modules/chalk/node_modules/color-name/index.js b/tools/node_modules/eslint/node_modules/chalk/node_modules/color-name/index.js index e42aa68a542d9e..b7c198a6f3d7c5 100644 --- a/tools/node_modules/eslint/node_modules/chalk/node_modules/color-name/index.js +++ b/tools/node_modules/eslint/node_modules/chalk/node_modules/color-name/index.js @@ -1,152 +1,152 @@ -'use strict' - -module.exports = { - "aliceblue": [240, 248, 255], - "antiquewhite": [250, 235, 215], - "aqua": [0, 255, 255], - "aquamarine": [127, 255, 212], - "azure": [240, 255, 255], - "beige": [245, 245, 220], - "bisque": [255, 228, 196], - "black": [0, 0, 0], - "blanchedalmond": [255, 235, 205], - "blue": [0, 0, 255], - "blueviolet": [138, 43, 226], - "brown": [165, 42, 42], - "burlywood": [222, 184, 135], - "cadetblue": [95, 158, 160], - "chartreuse": [127, 255, 0], - "chocolate": [210, 105, 30], - "coral": [255, 127, 80], - "cornflowerblue": [100, 149, 237], - "cornsilk": [255, 248, 220], - "crimson": [220, 20, 60], - "cyan": [0, 255, 255], - "darkblue": [0, 0, 139], - "darkcyan": [0, 139, 139], - "darkgoldenrod": [184, 134, 11], - "darkgray": [169, 169, 169], - "darkgreen": [0, 100, 0], - "darkgrey": [169, 169, 169], - "darkkhaki": [189, 183, 107], - "darkmagenta": [139, 0, 139], - "darkolivegreen": [85, 107, 47], - "darkorange": [255, 140, 0], - "darkorchid": [153, 50, 204], - "darkred": [139, 0, 0], - "darksalmon": [233, 150, 122], - "darkseagreen": [143, 188, 143], - "darkslateblue": [72, 61, 139], - "darkslategray": [47, 79, 79], - "darkslategrey": [47, 79, 79], - "darkturquoise": [0, 206, 209], - "darkviolet": [148, 0, 211], - "deeppink": [255, 20, 147], - "deepskyblue": [0, 191, 255], - "dimgray": [105, 105, 105], - "dimgrey": [105, 105, 105], - "dodgerblue": [30, 144, 255], - "firebrick": [178, 34, 34], - "floralwhite": [255, 250, 240], - "forestgreen": [34, 139, 34], - "fuchsia": [255, 0, 255], - "gainsboro": [220, 220, 220], - "ghostwhite": [248, 248, 255], - "gold": [255, 215, 0], - "goldenrod": [218, 165, 32], - "gray": [128, 128, 128], - "green": [0, 128, 0], - "greenyellow": [173, 255, 47], - "grey": [128, 128, 128], - "honeydew": [240, 255, 240], - "hotpink": [255, 105, 180], - "indianred": [205, 92, 92], - "indigo": [75, 0, 130], - "ivory": [255, 255, 240], - "khaki": [240, 230, 140], - "lavender": [230, 230, 250], - "lavenderblush": [255, 240, 245], - "lawngreen": [124, 252, 0], - "lemonchiffon": [255, 250, 205], - "lightblue": [173, 216, 230], - "lightcoral": [240, 128, 128], - "lightcyan": [224, 255, 255], - "lightgoldenrodyellow": [250, 250, 210], - "lightgray": [211, 211, 211], - "lightgreen": [144, 238, 144], - "lightgrey": [211, 211, 211], - "lightpink": [255, 182, 193], - "lightsalmon": [255, 160, 122], - "lightseagreen": [32, 178, 170], - "lightskyblue": [135, 206, 250], - "lightslategray": [119, 136, 153], - "lightslategrey": [119, 136, 153], - "lightsteelblue": [176, 196, 222], - "lightyellow": [255, 255, 224], - "lime": [0, 255, 0], - "limegreen": [50, 205, 50], - "linen": [250, 240, 230], - "magenta": [255, 0, 255], - "maroon": [128, 0, 0], - "mediumaquamarine": [102, 205, 170], - "mediumblue": [0, 0, 205], - "mediumorchid": [186, 85, 211], - "mediumpurple": [147, 112, 219], - "mediumseagreen": [60, 179, 113], - "mediumslateblue": [123, 104, 238], - "mediumspringgreen": [0, 250, 154], - "mediumturquoise": [72, 209, 204], - "mediumvioletred": [199, 21, 133], - "midnightblue": [25, 25, 112], - "mintcream": [245, 255, 250], - "mistyrose": [255, 228, 225], - "moccasin": [255, 228, 181], - "navajowhite": [255, 222, 173], - "navy": [0, 0, 128], - "oldlace": [253, 245, 230], - "olive": [128, 128, 0], - "olivedrab": [107, 142, 35], - "orange": [255, 165, 0], - "orangered": [255, 69, 0], - "orchid": [218, 112, 214], - "palegoldenrod": [238, 232, 170], - "palegreen": [152, 251, 152], - "paleturquoise": [175, 238, 238], - "palevioletred": [219, 112, 147], - "papayawhip": [255, 239, 213], - "peachpuff": [255, 218, 185], - "peru": [205, 133, 63], - "pink": [255, 192, 203], - "plum": [221, 160, 221], - "powderblue": [176, 224, 230], - "purple": [128, 0, 128], - "rebeccapurple": [102, 51, 153], - "red": [255, 0, 0], - "rosybrown": [188, 143, 143], - "royalblue": [65, 105, 225], - "saddlebrown": [139, 69, 19], - "salmon": [250, 128, 114], - "sandybrown": [244, 164, 96], - "seagreen": [46, 139, 87], - "seashell": [255, 245, 238], - "sienna": [160, 82, 45], - "silver": [192, 192, 192], - "skyblue": [135, 206, 235], - "slateblue": [106, 90, 205], - "slategray": [112, 128, 144], - "slategrey": [112, 128, 144], - "snow": [255, 250, 250], - "springgreen": [0, 255, 127], - "steelblue": [70, 130, 180], - "tan": [210, 180, 140], - "teal": [0, 128, 128], - "thistle": [216, 191, 216], - "tomato": [255, 99, 71], - "turquoise": [64, 224, 208], - "violet": [238, 130, 238], - "wheat": [245, 222, 179], - "white": [255, 255, 255], - "whitesmoke": [245, 245, 245], - "yellow": [255, 255, 0], - "yellowgreen": [154, 205, 50] -}; +'use strict' + +module.exports = { + "aliceblue": [240, 248, 255], + "antiquewhite": [250, 235, 215], + "aqua": [0, 255, 255], + "aquamarine": [127, 255, 212], + "azure": [240, 255, 255], + "beige": [245, 245, 220], + "bisque": [255, 228, 196], + "black": [0, 0, 0], + "blanchedalmond": [255, 235, 205], + "blue": [0, 0, 255], + "blueviolet": [138, 43, 226], + "brown": [165, 42, 42], + "burlywood": [222, 184, 135], + "cadetblue": [95, 158, 160], + "chartreuse": [127, 255, 0], + "chocolate": [210, 105, 30], + "coral": [255, 127, 80], + "cornflowerblue": [100, 149, 237], + "cornsilk": [255, 248, 220], + "crimson": [220, 20, 60], + "cyan": [0, 255, 255], + "darkblue": [0, 0, 139], + "darkcyan": [0, 139, 139], + "darkgoldenrod": [184, 134, 11], + "darkgray": [169, 169, 169], + "darkgreen": [0, 100, 0], + "darkgrey": [169, 169, 169], + "darkkhaki": [189, 183, 107], + "darkmagenta": [139, 0, 139], + "darkolivegreen": [85, 107, 47], + "darkorange": [255, 140, 0], + "darkorchid": [153, 50, 204], + "darkred": [139, 0, 0], + "darksalmon": [233, 150, 122], + "darkseagreen": [143, 188, 143], + "darkslateblue": [72, 61, 139], + "darkslategray": [47, 79, 79], + "darkslategrey": [47, 79, 79], + "darkturquoise": [0, 206, 209], + "darkviolet": [148, 0, 211], + "deeppink": [255, 20, 147], + "deepskyblue": [0, 191, 255], + "dimgray": [105, 105, 105], + "dimgrey": [105, 105, 105], + "dodgerblue": [30, 144, 255], + "firebrick": [178, 34, 34], + "floralwhite": [255, 250, 240], + "forestgreen": [34, 139, 34], + "fuchsia": [255, 0, 255], + "gainsboro": [220, 220, 220], + "ghostwhite": [248, 248, 255], + "gold": [255, 215, 0], + "goldenrod": [218, 165, 32], + "gray": [128, 128, 128], + "green": [0, 128, 0], + "greenyellow": [173, 255, 47], + "grey": [128, 128, 128], + "honeydew": [240, 255, 240], + "hotpink": [255, 105, 180], + "indianred": [205, 92, 92], + "indigo": [75, 0, 130], + "ivory": [255, 255, 240], + "khaki": [240, 230, 140], + "lavender": [230, 230, 250], + "lavenderblush": [255, 240, 245], + "lawngreen": [124, 252, 0], + "lemonchiffon": [255, 250, 205], + "lightblue": [173, 216, 230], + "lightcoral": [240, 128, 128], + "lightcyan": [224, 255, 255], + "lightgoldenrodyellow": [250, 250, 210], + "lightgray": [211, 211, 211], + "lightgreen": [144, 238, 144], + "lightgrey": [211, 211, 211], + "lightpink": [255, 182, 193], + "lightsalmon": [255, 160, 122], + "lightseagreen": [32, 178, 170], + "lightskyblue": [135, 206, 250], + "lightslategray": [119, 136, 153], + "lightslategrey": [119, 136, 153], + "lightsteelblue": [176, 196, 222], + "lightyellow": [255, 255, 224], + "lime": [0, 255, 0], + "limegreen": [50, 205, 50], + "linen": [250, 240, 230], + "magenta": [255, 0, 255], + "maroon": [128, 0, 0], + "mediumaquamarine": [102, 205, 170], + "mediumblue": [0, 0, 205], + "mediumorchid": [186, 85, 211], + "mediumpurple": [147, 112, 219], + "mediumseagreen": [60, 179, 113], + "mediumslateblue": [123, 104, 238], + "mediumspringgreen": [0, 250, 154], + "mediumturquoise": [72, 209, 204], + "mediumvioletred": [199, 21, 133], + "midnightblue": [25, 25, 112], + "mintcream": [245, 255, 250], + "mistyrose": [255, 228, 225], + "moccasin": [255, 228, 181], + "navajowhite": [255, 222, 173], + "navy": [0, 0, 128], + "oldlace": [253, 245, 230], + "olive": [128, 128, 0], + "olivedrab": [107, 142, 35], + "orange": [255, 165, 0], + "orangered": [255, 69, 0], + "orchid": [218, 112, 214], + "palegoldenrod": [238, 232, 170], + "palegreen": [152, 251, 152], + "paleturquoise": [175, 238, 238], + "palevioletred": [219, 112, 147], + "papayawhip": [255, 239, 213], + "peachpuff": [255, 218, 185], + "peru": [205, 133, 63], + "pink": [255, 192, 203], + "plum": [221, 160, 221], + "powderblue": [176, 224, 230], + "purple": [128, 0, 128], + "rebeccapurple": [102, 51, 153], + "red": [255, 0, 0], + "rosybrown": [188, 143, 143], + "royalblue": [65, 105, 225], + "saddlebrown": [139, 69, 19], + "salmon": [250, 128, 114], + "sandybrown": [244, 164, 96], + "seagreen": [46, 139, 87], + "seashell": [255, 245, 238], + "sienna": [160, 82, 45], + "silver": [192, 192, 192], + "skyblue": [135, 206, 235], + "slateblue": [106, 90, 205], + "slategray": [112, 128, 144], + "slategrey": [112, 128, 144], + "snow": [255, 250, 250], + "springgreen": [0, 255, 127], + "steelblue": [70, 130, 180], + "tan": [210, 180, 140], + "teal": [0, 128, 128], + "thistle": [216, 191, 216], + "tomato": [255, 99, 71], + "turquoise": [64, 224, 208], + "violet": [238, 130, 238], + "wheat": [245, 222, 179], + "white": [255, 255, 255], + "whitesmoke": [245, 245, 245], + "yellow": [255, 255, 0], + "yellowgreen": [154, 205, 50] +}; diff --git a/tools/node_modules/eslint/node_modules/cli-width/.nyc_output/00ef1b3d-3687-482b-8d03-de2f76b58f54.json b/tools/node_modules/eslint/node_modules/cli-width/.nyc_output/00ef1b3d-3687-482b-8d03-de2f76b58f54.json new file mode 100644 index 00000000000000..c275decd2d23a7 --- /dev/null +++ b/tools/node_modules/eslint/node_modules/cli-width/.nyc_output/00ef1b3d-3687-482b-8d03-de2f76b58f54.json @@ -0,0 +1 @@ +{"/Users/ilya/maintained/cli-width/index.js":{"path":"/Users/ilya/maintained/cli-width/index.js","statementMap":{"0":{"start":{"line":3,"column":0},"end":{"line":3,"column":36}},"1":{"start":{"line":6,"column":20},"end":{"line":10,"column":3}},"2":{"start":{"line":12,"column":2},"end":{"line":14,"column":3}},"3":{"start":{"line":13,"column":4},"end":{"line":13,"column":23}},"4":{"start":{"line":16,"column":2},"end":{"line":20,"column":5}},"5":{"start":{"line":17,"column":4},"end":{"line":19,"column":5}},"6":{"start":{"line":18,"column":6},"end":{"line":18,"column":38}},"7":{"start":{"line":22,"column":2},"end":{"line":22,"column":17}},"8":{"start":{"line":26,"column":13},"end":{"line":26,"column":35}},"9":{"start":{"line":28,"column":2},"end":{"line":30,"column":3}},"10":{"start":{"line":29,"column":4},"end":{"line":29,"column":63}},"11":{"start":{"line":32,"column":2},"end":{"line":34,"column":3}},"12":{"start":{"line":33,"column":4},"end":{"line":33,"column":60}},"13":{"start":{"line":36,"column":2},"end":{"line":38,"column":3}},"14":{"start":{"line":37,"column":4},"end":{"line":37,"column":31}},"15":{"start":{"line":40,"column":2},"end":{"line":46,"column":3}},"16":{"start":{"line":41,"column":16},"end":{"line":41,"column":51}},"17":{"start":{"line":43,"column":4},"end":{"line":45,"column":5}},"18":{"start":{"line":44,"column":6},"end":{"line":44,"column":19}},"19":{"start":{"line":48,"column":2},"end":{"line":48,"column":27}}},"fnMap":{"0":{"name":"normalizeOpts","decl":{"start":{"line":5,"column":9},"end":{"line":5,"column":22}},"loc":{"start":{"line":5,"column":32},"end":{"line":23,"column":1}},"line":5},"1":{"name":"(anonymous_1)","decl":{"start":{"line":16,"column":35},"end":{"line":16,"column":36}},"loc":{"start":{"line":16,"column":50},"end":{"line":20,"column":3}},"line":16},"2":{"name":"cliWidth","decl":{"start":{"line":25,"column":9},"end":{"line":25,"column":17}},"loc":{"start":{"line":25,"column":27},"end":{"line":49,"column":1}},"line":25}},"branchMap":{"0":{"loc":{"start":{"line":12,"column":2},"end":{"line":14,"column":3}},"type":"if","locations":[{"start":{"line":12,"column":2},"end":{"line":14,"column":3}},{"start":{"line":12,"column":2},"end":{"line":14,"column":3}}],"line":12},"1":{"loc":{"start":{"line":17,"column":4},"end":{"line":19,"column":5}},"type":"if","locations":[{"start":{"line":17,"column":4},"end":{"line":19,"column":5}},{"start":{"line":17,"column":4},"end":{"line":19,"column":5}}],"line":17},"2":{"loc":{"start":{"line":28,"column":2},"end":{"line":30,"column":3}},"type":"if","locations":[{"start":{"line":28,"column":2},"end":{"line":30,"column":3}},{"start":{"line":28,"column":2},"end":{"line":30,"column":3}}],"line":28},"3":{"loc":{"start":{"line":29,"column":11},"end":{"line":29,"column":62}},"type":"binary-expr","locations":[{"start":{"line":29,"column":11},"end":{"line":29,"column":41}},{"start":{"line":29,"column":45},"end":{"line":29,"column":62}}],"line":29},"4":{"loc":{"start":{"line":32,"column":2},"end":{"line":34,"column":3}},"type":"if","locations":[{"start":{"line":32,"column":2},"end":{"line":34,"column":3}},{"start":{"line":32,"column":2},"end":{"line":34,"column":3}}],"line":32},"5":{"loc":{"start":{"line":33,"column":11},"end":{"line":33,"column":59}},"type":"binary-expr","locations":[{"start":{"line":33,"column":11},"end":{"line":33,"column":38}},{"start":{"line":33,"column":42},"end":{"line":33,"column":59}}],"line":33},"6":{"loc":{"start":{"line":36,"column":2},"end":{"line":38,"column":3}},"type":"if","locations":[{"start":{"line":36,"column":2},"end":{"line":38,"column":3}},{"start":{"line":36,"column":2},"end":{"line":38,"column":3}}],"line":36},"7":{"loc":{"start":{"line":40,"column":2},"end":{"line":46,"column":3}},"type":"if","locations":[{"start":{"line":40,"column":2},"end":{"line":46,"column":3}},{"start":{"line":40,"column":2},"end":{"line":46,"column":3}}],"line":40},"8":{"loc":{"start":{"line":43,"column":4},"end":{"line":45,"column":5}},"type":"if","locations":[{"start":{"line":43,"column":4},"end":{"line":45,"column":5}},{"start":{"line":43,"column":4},"end":{"line":45,"column":5}}],"line":43},"9":{"loc":{"start":{"line":43,"column":8},"end":{"line":43,"column":36}},"type":"binary-expr","locations":[{"start":{"line":43,"column":8},"end":{"line":43,"column":21}},{"start":{"line":43,"column":25},"end":{"line":43,"column":36}}],"line":43}},"s":{"0":1,"1":11,"2":11,"3":5,"4":6,"5":18,"6":12,"7":6,"8":11,"9":11,"10":3,"11":8,"12":3,"13":5,"14":1,"15":4,"16":2,"17":2,"18":1,"19":3},"f":{"0":11,"1":18,"2":11},"b":{"0":[5,6],"1":[12,6],"2":[3,8],"3":[3,1],"4":[3,5],"5":[3,1],"6":[1,4],"7":[2,2],"8":[1,1],"9":[2,1]},"_coverageSchema":"1a1c01bbd47fc00a2c39e90264f33305004495a9","hash":"a4d7f0a30376f059a5bc5bb60422e8b1332adf0c","contentHash":"1ab1e2def09289f7630132524d4d3929b81fe2db9a3f07e64865500b9c42e817"}} \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/cli-width/.nyc_output/processinfo/00ef1b3d-3687-482b-8d03-de2f76b58f54.json b/tools/node_modules/eslint/node_modules/cli-width/.nyc_output/processinfo/00ef1b3d-3687-482b-8d03-de2f76b58f54.json new file mode 100644 index 00000000000000..10921d66e857a7 --- /dev/null +++ b/tools/node_modules/eslint/node_modules/cli-width/.nyc_output/processinfo/00ef1b3d-3687-482b-8d03-de2f76b58f54.json @@ -0,0 +1 @@ +{"parent":null,"pid":4489,"argv":["/Users/ilya/.volta/tools/image/node/12.16.0/6.13.4/bin/node","/Users/ilya/maintained/cli-width/test"],"execArgv":[],"cwd":"/Users/ilya/maintained/cli-width","time":1586875876791,"ppid":4487,"coverageFilename":"/Users/ilya/maintained/cli-width/.nyc_output/00ef1b3d-3687-482b-8d03-de2f76b58f54.json","externalId":"","uuid":"00ef1b3d-3687-482b-8d03-de2f76b58f54","files":["/Users/ilya/maintained/cli-width/index.js"]} \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/cli-width/.nyc_output/processinfo/index.json b/tools/node_modules/eslint/node_modules/cli-width/.nyc_output/processinfo/index.json new file mode 100644 index 00000000000000..7f9a443d80d22a --- /dev/null +++ b/tools/node_modules/eslint/node_modules/cli-width/.nyc_output/processinfo/index.json @@ -0,0 +1 @@ +{"processes":{"00ef1b3d-3687-482b-8d03-de2f76b58f54":{"parent":null,"children":[]}},"files":{"/Users/ilya/maintained/cli-width/index.js":["00ef1b3d-3687-482b-8d03-de2f76b58f54"]},"externalIds":{}} \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/espree/README.md b/tools/node_modules/eslint/node_modules/espree/README.md index a03d1c3ef402fa..988575d77f0045 100644 --- a/tools/node_modules/eslint/node_modules/espree/README.md +++ b/tools/node_modules/eslint/node_modules/espree/README.md @@ -23,14 +23,101 @@ const espree = require("espree"); const ast = espree.parse(code); ``` -There is a second argument to `parse()` that allows you to specify various options: +## API + +### `parse()` + +`parse` parses the given code and returns a abstract syntax tree (AST). It takes two paramenter. + +- `code` [string]() - the code which needs to be parsed. +- `options (Optional)` [Object]() - read more about this [here](#options) ```javascript const espree = require("espree"); -// Optional second options argument with the following default settings -const ast = espree.parse(code, { +const ast = espree.parse(code, options); +``` + +**Example :** + +```js +const ast = espree.parse('let foo = "bar"', { ecmaVersion: 6 }); +console.log(ast); +``` + +
Output +

+ +``` +Node { + type: 'Program', + start: 0, + end: 15, + body: [ + Node { + type: 'VariableDeclaration', + start: 0, + end: 15, + declarations: [Array], + kind: 'let' + } + ], + sourceType: 'script' +} +``` + +

+
+ +### `tokenize()` + +`tokenize` returns the tokens of a give code. It takes two paramenter. + +- `code` [string]() - the code which needs to be parsed. +- `options (Optional)` [Object]() - read more about this [here](#options) + +Even if `options` is empty or undefined or `options.tokens` is `false`, it assigns it to `true` in order to get the `tokens` array + +**Example :** + +```js +const tokens = espree.tokenize('let foo = "bar"', { ecmaVersion: 6 }); +console.log(tokens); +``` + +
Output +

+ +``` +Token { type: 'Keyword', value: 'let', start: 0, end: 3 }, +Token { type: 'Identifier', value: 'foo', start: 4, end: 7 }, +Token { type: 'Punctuator', value: '=', start: 8, end: 9 }, +Token { type: 'String', value: '"bar"', start: 10, end: 15 } +``` + +

+
+ +### `version` + +Returns the current `espree` version + +### `VisitorKeys` + +Returns all visitor keys for traversing the AST from [eslint-visitor-keys](https://github.com/eslint/eslint-visitor-keys) + +### `latestEcmaVersion` + +Returns the latest ECMAScript supported by `espree` + +### `supportedEcmaVersions` + +Returns an array of all supported ECMAScript version + +## Options +```js +const options = { // attach range information to each node range: false, @@ -62,7 +149,7 @@ const ast = espree.parse(code, { // enable implied strict mode (if ecmaVersion >= 5) impliedStrict: false } -}); +} ``` ## Esprima Compatibility Going Forward diff --git a/tools/node_modules/eslint/node_modules/espree/package.json b/tools/node_modules/eslint/node_modules/espree/package.json index d22f11891bdd84..5f7f545e8785a3 100644 --- a/tools/node_modules/eslint/node_modules/espree/package.json +++ b/tools/node_modules/eslint/node_modules/espree/package.json @@ -33,7 +33,7 @@ "unicode-6.3.0": "^0.7.5" }, "engines": { - "node": ">=6.0.0" + "node": "^10.12.0 || >=12.0.0" }, "files": [ "lib", @@ -64,7 +64,8 @@ "generate-release": "eslint-generate-release", "lint": "node Makefile.js lint", "publish-release": "eslint-publish-release", + "sync-docs": "node Makefile.js docs", "test": "npm run-script lint && node Makefile.js test" }, - "version": "6.2.1" + "version": "7.0.0" } \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/esquery/dist/esquery.esm.js b/tools/node_modules/eslint/node_modules/esquery/dist/esquery.esm.js index aa23d09f79dd9f..88abe0ffb91100 100644 --- a/tools/node_modules/eslint/node_modules/esquery/dist/esquery.esm.js +++ b/tools/node_modules/eslint/node_modules/esquery/dist/esquery.esm.js @@ -96,16 +96,16 @@ var estraverse = createCommonjsModule(function (module, exports) { /* Copyright (C) 2012-2013 Yusuke Suzuki Copyright (C) 2012 Ariya Hidayat - + 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. - + 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 diff --git a/tools/node_modules/eslint/node_modules/esquery/dist/esquery.js b/tools/node_modules/eslint/node_modules/esquery/dist/esquery.js index 700b4ff054b1fe..e2c80afc134141 100644 --- a/tools/node_modules/eslint/node_modules/esquery/dist/esquery.js +++ b/tools/node_modules/eslint/node_modules/esquery/dist/esquery.js @@ -95,23 +95,23 @@ var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; function createCommonjsModule(fn, module) { - return module = { exports: {} }, fn(module, module.exports), module.exports; + return module = { exports: {} }, fn(module, module.exports), module.exports; } var estraverse = createCommonjsModule(function (module, exports) { /* Copyright (C) 2012-2013 Yusuke Suzuki Copyright (C) 2012 Ariya Hidayat - + 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. - + 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 diff --git a/tools/node_modules/eslint/node_modules/esquery/node_modules/estraverse/estraverse.js b/tools/node_modules/eslint/node_modules/esquery/node_modules/estraverse/estraverse.js index 1bd3a921263580..b7db020775eb2d 100644 --- a/tools/node_modules/eslint/node_modules/esquery/node_modules/estraverse/estraverse.js +++ b/tools/node_modules/eslint/node_modules/esquery/node_modules/estraverse/estraverse.js @@ -388,7 +388,7 @@ function isProperty(nodeType, key) { return (nodeType === Syntax.ObjectExpression || nodeType === Syntax.ObjectPattern) && 'properties' === key; } - + function candidateExistsInLeaveList(leavelist, candidate) { for (var i = leavelist.length - 1; i >= 0; --i) { if (leavelist[i].node === candidate) { diff --git a/tools/node_modules/eslint/node_modules/inquirer/node_modules/ansi-styles/index.js b/tools/node_modules/eslint/node_modules/inquirer/node_modules/ansi-styles/index.js new file mode 100644 index 00000000000000..5d82581a13f990 --- /dev/null +++ b/tools/node_modules/eslint/node_modules/inquirer/node_modules/ansi-styles/index.js @@ -0,0 +1,163 @@ +'use strict'; + +const wrapAnsi16 = (fn, offset) => (...args) => { + const code = fn(...args); + return `\u001B[${code + offset}m`; +}; + +const wrapAnsi256 = (fn, offset) => (...args) => { + const code = fn(...args); + return `\u001B[${38 + offset};5;${code}m`; +}; + +const wrapAnsi16m = (fn, offset) => (...args) => { + const rgb = fn(...args); + return `\u001B[${38 + offset};2;${rgb[0]};${rgb[1]};${rgb[2]}m`; +}; + +const ansi2ansi = n => n; +const rgb2rgb = (r, g, b) => [r, g, b]; + +const setLazyProperty = (object, property, get) => { + Object.defineProperty(object, property, { + get: () => { + const value = get(); + + Object.defineProperty(object, property, { + value, + enumerable: true, + configurable: true + }); + + return value; + }, + enumerable: true, + configurable: true + }); +}; + +/** @type {typeof import('color-convert')} */ +let colorConvert; +const makeDynamicStyles = (wrap, targetSpace, identity, isBackground) => { + if (colorConvert === undefined) { + colorConvert = require('color-convert'); + } + + const offset = isBackground ? 10 : 0; + const styles = {}; + + for (const [sourceSpace, suite] of Object.entries(colorConvert)) { + const name = sourceSpace === 'ansi16' ? 'ansi' : sourceSpace; + if (sourceSpace === targetSpace) { + styles[name] = wrap(identity, offset); + } else if (typeof suite === 'object') { + styles[name] = wrap(suite[targetSpace], offset); + } + } + + return styles; +}; + +function assembleStyles() { + const codes = new Map(); + const styles = { + modifier: { + reset: [0, 0], + // 21 isn't widely supported and 22 does the same thing + bold: [1, 22], + dim: [2, 22], + italic: [3, 23], + underline: [4, 24], + inverse: [7, 27], + hidden: [8, 28], + strikethrough: [9, 29] + }, + color: { + black: [30, 39], + red: [31, 39], + green: [32, 39], + yellow: [33, 39], + blue: [34, 39], + magenta: [35, 39], + cyan: [36, 39], + white: [37, 39], + + // Bright color + blackBright: [90, 39], + redBright: [91, 39], + greenBright: [92, 39], + yellowBright: [93, 39], + blueBright: [94, 39], + magentaBright: [95, 39], + cyanBright: [96, 39], + whiteBright: [97, 39] + }, + bgColor: { + bgBlack: [40, 49], + bgRed: [41, 49], + bgGreen: [42, 49], + bgYellow: [43, 49], + bgBlue: [44, 49], + bgMagenta: [45, 49], + bgCyan: [46, 49], + bgWhite: [47, 49], + + // Bright color + bgBlackBright: [100, 49], + bgRedBright: [101, 49], + bgGreenBright: [102, 49], + bgYellowBright: [103, 49], + bgBlueBright: [104, 49], + bgMagentaBright: [105, 49], + bgCyanBright: [106, 49], + bgWhiteBright: [107, 49] + } + }; + + // Alias bright black as gray (and grey) + styles.color.gray = styles.color.blackBright; + styles.bgColor.bgGray = styles.bgColor.bgBlackBright; + styles.color.grey = styles.color.blackBright; + styles.bgColor.bgGrey = styles.bgColor.bgBlackBright; + + for (const [groupName, group] of Object.entries(styles)) { + for (const [styleName, style] of Object.entries(group)) { + styles[styleName] = { + open: `\u001B[${style[0]}m`, + close: `\u001B[${style[1]}m` + }; + + group[styleName] = styles[styleName]; + + codes.set(style[0], style[1]); + } + + Object.defineProperty(styles, groupName, { + value: group, + enumerable: false + }); + } + + Object.defineProperty(styles, 'codes', { + value: codes, + enumerable: false + }); + + styles.color.close = '\u001B[39m'; + styles.bgColor.close = '\u001B[49m'; + + setLazyProperty(styles.color, 'ansi', () => makeDynamicStyles(wrapAnsi16, 'ansi16', ansi2ansi, false)); + setLazyProperty(styles.color, 'ansi256', () => makeDynamicStyles(wrapAnsi256, 'ansi256', ansi2ansi, false)); + setLazyProperty(styles.color, 'ansi16m', () => makeDynamicStyles(wrapAnsi16m, 'rgb', rgb2rgb, false)); + setLazyProperty(styles.bgColor, 'ansi', () => makeDynamicStyles(wrapAnsi16, 'ansi16', ansi2ansi, true)); + setLazyProperty(styles.bgColor, 'ansi256', () => makeDynamicStyles(wrapAnsi256, 'ansi256', ansi2ansi, true)); + setLazyProperty(styles.bgColor, 'ansi16m', () => makeDynamicStyles(wrapAnsi16m, 'rgb', rgb2rgb, true)); + + return styles; +} + +// Make the export immutable +Object.defineProperty(module, 'exports', { + enumerable: true, + get: assembleStyles +}); diff --git a/tools/node_modules/eslint/node_modules/inquirer/node_modules/ansi-styles/license b/tools/node_modules/eslint/node_modules/inquirer/node_modules/ansi-styles/license new file mode 100644 index 00000000000000..e7af2f77107d73 --- /dev/null +++ b/tools/node_modules/eslint/node_modules/inquirer/node_modules/ansi-styles/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +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. diff --git a/tools/node_modules/eslint/node_modules/inquirer/node_modules/ansi-styles/package.json b/tools/node_modules/eslint/node_modules/inquirer/node_modules/ansi-styles/package.json new file mode 100644 index 00000000000000..2b0aef0e49e6e8 --- /dev/null +++ b/tools/node_modules/eslint/node_modules/inquirer/node_modules/ansi-styles/package.json @@ -0,0 +1,66 @@ +{ + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "bugs": { + "url": "https://github.com/chalk/ansi-styles/issues" + }, + "bundleDependencies": false, + "dependencies": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + }, + "deprecated": false, + "description": "ANSI escape codes for styling strings in the terminal", + "devDependencies": { + "@types/color-convert": "^1.9.0", + "ava": "^2.3.0", + "svg-term-cli": "^2.1.1", + "tsd": "^0.11.0", + "xo": "^0.25.3" + }, + "engines": { + "node": ">=8" + }, + "files": [ + "index.js", + "index.d.ts" + ], + "funding": "https://github.com/chalk/ansi-styles?sponsor=1", + "homepage": "https://github.com/chalk/ansi-styles#readme", + "keywords": [ + "ansi", + "styles", + "color", + "colour", + "colors", + "terminal", + "console", + "cli", + "string", + "tty", + "escape", + "formatting", + "rgb", + "256", + "shell", + "xterm", + "log", + "logging", + "command-line", + "text" + ], + "license": "MIT", + "name": "ansi-styles", + "repository": { + "type": "git", + "url": "git+https://github.com/chalk/ansi-styles.git" + }, + "scripts": { + "screenshot": "svg-term --command='node screenshot' --out=screenshot.svg --padding=3 --width=55 --height=3 --at=1000 --no-cursor", + "test": "xo && ava && tsd" + }, + "version": "4.2.1" +} \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/inquirer/node_modules/ansi-styles/readme.md b/tools/node_modules/eslint/node_modules/inquirer/node_modules/ansi-styles/readme.md new file mode 100644 index 00000000000000..2a1ef654667d3f --- /dev/null +++ b/tools/node_modules/eslint/node_modules/inquirer/node_modules/ansi-styles/readme.md @@ -0,0 +1,158 @@ +# ansi-styles [![Build Status](https://travis-ci.org/chalk/ansi-styles.svg?branch=master)](https://travis-ci.org/chalk/ansi-styles) + +> [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors_and_Styles) for styling strings in the terminal + +You probably want the higher-level [chalk](https://github.com/chalk/chalk) module for styling your strings. + + + +## Install + +``` +$ npm install ansi-styles +``` + +## Usage + +```js +const style = require('ansi-styles'); + +console.log(`${style.green.open}Hello world!${style.green.close}`); + + +// Color conversion between 16/256/truecolor +// NOTE: If conversion goes to 16 colors or 256 colors, the original color +// may be degraded to fit that color palette. This means terminals +// that do not support 16 million colors will best-match the +// original color. +console.log(style.bgColor.ansi.hsl(120, 80, 72) + 'Hello world!' + style.bgColor.close); +console.log(style.color.ansi256.rgb(199, 20, 250) + 'Hello world!' + style.color.close); +console.log(style.color.ansi16m.hex('#abcdef') + 'Hello world!' + style.color.close); +``` + +## API + +Each style has an `open` and `close` property. + +## Styles + +### Modifiers + +- `reset` +- `bold` +- `dim` +- `italic` *(Not widely supported)* +- `underline` +- `inverse` +- `hidden` +- `strikethrough` *(Not widely supported)* + +### Colors + +- `black` +- `red` +- `green` +- `yellow` +- `blue` +- `magenta` +- `cyan` +- `white` +- `blackBright` (alias: `gray`, `grey`) +- `redBright` +- `greenBright` +- `yellowBright` +- `blueBright` +- `magentaBright` +- `cyanBright` +- `whiteBright` + +### Background colors + +- `bgBlack` +- `bgRed` +- `bgGreen` +- `bgYellow` +- `bgBlue` +- `bgMagenta` +- `bgCyan` +- `bgWhite` +- `bgBlackBright` (alias: `bgGray`, `bgGrey`) +- `bgRedBright` +- `bgGreenBright` +- `bgYellowBright` +- `bgBlueBright` +- `bgMagentaBright` +- `bgCyanBright` +- `bgWhiteBright` + +## Advanced usage + +By default, you get a map of styles, but the styles are also available as groups. They are non-enumerable so they don't show up unless you access them explicitly. This makes it easier to expose only a subset in a higher-level module. + +- `style.modifier` +- `style.color` +- `style.bgColor` + +###### Example + +```js +console.log(style.color.green.open); +``` + +Raw escape codes (i.e. without the CSI escape prefix `\u001B[` and render mode postfix `m`) are available under `style.codes`, which returns a `Map` with the open codes as keys and close codes as values. + +###### Example + +```js +console.log(style.codes.get(36)); +//=> 39 +``` + +## [256 / 16 million (TrueColor) support](https://gist.github.com/XVilka/8346728) + +`ansi-styles` uses the [`color-convert`](https://github.com/Qix-/color-convert) package to allow for converting between various colors and ANSI escapes, with support for 256 and 16 million colors. + +The following color spaces from `color-convert` are supported: + +- `rgb` +- `hex` +- `keyword` +- `hsl` +- `hsv` +- `hwb` +- `ansi` +- `ansi256` + +To use these, call the associated conversion function with the intended output, for example: + +```js +style.color.ansi.rgb(100, 200, 15); // RGB to 16 color ansi foreground code +style.bgColor.ansi.rgb(100, 200, 15); // RGB to 16 color ansi background code + +style.color.ansi256.hsl(120, 100, 60); // HSL to 256 color ansi foreground code +style.bgColor.ansi256.hsl(120, 100, 60); // HSL to 256 color ansi foreground code + +style.color.ansi16m.hex('#C0FFEE'); // Hex (RGB) to 16 million color foreground code +style.bgColor.ansi16m.hex('#C0FFEE'); // Hex (RGB) to 16 million color background code +``` + +## Related + +- [ansi-escapes](https://github.com/sindresorhus/ansi-escapes) - ANSI escape codes for manipulating the terminal + +## Maintainers + +- [Sindre Sorhus](https://github.com/sindresorhus) +- [Josh Junon](https://github.com/qix-) + +--- + +
+ + Get professional support for this package with a Tidelift subscription + +
+ + Tidelift helps make open source sustainable for maintainers while giving companies
assurances about security, maintenance, and licensing for their dependencies. +
+
diff --git a/tools/node_modules/eslint/node_modules/inquirer/node_modules/chalk/license b/tools/node_modules/eslint/node_modules/inquirer/node_modules/chalk/license new file mode 100644 index 00000000000000..e7af2f77107d73 --- /dev/null +++ b/tools/node_modules/eslint/node_modules/inquirer/node_modules/chalk/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +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. diff --git a/tools/node_modules/eslint/node_modules/inquirer/node_modules/chalk/package.json b/tools/node_modules/eslint/node_modules/inquirer/node_modules/chalk/package.json new file mode 100644 index 00000000000000..b6219713cecd70 --- /dev/null +++ b/tools/node_modules/eslint/node_modules/inquirer/node_modules/chalk/package.json @@ -0,0 +1,72 @@ +{ + "bugs": { + "url": "https://github.com/chalk/chalk/issues" + }, + "bundleDependencies": false, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "deprecated": false, + "description": "Terminal string styling done right", + "devDependencies": { + "ava": "^2.4.0", + "coveralls": "^3.0.7", + "execa": "^3.2.0", + "import-fresh": "^3.1.0", + "matcha": "^0.7.0", + "nyc": "^14.1.1", + "resolve-from": "^5.0.0", + "tsd": "^0.7.4", + "xo": "^0.25.3" + }, + "engines": { + "node": ">=8" + }, + "files": [ + "source", + "index.d.ts" + ], + "homepage": "https://github.com/chalk/chalk#readme", + "keywords": [ + "color", + "colour", + "colors", + "terminal", + "console", + "cli", + "string", + "str", + "ansi", + "style", + "styles", + "tty", + "formatting", + "rgb", + "256", + "shell", + "xterm", + "log", + "logging", + "command-line", + "text" + ], + "license": "MIT", + "main": "source", + "name": "chalk", + "repository": { + "type": "git", + "url": "git+https://github.com/chalk/chalk.git" + }, + "scripts": { + "bench": "matcha benchmark.js", + "test": "xo && nyc ava && tsd" + }, + "version": "3.0.0", + "xo": { + "rules": { + "unicorn/prefer-string-slice": "off", + "unicorn/prefer-includes": "off" + } + } +} \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/inquirer/node_modules/chalk/readme.md b/tools/node_modules/eslint/node_modules/inquirer/node_modules/chalk/readme.md new file mode 100644 index 00000000000000..877cb93b7861f7 --- /dev/null +++ b/tools/node_modules/eslint/node_modules/inquirer/node_modules/chalk/readme.md @@ -0,0 +1,304 @@ +

+
+
+ Chalk +
+
+
+

+ +> Terminal string styling done right + +[![Build Status](https://travis-ci.org/chalk/chalk.svg?branch=master)](https://travis-ci.org/chalk/chalk) [![Coverage Status](https://coveralls.io/repos/github/chalk/chalk/badge.svg?branch=master)](https://coveralls.io/github/chalk/chalk?branch=master) [![npm dependents](https://badgen.net/npm/dependents/chalk)](https://www.npmjs.com/package/chalk?activeTab=dependents) [![Downloads](https://badgen.net/npm/dt/chalk)](https://www.npmjs.com/package/chalk) [![](https://img.shields.io/badge/unicorn-approved-ff69b4.svg)](https://www.youtube.com/watch?v=9auOCbH5Ns4) [![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/xojs/xo) ![TypeScript-ready](https://img.shields.io/npm/types/chalk.svg) + + + + +## Highlights + +- Expressive API +- Highly performant +- Ability to nest styles +- [256/Truecolor color support](#256-and-truecolor-color-support) +- Auto-detects color support +- Doesn't extend `String.prototype` +- Clean and focused +- Actively maintained +- [Used by ~46,000 packages](https://www.npmjs.com/browse/depended/chalk) as of October 1, 2019 + + +## Install + +```console +$ npm install chalk +``` + + +## Usage + +```js +const chalk = require('chalk'); + +console.log(chalk.blue('Hello world!')); +``` + +Chalk comes with an easy to use composable API where you just chain and nest the styles you want. + +```js +const chalk = require('chalk'); +const log = console.log; + +// Combine styled and normal strings +log(chalk.blue('Hello') + ' World' + chalk.red('!')); + +// Compose multiple styles using the chainable API +log(chalk.blue.bgRed.bold('Hello world!')); + +// Pass in multiple arguments +log(chalk.blue('Hello', 'World!', 'Foo', 'bar', 'biz', 'baz')); + +// Nest styles +log(chalk.red('Hello', chalk.underline.bgBlue('world') + '!')); + +// Nest styles of the same type even (color, underline, background) +log(chalk.green( + 'I am a green line ' + + chalk.blue.underline.bold('with a blue substring') + + ' that becomes green again!' +)); + +// ES2015 template literal +log(` +CPU: ${chalk.red('90%')} +RAM: ${chalk.green('40%')} +DISK: ${chalk.yellow('70%')} +`); + +// ES2015 tagged template literal +log(chalk` +CPU: {red ${cpu.totalPercent}%} +RAM: {green ${ram.used / ram.total * 100}%} +DISK: {rgb(255,131,0) ${disk.used / disk.total * 100}%} +`); + +// Use RGB colors in terminal emulators that support it. +log(chalk.keyword('orange')('Yay for orange colored text!')); +log(chalk.rgb(123, 45, 67).underline('Underlined reddish color')); +log(chalk.hex('#DEADED').bold('Bold gray!')); +``` + +Easily define your own themes: + +```js +const chalk = require('chalk'); + +const error = chalk.bold.red; +const warning = chalk.keyword('orange'); + +console.log(error('Error!')); +console.log(warning('Warning!')); +``` + +Take advantage of console.log [string substitution](https://nodejs.org/docs/latest/api/console.html#console_console_log_data_args): + +```js +const name = 'Sindre'; +console.log(chalk.green('Hello %s'), name); +//=> 'Hello Sindre' +``` + + +## API + +### chalk.`